@php-wasm/logger
Advanced tools
Comparing version 0.7.1 to 0.7.3
export * from './lib/logger'; | ||
export * from './lib/log-collector'; |
320
index.js
@@ -1,1 +0,319 @@ | ||
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=function(){var o;return typeof process<"u"&&((o=process.release)==null?void 0:o.name)==="node"?"NODE":typeof window<"u"?"WEB":typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope?"WORKER":"NODE"}();if(u==="NODE"){let o=function(t){return new Promise(function(r,n){t.onload=t.onerror=function(i){t.onload=t.onerror=null,i.type==="load"?r(t.result):n(new Error("Failed to read the blob/file"))}})},e=function(){const t=new Uint8Array([1,2,3,4]),n=new File([t],"test").stream();try{return n.getReader({mode:"byob"}),!0}catch{return!1}};if(typeof File>"u"){class t extends Blob{constructor(n,i,a){super(n);let s;a!=null&&a.lastModified&&(s=new Date),(!s||isNaN(s.getFullYear()))&&(s=new Date),this.lastModifiedDate=s,this.lastModified=s.getMilliseconds(),this.name=i||""}}global.File=t}typeof Blob.prototype.arrayBuffer>"u"&&(Blob.prototype.arrayBuffer=function(){const r=new FileReader;return r.readAsArrayBuffer(this),o(r)}),typeof Blob.prototype.text>"u"&&(Blob.prototype.text=function(){const r=new FileReader;return r.readAsText(this),o(r)}),(typeof Blob.prototype.stream>"u"||!e())&&(Blob.prototype.stream=function(){let t=0;const r=this;return new ReadableStream({type:"bytes",autoAllocateChunkSize:512*1024,async pull(n){const i=n.byobRequest.view,s=await r.slice(t,t+i.byteLength).arrayBuffer(),d=new Uint8Array(s);new Uint8Array(i.buffer).set(d);const l=d.byteLength;n.byobRequest.respond(l),t+=l,t>=r.size&&n.close()}})})}if(u==="NODE"&&typeof CustomEvent>"u"){class o extends Event{constructor(t,r={}){super(t,r),this.detail=r.detail}initCustomEvent(){}}globalThis.CustomEvent=o}class c extends EventTarget{constructor(e){super(),this.fatalErrorEvent="playground-fatal-error",this.logs=[],this.windowConnected=!1,this.lastPHPLogLength=0,this.context={},this.errorLogPath="/wordpress/wp-content/debug.log",e&&(this.errorLogPath=e)}async getRequestPhpErrorLog(e){return await e.fileExists(this.errorLogPath)?await e.readFileAsText(this.errorLogPath):""}logWindowError(e){this.log(`${e.message} in ${e.filename} on line ${e.lineno}:${e.colno}`,"Error")}logUnhandledRejection(e){if(!(e!=null&&e.reason))return;const t=(e==null?void 0:e.reason.stack)??e.reason;this.log(t,"Error")}addWindowErrorListener(){this.windowConnected||typeof window>"u"||(window.addEventListener("error",this.logWindowError.bind(this)),window.addEventListener("unhandledrejection",this.logUnhandledRejection.bind(this)),window.addEventListener("rejectionhandled",this.logUnhandledRejection.bind(this)),this.windowConnected=!0)}addServiceWorkerMessageListener(){navigator.serviceWorker.addEventListener("message",e=>{var t;((t=e.data)==null?void 0:t.numberOfOpenPlaygroundTabs)!==void 0&&this.addContext({numberOfOpenPlaygroundTabs:e.data.numberOfOpenPlaygroundTabs})})}addPlaygroundRequestEndListener(e){e.addEventListener("request.end",async()=>{const t=await this.getRequestPhpErrorLog(e);t.length>this.lastPHPLogLength&&(this.logRaw(t.substring(this.lastPHPLogLength)),this.lastPHPLogLength=t.length)}),e.addEventListener("request.error",t=>{t=t,t.error&&(this.log(`${t.error.message} ${t.error.stack}`,"Fatal","PHP-WASM"),this.dispatchEvent(new CustomEvent(this.fatalErrorEvent,{detail:{logs:this.getLogs(),source:t.source}})))})}formatLogDate(e){const t=new Intl.DateTimeFormat("en-GB",{year:"numeric",month:"short",day:"2-digit",timeZone:"UTC"}).format(e).replace(/ /g,"-"),r=new Intl.DateTimeFormat("en-GB",{hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1,timeZone:"UTC",timeZoneName:"short"}).format(e);return t+" "+r}formatMessage(e,t,r){return`[${this.formatLogDate(new Date)}] ${r} ${t}: ${e}`}log(e,t,r){t===void 0&&(t="Info");const n=this.formatMessage(e,t,r??"Playground");this.logRaw(n)}logRaw(e){this.logs.push(e),console.debug(e)}getLogs(){return[...this.logs]}addContext(e){this.context={...this.context,...e}}getContext(){return{...this.context}}}const f=new c;function h(o){o.addWindowErrorListener(),o.addServiceWorkerMessageListener()}function g(o,e){o.addPlaygroundRequestEndListener(e)}function m(o){o.addEventListener("activate",()=>{o.clients.matchAll().then(e=>{const t={numberOfOpenPlaygroundTabs:e.filter(r=>r.frameType==="top-level").length};o.clients.matchAll({includeUncontrolled:!0}).then(r=>{for(const n of r)n.postMessage(t)})})})}function w(o,e){o.addEventListener(o.fatalErrorEvent,e)}exports.Logger=c;exports.addCrashListener=w;exports.collectPhpLogs=g;exports.collectWindowErrors=h;exports.logger=f;exports.reportServiceWorkerMetrics=m; | ||
const p = function() { | ||
var r; | ||
return typeof process < "u" && ((r = process.release) == null ? void 0 : r.name) === "node" ? "NODE" : typeof window < "u" ? "WEB" : ( | ||
// @ts-ignore | ||
typeof WorkerGlobalScope < "u" && // @ts-ignore | ||
self instanceof WorkerGlobalScope ? "WORKER" : "NODE" | ||
); | ||
}(); | ||
if (p === "NODE") { | ||
let r = function(t) { | ||
return new Promise(function(s, o) { | ||
t.onload = t.onerror = function(n) { | ||
t.onload = t.onerror = null, n.type === "load" ? s(t.result) : o(new Error("Failed to read the blob/file")); | ||
}; | ||
}); | ||
}, e = function() { | ||
const t = new Uint8Array([1, 2, 3, 4]), o = new File([t], "test").stream(); | ||
try { | ||
return o.getReader({ mode: "byob" }), !0; | ||
} catch { | ||
return !1; | ||
} | ||
}; | ||
if (typeof File > "u") { | ||
class t extends Blob { | ||
constructor(o, n, i) { | ||
super(o); | ||
let a; | ||
i != null && i.lastModified && (a = /* @__PURE__ */ new Date()), (!a || isNaN(a.getFullYear())) && (a = /* @__PURE__ */ new Date()), this.lastModifiedDate = a, this.lastModified = a.getMilliseconds(), this.name = n || ""; | ||
} | ||
} | ||
global.File = t; | ||
} | ||
typeof Blob.prototype.arrayBuffer > "u" && (Blob.prototype.arrayBuffer = function() { | ||
const s = new FileReader(); | ||
return s.readAsArrayBuffer(this), r(s); | ||
}), typeof Blob.prototype.text > "u" && (Blob.prototype.text = function() { | ||
const s = new FileReader(); | ||
return s.readAsText(this), r(s); | ||
}), (typeof Blob.prototype.stream > "u" || !e()) && (Blob.prototype.stream = function() { | ||
let t = 0; | ||
const s = this; | ||
return new ReadableStream({ | ||
type: "bytes", | ||
// 0.5 MB seems like a reasonable chunk size, let's adjust | ||
// this if needed. | ||
autoAllocateChunkSize: 512 * 1024, | ||
async pull(o) { | ||
const n = o.byobRequest.view, a = await s.slice( | ||
t, | ||
t + n.byteLength | ||
).arrayBuffer(), f = new Uint8Array(a); | ||
new Uint8Array(n.buffer).set(f); | ||
const c = f.byteLength; | ||
o.byobRequest.respond(c), t += c, t >= s.size && o.close(); | ||
} | ||
}); | ||
}); | ||
} | ||
if (p === "NODE" && typeof CustomEvent > "u") { | ||
class r extends Event { | ||
constructor(t, s = {}) { | ||
super(t, s), this.detail = s.detail; | ||
} | ||
initCustomEvent() { | ||
} | ||
} | ||
globalThis.CustomEvent = r; | ||
} | ||
const w = (r, ...e) => { | ||
switch (r.severity) { | ||
case "Debug": | ||
console.debug(r.message, ...e); | ||
break; | ||
case "Info": | ||
console.info(r.message, ...e); | ||
break; | ||
case "Warn": | ||
console.warn(r.message, ...e); | ||
break; | ||
case "Error": | ||
console.error(r.message, ...e); | ||
break; | ||
case "Fatal": | ||
console.error(r.message, ...e); | ||
break; | ||
default: | ||
console.log(r.message, ...e); | ||
} | ||
}, E = (r, ...e) => [ | ||
typeof r == "object" ? JSON.stringify(r) : r, | ||
...e.map((t) => JSON.stringify(t)) | ||
].join(" "), h = [], u = (r) => { | ||
h.push(r); | ||
}, b = (r) => { | ||
if (r.raw === !0) | ||
u(r.message); | ||
else { | ||
const e = L( | ||
typeof r.message == "object" ? E(r.message) : r.message, | ||
r.severity ?? "Info", | ||
r.prefix ?? "JavaScript" | ||
); | ||
u(e); | ||
} | ||
}; | ||
class v extends EventTarget { | ||
// constructor | ||
constructor(e = []) { | ||
super(), this.handlers = e, this.fatalErrorEvent = "playground-fatal-error"; | ||
} | ||
/** | ||
* Get all logs. | ||
* @returns string[] | ||
*/ | ||
getLogs() { | ||
return this.handlers.includes(b) ? [...h] : (this.error(`Logs aren't stored because the logToMemory handler isn't registered. | ||
If you're using a custom logger instance, make sure to register logToMemory handler. | ||
`), []); | ||
} | ||
/** | ||
* Log message with severity. | ||
* | ||
* @param message any | ||
* @param severity LogSeverity | ||
* @param raw boolean | ||
* @param args any | ||
*/ | ||
logMessage(e, ...t) { | ||
for (const s of this.handlers) | ||
s(e, ...t); | ||
} | ||
/** | ||
* Log message | ||
* | ||
* @param message any | ||
* @param args any | ||
*/ | ||
log(e, ...t) { | ||
this.logMessage( | ||
{ | ||
message: e, | ||
severity: void 0, | ||
prefix: "JavaScript", | ||
raw: !1 | ||
}, | ||
...t | ||
); | ||
} | ||
/** | ||
* Log debug message | ||
* | ||
* @param message any | ||
* @param args any | ||
*/ | ||
debug(e, ...t) { | ||
this.logMessage( | ||
{ | ||
message: e, | ||
severity: "Debug", | ||
prefix: "JavaScript", | ||
raw: !1 | ||
}, | ||
...t | ||
); | ||
} | ||
/** | ||
* Log info message | ||
* | ||
* @param message any | ||
* @param args any | ||
*/ | ||
info(e, ...t) { | ||
this.logMessage( | ||
{ | ||
message: e, | ||
severity: "Info", | ||
prefix: "JavaScript", | ||
raw: !1 | ||
}, | ||
...t | ||
); | ||
} | ||
/** | ||
* Log warning message | ||
* | ||
* @param message any | ||
* @param args any | ||
*/ | ||
warn(e, ...t) { | ||
this.logMessage( | ||
{ | ||
message: e, | ||
severity: "Warn", | ||
prefix: "JavaScript", | ||
raw: !1 | ||
}, | ||
...t | ||
); | ||
} | ||
/** | ||
* Log error message | ||
* | ||
* @param message any | ||
* @param args any | ||
*/ | ||
error(e, ...t) { | ||
this.logMessage( | ||
{ | ||
message: e, | ||
severity: "Error", | ||
prefix: "JavaScript", | ||
raw: !1 | ||
}, | ||
...t | ||
); | ||
} | ||
} | ||
const B = new v([b, w]), L = (r, e, t) => { | ||
const s = /* @__PURE__ */ new Date(), o = new Intl.DateTimeFormat("en-GB", { | ||
year: "numeric", | ||
month: "short", | ||
day: "2-digit", | ||
timeZone: "UTC" | ||
}).format(s).replace(/ /g, "-"), n = new Intl.DateTimeFormat("en-GB", { | ||
hour: "2-digit", | ||
minute: "2-digit", | ||
second: "2-digit", | ||
hour12: !1, | ||
timeZone: "UTC", | ||
timeZoneName: "short" | ||
}).format(s); | ||
return `[${o + " " + n}] ${t} ${e}: ${r}`; | ||
}, O = (r, e) => { | ||
r.addEventListener(r.fatalErrorEvent, e); | ||
}; | ||
let l = 0; | ||
const g = "/wordpress/wp-content/debug.log", M = async (r) => await r.fileExists(g) ? await r.readFileAsText(g) : "", P = (r, e) => { | ||
e.addEventListener("request.end", async () => { | ||
const t = await M(e); | ||
if (t.length > l) { | ||
const s = t.substring(l); | ||
r.logMessage({ | ||
message: s, | ||
raw: !0 | ||
}), l = t.length; | ||
} | ||
}), e.addEventListener("request.error", (t) => { | ||
t = t, t.error && (r.logMessage({ | ||
message: `${t.error.message} ${t.error.stack}`, | ||
severity: "Fatal", | ||
prefix: t.source === "request" ? "PHP" : "WASM Crash" | ||
}), r.dispatchEvent( | ||
new CustomEvent(r.fatalErrorEvent, { | ||
detail: { | ||
logs: r.getLogs(), | ||
source: t.source | ||
} | ||
}) | ||
)); | ||
}); | ||
}, T = (r, e) => { | ||
r.logMessage({ | ||
message: `${e.message} in ${e.filename} on line ${e.lineno}:${e.colno}`, | ||
severity: "Error" | ||
}); | ||
}, m = (r, e) => { | ||
if (!(e != null && e.reason)) | ||
return; | ||
const t = (e == null ? void 0 : e.reason.stack) ?? e.reason; | ||
r.logMessage({ | ||
message: t, | ||
severity: "Error" | ||
}); | ||
}; | ||
let d = 0; | ||
const x = (r) => { | ||
navigator.serviceWorker.addEventListener("message", (e) => { | ||
var t, s, o; | ||
((t = e.data) == null ? void 0 : t.numberOfOpenPlaygroundTabs) !== void 0 && d !== ((s = e.data) == null ? void 0 : s.numberOfOpenPlaygroundTabs) && (d = (o = e.data) == null ? void 0 : o.numberOfOpenPlaygroundTabs, r.debug( | ||
`Number of open Playground tabs is: ${d}` | ||
)); | ||
}); | ||
}; | ||
let y = !1; | ||
const S = (r) => { | ||
y || (x(r), !(typeof window > "u") && (window.addEventListener( | ||
"error", | ||
(e) => T(r, e) | ||
), window.addEventListener( | ||
"unhandledrejection", | ||
(e) => m(r, e) | ||
), window.addEventListener( | ||
"rejectionhandled", | ||
(e) => m(r, e) | ||
), y = !0)); | ||
}, k = (r) => { | ||
r.addEventListener("activate", () => { | ||
r.clients.matchAll().then((e) => { | ||
const t = { | ||
numberOfOpenPlaygroundTabs: e.filter( | ||
// Only count top-level frames to get the number of tabs. | ||
(s) => s.frameType === "top-level" | ||
).length | ||
}; | ||
for (const s of e) | ||
s.postMessage(t); | ||
}); | ||
}); | ||
}; | ||
export { | ||
v as Logger, | ||
O as addCrashListener, | ||
P as collectPhpLogs, | ||
S as collectWindowErrors, | ||
L as formatLogEntry, | ||
B as logger, | ||
k as reportServiceWorkerMetrics | ||
}; |
@@ -1,3 +0,7 @@ | ||
/// <reference lib="webworker" /> | ||
import { UniversalPHP } from '../../../universal/src/index.ts/src/lib/universal-php'; | ||
export type Log = { | ||
message: any; | ||
severity?: LogSeverity; | ||
prefix?: LogPrefix; | ||
raw?: boolean; | ||
}; | ||
/** | ||
@@ -10,3 +14,3 @@ * Log severity levels. | ||
*/ | ||
export type LogPrefix = 'Playground' | 'PHP-WASM'; | ||
export type LogPrefix = 'WASM Crash' | 'PHP' | 'JavaScript'; | ||
/** | ||
@@ -16,96 +20,54 @@ * A logger for Playground. | ||
export declare class Logger extends EventTarget { | ||
private readonly handlers; | ||
readonly fatalErrorEvent = "playground-fatal-error"; | ||
constructor(handlers?: Function[]); | ||
/** | ||
* Log messages | ||
* Get all logs. | ||
* @returns string[] | ||
*/ | ||
private logs; | ||
getLogs(): string[]; | ||
/** | ||
* Whether the window events are connected. | ||
* Log message with severity. | ||
* | ||
* @param message any | ||
* @param severity LogSeverity | ||
* @param raw boolean | ||
* @param args any | ||
*/ | ||
private windowConnected; | ||
logMessage(log: Log, ...args: any[]): void; | ||
/** | ||
* The length of the last PHP log. | ||
* Log message | ||
* | ||
* @param message any | ||
* @param args any | ||
*/ | ||
private lastPHPLogLength; | ||
log(message: any, ...args: any[]): void; | ||
/** | ||
* Context data | ||
*/ | ||
private context; | ||
/** | ||
* The path to the error log file. | ||
*/ | ||
private errorLogPath; | ||
constructor(errorLogPath?: string); | ||
/** | ||
* Read the WordPress debug.log file and return its content. | ||
* Log debug message | ||
* | ||
* @param UniversalPHP playground instance | ||
* @returns string The content of the debug.log file | ||
* @param message any | ||
* @param args any | ||
*/ | ||
private getRequestPhpErrorLog; | ||
debug(message: any, ...args: any[]): void; | ||
/** | ||
* Log Windows errors. | ||
* Log info message | ||
* | ||
* @param ErrorEvent event | ||
* @param message any | ||
* @param args any | ||
*/ | ||
private logWindowError; | ||
info(message: any, ...args: any[]): void; | ||
/** | ||
* Log unhandled promise rejections. | ||
* Log warning message | ||
* | ||
* @param PromiseRejectionEvent event | ||
* @param message any | ||
* @param args any | ||
*/ | ||
private logUnhandledRejection; | ||
warn(message: any, ...args: any[]): void; | ||
/** | ||
* Register a listener for the window error events and log the data. | ||
*/ | ||
addWindowErrorListener(): void; | ||
/** | ||
* Register a listener for service worker messages and log the data. | ||
* The service worker will send the number of open Playground tabs. | ||
*/ | ||
addServiceWorkerMessageListener(): void; | ||
/** | ||
* Register a listener for the request.end event and log the data. | ||
* @param UniversalPHP playground instance | ||
*/ | ||
addPlaygroundRequestEndListener(playground: UniversalPHP): void; | ||
/** | ||
* Get UTC date in the PHP log format https://github.com/php/php-src/blob/master/main/main.c#L849 | ||
* Log error message | ||
* | ||
* @param date | ||
* @returns string | ||
* @param message any | ||
* @param args any | ||
*/ | ||
private formatLogDate; | ||
/** | ||
* Format log message and severity and log it. | ||
* @param string message | ||
* @param LogSeverity severity | ||
* @param string prefix | ||
*/ | ||
formatMessage(message: string, severity: LogSeverity, prefix: string): string; | ||
/** | ||
* Log message with severity and timestamp. | ||
* @param string message | ||
* @param LogSeverity severity | ||
* @param string prefix | ||
*/ | ||
log(message: string, severity?: LogSeverity, prefix?: LogPrefix): void; | ||
/** | ||
* Log message without severity and timestamp. | ||
* @param string log | ||
*/ | ||
logRaw(log: string): void; | ||
/** | ||
* Get all logs. | ||
* @returns string[] | ||
*/ | ||
getLogs(): string[]; | ||
/** | ||
* Add context data. | ||
*/ | ||
addContext(data: Record<string, any>): void; | ||
/** | ||
* Get context data. | ||
*/ | ||
getContext(): Record<string, any>; | ||
error(message: any, ...args: any[]): void; | ||
} | ||
@@ -116,24 +78,4 @@ /** | ||
export declare const logger: Logger; | ||
export declare const formatLogEntry: (message: string, severity: LogSeverity, prefix: string) => string; | ||
/** | ||
* Collect errors from JavaScript window events like error and log them. | ||
* @param loggerInstance The logger instance | ||
*/ | ||
export declare function collectWindowErrors(loggerInstance: Logger): void; | ||
/** | ||
* Collect PHP logs from the error_log file and log them. | ||
* @param UniversalPHP playground instance | ||
* @param loggerInstance The logger instance | ||
*/ | ||
export declare function collectPhpLogs(loggerInstance: Logger, playground: UniversalPHP): void; | ||
/** | ||
* **Call this inside a service worker.** | ||
* | ||
* Reports service worker metrics. | ||
* Allows the logger to request metrics from the service worker by sending a message. | ||
* The service worker will respond with the number of open Playground tabs. | ||
* | ||
* @param worker The service worker | ||
*/ | ||
export declare function reportServiceWorkerMetrics(worker: ServiceWorkerGlobalScope): void; | ||
/** | ||
* Add a listener for the Playground crashes. | ||
@@ -146,2 +88,2 @@ * These crashes include Playground errors like Asyncify errors. | ||
*/ | ||
export declare function addCrashListener(loggerInstance: Logger, callback: EventListenerOrEventListenerObject): void; | ||
export declare const addCrashListener: (loggerInstance: Logger, callback: EventListenerOrEventListenerObject) => void; |
{ | ||
"name": "@php-wasm/logger", | ||
"version": "0.7.1", | ||
"version": "0.7.3", | ||
"description": "A logger for PHP-wasm clients like Playground and WP-now.", | ||
@@ -22,3 +22,4 @@ "repository": { | ||
"license": "GPL-2.0-or-later", | ||
"main": "index.cjs", | ||
"type": "module", | ||
"main": "index.js", | ||
"types": "index.d.ts", | ||
@@ -29,3 +30,3 @@ "engines": { | ||
}, | ||
"gitHead": "ed0ec39040ab4cd69dc48a8eac157436b30f9d55" | ||
"gitHead": "e8fedf92bbead5cec963c8d6976e7143d8e68721" | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
17976
12
475
Yes
1