@php-wasm/logger 0.7.1 → 0.7.3
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/index.cjs +3 -0
- package/index.d.ts +1 -0
- package/index.js +319 -1
- package/lib/collectors/collect-php-logs.d.ts +8 -0
- package/lib/collectors/collect-service-worker-metrics.d.ts +12 -0
- package/lib/collectors/collect-window-errors.d.ts +6 -0
- package/lib/handlers/log-to-console.d.ts +5 -0
- package/lib/handlers/log-to-memory.d.ts +7 -0
- package/lib/log-collector.d.ts +3 -0
- package/lib/log-handlers.d.ts +6 -0
- package/lib/logger.d.ts +42 -100
- package/package.json +4 -3
- package/index.mjs +0 -261
package/index.cjs
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=function(){var r;return typeof process<"u"&&((r=process.release)==null?void 0:r.name)==="node"?"NODE":typeof window<"u"?"WEB":typeof WorkerGlobalScope<"u"&&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=new Date),(!a||isNaN(a.getFullYear()))&&(a=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",autoAllocateChunkSize:512*1024,async pull(o){const n=o.byobRequest.view,a=await s.slice(t,t+n.byteLength).arrayBuffer(),c=new Uint8Array(a);new Uint8Array(n.buffer).set(c);const f=c.byteLength;o.byobRequest.respond(f),t+=f,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 L=(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)}},v=(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=E(typeof r.message=="object"?v(r.message):r.message,r.severity??"Info",r.prefix??"JavaScript");u(e)}};class w extends EventTarget{constructor(e=[]){super(),this.handlers=e,this.fatalErrorEvent="playground-fatal-error"}getLogs(){return this.handlers.includes(b)?[...h]:(this.error(`Logs aren't stored because the logToMemory handler isn't registered.
|
|
2
|
+
If you're using a custom logger instance, make sure to register logToMemory handler.
|
|
3
|
+
`),[])}logMessage(e,...t){for(const s of this.handlers)s(e,...t)}log(e,...t){this.logMessage({message:e,severity:void 0,prefix:"JavaScript",raw:!1},...t)}debug(e,...t){this.logMessage({message:e,severity:"Debug",prefix:"JavaScript",raw:!1},...t)}info(e,...t){this.logMessage({message:e,severity:"Info",prefix:"JavaScript",raw:!1},...t)}warn(e,...t){this.logMessage({message:e,severity:"Warn",prefix:"JavaScript",raw:!1},...t)}error(e,...t){this.logMessage({message:e,severity:"Error",prefix:"JavaScript",raw:!1},...t)}}const M=new w([b,L]),E=(r,e,t)=>{const s=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}`},T=(r,e)=>{r.addEventListener(r.fatalErrorEvent,e)};let l=0;const g="/wordpress/wp-content/debug.log",S=async r=>await r.fileExists(g)?await r.readFileAsText(g):"",O=(r,e)=>{e.addEventListener("request.end",async()=>{const t=await S(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}})))})},P=(r,e)=>{r.logMessage({message:`${e.message} in ${e.filename} on line ${e.lineno}:${e.colno}`,severity:"Error"})},y=(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 B=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 m=!1;const k=r=>{m||(B(r),!(typeof window>"u")&&(window.addEventListener("error",e=>P(r,e)),window.addEventListener("unhandledrejection",e=>y(r,e)),window.addEventListener("rejectionhandled",e=>y(r,e)),m=!0))},x=r=>{r.addEventListener("activate",()=>{r.clients.matchAll().then(e=>{const t={numberOfOpenPlaygroundTabs:e.filter(s=>s.frameType==="top-level").length};for(const s of e)s.postMessage(t)})})};exports.Logger=w;exports.addCrashListener=T;exports.collectPhpLogs=O;exports.collectWindowErrors=k;exports.formatLogEntry=E;exports.logger=M;exports.reportServiceWorkerMetrics=x;
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -1 +1,319 @@
|
|
|
1
|
-
|
|
1
|
+
const p = function() {
|
|
2
|
+
var r;
|
|
3
|
+
return typeof process < "u" && ((r = process.release) == null ? void 0 : r.name) === "node" ? "NODE" : typeof window < "u" ? "WEB" : (
|
|
4
|
+
// @ts-ignore
|
|
5
|
+
typeof WorkerGlobalScope < "u" && // @ts-ignore
|
|
6
|
+
self instanceof WorkerGlobalScope ? "WORKER" : "NODE"
|
|
7
|
+
);
|
|
8
|
+
}();
|
|
9
|
+
if (p === "NODE") {
|
|
10
|
+
let r = function(t) {
|
|
11
|
+
return new Promise(function(s, o) {
|
|
12
|
+
t.onload = t.onerror = function(n) {
|
|
13
|
+
t.onload = t.onerror = null, n.type === "load" ? s(t.result) : o(new Error("Failed to read the blob/file"));
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
}, e = function() {
|
|
17
|
+
const t = new Uint8Array([1, 2, 3, 4]), o = new File([t], "test").stream();
|
|
18
|
+
try {
|
|
19
|
+
return o.getReader({ mode: "byob" }), !0;
|
|
20
|
+
} catch {
|
|
21
|
+
return !1;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
if (typeof File > "u") {
|
|
25
|
+
class t extends Blob {
|
|
26
|
+
constructor(o, n, i) {
|
|
27
|
+
super(o);
|
|
28
|
+
let a;
|
|
29
|
+
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 || "";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
global.File = t;
|
|
33
|
+
}
|
|
34
|
+
typeof Blob.prototype.arrayBuffer > "u" && (Blob.prototype.arrayBuffer = function() {
|
|
35
|
+
const s = new FileReader();
|
|
36
|
+
return s.readAsArrayBuffer(this), r(s);
|
|
37
|
+
}), typeof Blob.prototype.text > "u" && (Blob.prototype.text = function() {
|
|
38
|
+
const s = new FileReader();
|
|
39
|
+
return s.readAsText(this), r(s);
|
|
40
|
+
}), (typeof Blob.prototype.stream > "u" || !e()) && (Blob.prototype.stream = function() {
|
|
41
|
+
let t = 0;
|
|
42
|
+
const s = this;
|
|
43
|
+
return new ReadableStream({
|
|
44
|
+
type: "bytes",
|
|
45
|
+
// 0.5 MB seems like a reasonable chunk size, let's adjust
|
|
46
|
+
// this if needed.
|
|
47
|
+
autoAllocateChunkSize: 512 * 1024,
|
|
48
|
+
async pull(o) {
|
|
49
|
+
const n = o.byobRequest.view, a = await s.slice(
|
|
50
|
+
t,
|
|
51
|
+
t + n.byteLength
|
|
52
|
+
).arrayBuffer(), f = new Uint8Array(a);
|
|
53
|
+
new Uint8Array(n.buffer).set(f);
|
|
54
|
+
const c = f.byteLength;
|
|
55
|
+
o.byobRequest.respond(c), t += c, t >= s.size && o.close();
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (p === "NODE" && typeof CustomEvent > "u") {
|
|
61
|
+
class r extends Event {
|
|
62
|
+
constructor(t, s = {}) {
|
|
63
|
+
super(t, s), this.detail = s.detail;
|
|
64
|
+
}
|
|
65
|
+
initCustomEvent() {
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
globalThis.CustomEvent = r;
|
|
69
|
+
}
|
|
70
|
+
const w = (r, ...e) => {
|
|
71
|
+
switch (r.severity) {
|
|
72
|
+
case "Debug":
|
|
73
|
+
console.debug(r.message, ...e);
|
|
74
|
+
break;
|
|
75
|
+
case "Info":
|
|
76
|
+
console.info(r.message, ...e);
|
|
77
|
+
break;
|
|
78
|
+
case "Warn":
|
|
79
|
+
console.warn(r.message, ...e);
|
|
80
|
+
break;
|
|
81
|
+
case "Error":
|
|
82
|
+
console.error(r.message, ...e);
|
|
83
|
+
break;
|
|
84
|
+
case "Fatal":
|
|
85
|
+
console.error(r.message, ...e);
|
|
86
|
+
break;
|
|
87
|
+
default:
|
|
88
|
+
console.log(r.message, ...e);
|
|
89
|
+
}
|
|
90
|
+
}, E = (r, ...e) => [
|
|
91
|
+
typeof r == "object" ? JSON.stringify(r) : r,
|
|
92
|
+
...e.map((t) => JSON.stringify(t))
|
|
93
|
+
].join(" "), h = [], u = (r) => {
|
|
94
|
+
h.push(r);
|
|
95
|
+
}, b = (r) => {
|
|
96
|
+
if (r.raw === !0)
|
|
97
|
+
u(r.message);
|
|
98
|
+
else {
|
|
99
|
+
const e = L(
|
|
100
|
+
typeof r.message == "object" ? E(r.message) : r.message,
|
|
101
|
+
r.severity ?? "Info",
|
|
102
|
+
r.prefix ?? "JavaScript"
|
|
103
|
+
);
|
|
104
|
+
u(e);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
class v extends EventTarget {
|
|
108
|
+
// constructor
|
|
109
|
+
constructor(e = []) {
|
|
110
|
+
super(), this.handlers = e, this.fatalErrorEvent = "playground-fatal-error";
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Get all logs.
|
|
114
|
+
* @returns string[]
|
|
115
|
+
*/
|
|
116
|
+
getLogs() {
|
|
117
|
+
return this.handlers.includes(b) ? [...h] : (this.error(`Logs aren't stored because the logToMemory handler isn't registered.
|
|
118
|
+
If you're using a custom logger instance, make sure to register logToMemory handler.
|
|
119
|
+
`), []);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Log message with severity.
|
|
123
|
+
*
|
|
124
|
+
* @param message any
|
|
125
|
+
* @param severity LogSeverity
|
|
126
|
+
* @param raw boolean
|
|
127
|
+
* @param args any
|
|
128
|
+
*/
|
|
129
|
+
logMessage(e, ...t) {
|
|
130
|
+
for (const s of this.handlers)
|
|
131
|
+
s(e, ...t);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Log message
|
|
135
|
+
*
|
|
136
|
+
* @param message any
|
|
137
|
+
* @param args any
|
|
138
|
+
*/
|
|
139
|
+
log(e, ...t) {
|
|
140
|
+
this.logMessage(
|
|
141
|
+
{
|
|
142
|
+
message: e,
|
|
143
|
+
severity: void 0,
|
|
144
|
+
prefix: "JavaScript",
|
|
145
|
+
raw: !1
|
|
146
|
+
},
|
|
147
|
+
...t
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Log debug message
|
|
152
|
+
*
|
|
153
|
+
* @param message any
|
|
154
|
+
* @param args any
|
|
155
|
+
*/
|
|
156
|
+
debug(e, ...t) {
|
|
157
|
+
this.logMessage(
|
|
158
|
+
{
|
|
159
|
+
message: e,
|
|
160
|
+
severity: "Debug",
|
|
161
|
+
prefix: "JavaScript",
|
|
162
|
+
raw: !1
|
|
163
|
+
},
|
|
164
|
+
...t
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Log info message
|
|
169
|
+
*
|
|
170
|
+
* @param message any
|
|
171
|
+
* @param args any
|
|
172
|
+
*/
|
|
173
|
+
info(e, ...t) {
|
|
174
|
+
this.logMessage(
|
|
175
|
+
{
|
|
176
|
+
message: e,
|
|
177
|
+
severity: "Info",
|
|
178
|
+
prefix: "JavaScript",
|
|
179
|
+
raw: !1
|
|
180
|
+
},
|
|
181
|
+
...t
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Log warning message
|
|
186
|
+
*
|
|
187
|
+
* @param message any
|
|
188
|
+
* @param args any
|
|
189
|
+
*/
|
|
190
|
+
warn(e, ...t) {
|
|
191
|
+
this.logMessage(
|
|
192
|
+
{
|
|
193
|
+
message: e,
|
|
194
|
+
severity: "Warn",
|
|
195
|
+
prefix: "JavaScript",
|
|
196
|
+
raw: !1
|
|
197
|
+
},
|
|
198
|
+
...t
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Log error message
|
|
203
|
+
*
|
|
204
|
+
* @param message any
|
|
205
|
+
* @param args any
|
|
206
|
+
*/
|
|
207
|
+
error(e, ...t) {
|
|
208
|
+
this.logMessage(
|
|
209
|
+
{
|
|
210
|
+
message: e,
|
|
211
|
+
severity: "Error",
|
|
212
|
+
prefix: "JavaScript",
|
|
213
|
+
raw: !1
|
|
214
|
+
},
|
|
215
|
+
...t
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
const B = new v([b, w]), L = (r, e, t) => {
|
|
220
|
+
const s = /* @__PURE__ */ new Date(), o = new Intl.DateTimeFormat("en-GB", {
|
|
221
|
+
year: "numeric",
|
|
222
|
+
month: "short",
|
|
223
|
+
day: "2-digit",
|
|
224
|
+
timeZone: "UTC"
|
|
225
|
+
}).format(s).replace(/ /g, "-"), n = new Intl.DateTimeFormat("en-GB", {
|
|
226
|
+
hour: "2-digit",
|
|
227
|
+
minute: "2-digit",
|
|
228
|
+
second: "2-digit",
|
|
229
|
+
hour12: !1,
|
|
230
|
+
timeZone: "UTC",
|
|
231
|
+
timeZoneName: "short"
|
|
232
|
+
}).format(s);
|
|
233
|
+
return `[${o + " " + n}] ${t} ${e}: ${r}`;
|
|
234
|
+
}, O = (r, e) => {
|
|
235
|
+
r.addEventListener(r.fatalErrorEvent, e);
|
|
236
|
+
};
|
|
237
|
+
let l = 0;
|
|
238
|
+
const g = "/wordpress/wp-content/debug.log", M = async (r) => await r.fileExists(g) ? await r.readFileAsText(g) : "", P = (r, e) => {
|
|
239
|
+
e.addEventListener("request.end", async () => {
|
|
240
|
+
const t = await M(e);
|
|
241
|
+
if (t.length > l) {
|
|
242
|
+
const s = t.substring(l);
|
|
243
|
+
r.logMessage({
|
|
244
|
+
message: s,
|
|
245
|
+
raw: !0
|
|
246
|
+
}), l = t.length;
|
|
247
|
+
}
|
|
248
|
+
}), e.addEventListener("request.error", (t) => {
|
|
249
|
+
t = t, t.error && (r.logMessage({
|
|
250
|
+
message: `${t.error.message} ${t.error.stack}`,
|
|
251
|
+
severity: "Fatal",
|
|
252
|
+
prefix: t.source === "request" ? "PHP" : "WASM Crash"
|
|
253
|
+
}), r.dispatchEvent(
|
|
254
|
+
new CustomEvent(r.fatalErrorEvent, {
|
|
255
|
+
detail: {
|
|
256
|
+
logs: r.getLogs(),
|
|
257
|
+
source: t.source
|
|
258
|
+
}
|
|
259
|
+
})
|
|
260
|
+
));
|
|
261
|
+
});
|
|
262
|
+
}, T = (r, e) => {
|
|
263
|
+
r.logMessage({
|
|
264
|
+
message: `${e.message} in ${e.filename} on line ${e.lineno}:${e.colno}`,
|
|
265
|
+
severity: "Error"
|
|
266
|
+
});
|
|
267
|
+
}, m = (r, e) => {
|
|
268
|
+
if (!(e != null && e.reason))
|
|
269
|
+
return;
|
|
270
|
+
const t = (e == null ? void 0 : e.reason.stack) ?? e.reason;
|
|
271
|
+
r.logMessage({
|
|
272
|
+
message: t,
|
|
273
|
+
severity: "Error"
|
|
274
|
+
});
|
|
275
|
+
};
|
|
276
|
+
let d = 0;
|
|
277
|
+
const x = (r) => {
|
|
278
|
+
navigator.serviceWorker.addEventListener("message", (e) => {
|
|
279
|
+
var t, s, o;
|
|
280
|
+
((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(
|
|
281
|
+
`Number of open Playground tabs is: ${d}`
|
|
282
|
+
));
|
|
283
|
+
});
|
|
284
|
+
};
|
|
285
|
+
let y = !1;
|
|
286
|
+
const S = (r) => {
|
|
287
|
+
y || (x(r), !(typeof window > "u") && (window.addEventListener(
|
|
288
|
+
"error",
|
|
289
|
+
(e) => T(r, e)
|
|
290
|
+
), window.addEventListener(
|
|
291
|
+
"unhandledrejection",
|
|
292
|
+
(e) => m(r, e)
|
|
293
|
+
), window.addEventListener(
|
|
294
|
+
"rejectionhandled",
|
|
295
|
+
(e) => m(r, e)
|
|
296
|
+
), y = !0));
|
|
297
|
+
}, k = (r) => {
|
|
298
|
+
r.addEventListener("activate", () => {
|
|
299
|
+
r.clients.matchAll().then((e) => {
|
|
300
|
+
const t = {
|
|
301
|
+
numberOfOpenPlaygroundTabs: e.filter(
|
|
302
|
+
// Only count top-level frames to get the number of tabs.
|
|
303
|
+
(s) => s.frameType === "top-level"
|
|
304
|
+
).length
|
|
305
|
+
};
|
|
306
|
+
for (const s of e)
|
|
307
|
+
s.postMessage(t);
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
};
|
|
311
|
+
export {
|
|
312
|
+
v as Logger,
|
|
313
|
+
O as addCrashListener,
|
|
314
|
+
P as collectPhpLogs,
|
|
315
|
+
S as collectWindowErrors,
|
|
316
|
+
L as formatLogEntry,
|
|
317
|
+
B as logger,
|
|
318
|
+
k as reportServiceWorkerMetrics
|
|
319
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { UniversalPHP } from '../../universal';
|
|
2
|
+
import { Logger } from '../logger';
|
|
3
|
+
/**
|
|
4
|
+
* Collect PHP logs from the error_log file and log them.
|
|
5
|
+
* @param UniversalPHP playground instance
|
|
6
|
+
* @param loggerInstance The logger instance
|
|
7
|
+
*/
|
|
8
|
+
export declare const collectPhpLogs: (loggerInstance: Logger, playground: UniversalPHP) => void;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/// <reference lib="webworker" />
|
|
2
|
+
/**
|
|
3
|
+
* **Call this inside a service worker.**
|
|
4
|
+
* These errors include Playground errors like Asyncify errors. PHP errors won't trigger this event.
|
|
5
|
+
*
|
|
6
|
+
* Reports service worker metrics.
|
|
7
|
+
* Allows the logger to request metrics from the service worker by sending a message.
|
|
8
|
+
* The service worker will respond with the number of open Playground tabs.
|
|
9
|
+
*
|
|
10
|
+
* @param worker The service worker
|
|
11
|
+
*/
|
|
12
|
+
export declare const reportServiceWorkerMetrics: (worker: ServiceWorkerGlobalScope) => void;
|
package/lib/logger.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
export type Log = {
|
|
2
|
+
message: any;
|
|
3
|
+
severity?: LogSeverity;
|
|
4
|
+
prefix?: LogPrefix;
|
|
5
|
+
raw?: boolean;
|
|
6
|
+
};
|
|
3
7
|
/**
|
|
4
8
|
* Log severity levels.
|
|
5
9
|
*/
|
|
@@ -7,131 +11,69 @@ export type LogSeverity = 'Debug' | 'Info' | 'Warn' | 'Error' | 'Fatal';
|
|
|
7
11
|
/**
|
|
8
12
|
* Log prefix.
|
|
9
13
|
*/
|
|
10
|
-
export type LogPrefix = '
|
|
14
|
+
export type LogPrefix = 'WASM Crash' | 'PHP' | 'JavaScript';
|
|
11
15
|
/**
|
|
12
16
|
* A logger for Playground.
|
|
13
17
|
*/
|
|
14
18
|
export declare class Logger extends EventTarget {
|
|
19
|
+
private readonly handlers;
|
|
15
20
|
readonly fatalErrorEvent = "playground-fatal-error";
|
|
21
|
+
constructor(handlers?: Function[]);
|
|
16
22
|
/**
|
|
17
|
-
*
|
|
18
|
-
|
|
19
|
-
private logs;
|
|
20
|
-
/**
|
|
21
|
-
* Whether the window events are connected.
|
|
22
|
-
*/
|
|
23
|
-
private windowConnected;
|
|
24
|
-
/**
|
|
25
|
-
* The length of the last PHP log.
|
|
26
|
-
*/
|
|
27
|
-
private lastPHPLogLength;
|
|
28
|
-
/**
|
|
29
|
-
* Context data
|
|
30
|
-
*/
|
|
31
|
-
private context;
|
|
32
|
-
/**
|
|
33
|
-
* The path to the error log file.
|
|
23
|
+
* Get all logs.
|
|
24
|
+
* @returns string[]
|
|
34
25
|
*/
|
|
35
|
-
|
|
36
|
-
constructor(errorLogPath?: string);
|
|
26
|
+
getLogs(): string[];
|
|
37
27
|
/**
|
|
38
|
-
*
|
|
28
|
+
* Log message with severity.
|
|
39
29
|
*
|
|
40
|
-
* @param
|
|
41
|
-
* @
|
|
30
|
+
* @param message any
|
|
31
|
+
* @param severity LogSeverity
|
|
32
|
+
* @param raw boolean
|
|
33
|
+
* @param args any
|
|
42
34
|
*/
|
|
43
|
-
|
|
35
|
+
logMessage(log: Log, ...args: any[]): void;
|
|
44
36
|
/**
|
|
45
|
-
* Log
|
|
37
|
+
* Log message
|
|
46
38
|
*
|
|
47
|
-
* @param
|
|
39
|
+
* @param message any
|
|
40
|
+
* @param args any
|
|
48
41
|
*/
|
|
49
|
-
|
|
42
|
+
log(message: any, ...args: any[]): void;
|
|
50
43
|
/**
|
|
51
|
-
* Log
|
|
44
|
+
* Log debug message
|
|
52
45
|
*
|
|
53
|
-
* @param
|
|
54
|
-
|
|
55
|
-
private logUnhandledRejection;
|
|
56
|
-
/**
|
|
57
|
-
* Register a listener for the window error events and log the data.
|
|
58
|
-
*/
|
|
59
|
-
addWindowErrorListener(): void;
|
|
60
|
-
/**
|
|
61
|
-
* Register a listener for service worker messages and log the data.
|
|
62
|
-
* The service worker will send the number of open Playground tabs.
|
|
46
|
+
* @param message any
|
|
47
|
+
* @param args any
|
|
63
48
|
*/
|
|
64
|
-
|
|
49
|
+
debug(message: any, ...args: any[]): void;
|
|
65
50
|
/**
|
|
66
|
-
*
|
|
67
|
-
* @param UniversalPHP playground instance
|
|
68
|
-
*/
|
|
69
|
-
addPlaygroundRequestEndListener(playground: UniversalPHP): void;
|
|
70
|
-
/**
|
|
71
|
-
* Get UTC date in the PHP log format https://github.com/php/php-src/blob/master/main/main.c#L849
|
|
51
|
+
* Log info message
|
|
72
52
|
*
|
|
73
|
-
* @param
|
|
74
|
-
* @
|
|
75
|
-
*/
|
|
76
|
-
private formatLogDate;
|
|
77
|
-
/**
|
|
78
|
-
* Format log message and severity and log it.
|
|
79
|
-
* @param string message
|
|
80
|
-
* @param LogSeverity severity
|
|
81
|
-
* @param string prefix
|
|
82
|
-
*/
|
|
83
|
-
formatMessage(message: string, severity: LogSeverity, prefix: string): string;
|
|
84
|
-
/**
|
|
85
|
-
* Log message with severity and timestamp.
|
|
86
|
-
* @param string message
|
|
87
|
-
* @param LogSeverity severity
|
|
88
|
-
* @param string prefix
|
|
89
|
-
*/
|
|
90
|
-
log(message: string, severity?: LogSeverity, prefix?: LogPrefix): void;
|
|
91
|
-
/**
|
|
92
|
-
* Log message without severity and timestamp.
|
|
93
|
-
* @param string log
|
|
94
|
-
*/
|
|
95
|
-
logRaw(log: string): void;
|
|
96
|
-
/**
|
|
97
|
-
* Get all logs.
|
|
98
|
-
* @returns string[]
|
|
53
|
+
* @param message any
|
|
54
|
+
* @param args any
|
|
99
55
|
*/
|
|
100
|
-
|
|
56
|
+
info(message: any, ...args: any[]): void;
|
|
101
57
|
/**
|
|
102
|
-
*
|
|
58
|
+
* Log warning message
|
|
59
|
+
*
|
|
60
|
+
* @param message any
|
|
61
|
+
* @param args any
|
|
103
62
|
*/
|
|
104
|
-
|
|
63
|
+
warn(message: any, ...args: any[]): void;
|
|
105
64
|
/**
|
|
106
|
-
*
|
|
65
|
+
* Log error message
|
|
66
|
+
*
|
|
67
|
+
* @param message any
|
|
68
|
+
* @param args any
|
|
107
69
|
*/
|
|
108
|
-
|
|
70
|
+
error(message: any, ...args: any[]): void;
|
|
109
71
|
}
|
|
110
72
|
/**
|
|
111
73
|
* The logger instance.
|
|
112
74
|
*/
|
|
113
75
|
export declare const logger: Logger;
|
|
114
|
-
|
|
115
|
-
* Collect errors from JavaScript window events like error and log them.
|
|
116
|
-
* @param loggerInstance The logger instance
|
|
117
|
-
*/
|
|
118
|
-
export declare function collectWindowErrors(loggerInstance: Logger): void;
|
|
119
|
-
/**
|
|
120
|
-
* Collect PHP logs from the error_log file and log them.
|
|
121
|
-
* @param UniversalPHP playground instance
|
|
122
|
-
* @param loggerInstance The logger instance
|
|
123
|
-
*/
|
|
124
|
-
export declare function collectPhpLogs(loggerInstance: Logger, playground: UniversalPHP): void;
|
|
125
|
-
/**
|
|
126
|
-
* **Call this inside a service worker.**
|
|
127
|
-
*
|
|
128
|
-
* Reports service worker metrics.
|
|
129
|
-
* Allows the logger to request metrics from the service worker by sending a message.
|
|
130
|
-
* The service worker will respond with the number of open Playground tabs.
|
|
131
|
-
*
|
|
132
|
-
* @param worker The service worker
|
|
133
|
-
*/
|
|
134
|
-
export declare function reportServiceWorkerMetrics(worker: ServiceWorkerGlobalScope): void;
|
|
76
|
+
export declare const formatLogEntry: (message: string, severity: LogSeverity, prefix: string) => string;
|
|
135
77
|
/**
|
|
136
78
|
* Add a listener for the Playground crashes.
|
|
137
79
|
* These crashes include Playground errors like Asyncify errors.
|
|
@@ -140,4 +82,4 @@ export declare function reportServiceWorkerMetrics(worker: ServiceWorkerGlobalSc
|
|
|
140
82
|
* @param loggerInstance The logger instance
|
|
141
83
|
* @param callback The callback function
|
|
142
84
|
*/
|
|
143
|
-
export declare
|
|
85
|
+
export declare const addCrashListener: (loggerInstance: Logger, callback: EventListenerOrEventListenerObject) => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@php-wasm/logger",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.3",
|
|
4
4
|
"description": "A logger for PHP-wasm clients like Playground and WP-now.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -19,11 +19,12 @@
|
|
|
19
19
|
"directory": "../../../dist/packages/php-wasm/logger"
|
|
20
20
|
},
|
|
21
21
|
"license": "GPL-2.0-or-later",
|
|
22
|
-
"
|
|
22
|
+
"type": "module",
|
|
23
|
+
"main": "index.js",
|
|
23
24
|
"types": "index.d.ts",
|
|
24
25
|
"engines": {
|
|
25
26
|
"node": ">=18.18.0",
|
|
26
27
|
"npm": ">=8.11.0"
|
|
27
28
|
},
|
|
28
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "e8fedf92bbead5cec963c8d6976e7143d8e68721"
|
|
29
30
|
}
|
package/index.mjs
DELETED
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
const u = function() {
|
|
2
|
-
var n;
|
|
3
|
-
return typeof process < "u" && ((n = process.release) == null ? void 0 : n.name) === "node" ? "NODE" : typeof window < "u" ? "WEB" : (
|
|
4
|
-
// @ts-ignore
|
|
5
|
-
typeof WorkerGlobalScope < "u" && // @ts-ignore
|
|
6
|
-
self instanceof WorkerGlobalScope ? "WORKER" : "NODE"
|
|
7
|
-
);
|
|
8
|
-
}();
|
|
9
|
-
if (u === "NODE") {
|
|
10
|
-
let n = function(t) {
|
|
11
|
-
return new Promise(function(r, o) {
|
|
12
|
-
t.onload = t.onerror = function(i) {
|
|
13
|
-
t.onload = t.onerror = null, i.type === "load" ? r(t.result) : o(new Error("Failed to read the blob/file"));
|
|
14
|
-
};
|
|
15
|
-
});
|
|
16
|
-
}, e = function() {
|
|
17
|
-
const t = new Uint8Array([1, 2, 3, 4]), o = new File([t], "test").stream();
|
|
18
|
-
try {
|
|
19
|
-
return o.getReader({ mode: "byob" }), !0;
|
|
20
|
-
} catch {
|
|
21
|
-
return !1;
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
if (typeof File > "u") {
|
|
25
|
-
class t extends Blob {
|
|
26
|
-
constructor(o, i, a) {
|
|
27
|
-
super(o);
|
|
28
|
-
let s;
|
|
29
|
-
a != null && a.lastModified && (s = /* @__PURE__ */ new Date()), (!s || isNaN(s.getFullYear())) && (s = /* @__PURE__ */ new Date()), this.lastModifiedDate = s, this.lastModified = s.getMilliseconds(), this.name = i || "";
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
global.File = t;
|
|
33
|
-
}
|
|
34
|
-
typeof Blob.prototype.arrayBuffer > "u" && (Blob.prototype.arrayBuffer = function() {
|
|
35
|
-
const r = new FileReader();
|
|
36
|
-
return r.readAsArrayBuffer(this), n(r);
|
|
37
|
-
}), typeof Blob.prototype.text > "u" && (Blob.prototype.text = function() {
|
|
38
|
-
const r = new FileReader();
|
|
39
|
-
return r.readAsText(this), n(r);
|
|
40
|
-
}), (typeof Blob.prototype.stream > "u" || !e()) && (Blob.prototype.stream = function() {
|
|
41
|
-
let t = 0;
|
|
42
|
-
const r = this;
|
|
43
|
-
return new ReadableStream({
|
|
44
|
-
type: "bytes",
|
|
45
|
-
// 0.5 MB seems like a reasonable chunk size, let's adjust
|
|
46
|
-
// this if needed.
|
|
47
|
-
autoAllocateChunkSize: 512 * 1024,
|
|
48
|
-
async pull(o) {
|
|
49
|
-
const i = o.byobRequest.view, s = await r.slice(
|
|
50
|
-
t,
|
|
51
|
-
t + i.byteLength
|
|
52
|
-
).arrayBuffer(), d = new Uint8Array(s);
|
|
53
|
-
new Uint8Array(i.buffer).set(d);
|
|
54
|
-
const l = d.byteLength;
|
|
55
|
-
o.byobRequest.respond(l), t += l, t >= r.size && o.close();
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
if (u === "NODE" && typeof CustomEvent > "u") {
|
|
61
|
-
class n extends Event {
|
|
62
|
-
constructor(t, r = {}) {
|
|
63
|
-
super(t, r), this.detail = r.detail;
|
|
64
|
-
}
|
|
65
|
-
initCustomEvent() {
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
globalThis.CustomEvent = n;
|
|
69
|
-
}
|
|
70
|
-
class f extends EventTarget {
|
|
71
|
-
constructor(e) {
|
|
72
|
-
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);
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Read the WordPress debug.log file and return its content.
|
|
76
|
-
*
|
|
77
|
-
* @param UniversalPHP playground instance
|
|
78
|
-
* @returns string The content of the debug.log file
|
|
79
|
-
*/
|
|
80
|
-
async getRequestPhpErrorLog(e) {
|
|
81
|
-
return await e.fileExists(this.errorLogPath) ? await e.readFileAsText(this.errorLogPath) : "";
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Log Windows errors.
|
|
85
|
-
*
|
|
86
|
-
* @param ErrorEvent event
|
|
87
|
-
*/
|
|
88
|
-
logWindowError(e) {
|
|
89
|
-
this.log(
|
|
90
|
-
`${e.message} in ${e.filename} on line ${e.lineno}:${e.colno}`,
|
|
91
|
-
"Error"
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Log unhandled promise rejections.
|
|
96
|
-
*
|
|
97
|
-
* @param PromiseRejectionEvent event
|
|
98
|
-
*/
|
|
99
|
-
logUnhandledRejection(e) {
|
|
100
|
-
if (!(e != null && e.reason))
|
|
101
|
-
return;
|
|
102
|
-
const t = (e == null ? void 0 : e.reason.stack) ?? e.reason;
|
|
103
|
-
this.log(t, "Error");
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Register a listener for the window error events and log the data.
|
|
107
|
-
*/
|
|
108
|
-
addWindowErrorListener() {
|
|
109
|
-
this.windowConnected || typeof window > "u" || (window.addEventListener("error", this.logWindowError.bind(this)), window.addEventListener(
|
|
110
|
-
"unhandledrejection",
|
|
111
|
-
this.logUnhandledRejection.bind(this)
|
|
112
|
-
), window.addEventListener(
|
|
113
|
-
"rejectionhandled",
|
|
114
|
-
this.logUnhandledRejection.bind(this)
|
|
115
|
-
), this.windowConnected = !0);
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Register a listener for service worker messages and log the data.
|
|
119
|
-
* The service worker will send the number of open Playground tabs.
|
|
120
|
-
*/
|
|
121
|
-
addServiceWorkerMessageListener() {
|
|
122
|
-
navigator.serviceWorker.addEventListener("message", (e) => {
|
|
123
|
-
var t;
|
|
124
|
-
((t = e.data) == null ? void 0 : t.numberOfOpenPlaygroundTabs) !== void 0 && this.addContext({
|
|
125
|
-
numberOfOpenPlaygroundTabs: e.data.numberOfOpenPlaygroundTabs
|
|
126
|
-
});
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Register a listener for the request.end event and log the data.
|
|
131
|
-
* @param UniversalPHP playground instance
|
|
132
|
-
*/
|
|
133
|
-
addPlaygroundRequestEndListener(e) {
|
|
134
|
-
e.addEventListener("request.end", async () => {
|
|
135
|
-
const t = await this.getRequestPhpErrorLog(e);
|
|
136
|
-
t.length > this.lastPHPLogLength && (this.logRaw(t.substring(this.lastPHPLogLength)), this.lastPHPLogLength = t.length);
|
|
137
|
-
}), e.addEventListener("request.error", (t) => {
|
|
138
|
-
t = t, t.error && (this.log(
|
|
139
|
-
`${t.error.message} ${t.error.stack}`,
|
|
140
|
-
"Fatal",
|
|
141
|
-
"PHP-WASM"
|
|
142
|
-
), this.dispatchEvent(
|
|
143
|
-
new CustomEvent(this.fatalErrorEvent, {
|
|
144
|
-
detail: {
|
|
145
|
-
logs: this.getLogs(),
|
|
146
|
-
source: t.source
|
|
147
|
-
}
|
|
148
|
-
})
|
|
149
|
-
));
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* Get UTC date in the PHP log format https://github.com/php/php-src/blob/master/main/main.c#L849
|
|
154
|
-
*
|
|
155
|
-
* @param date
|
|
156
|
-
* @returns string
|
|
157
|
-
*/
|
|
158
|
-
formatLogDate(e) {
|
|
159
|
-
const t = new Intl.DateTimeFormat("en-GB", {
|
|
160
|
-
year: "numeric",
|
|
161
|
-
month: "short",
|
|
162
|
-
day: "2-digit",
|
|
163
|
-
timeZone: "UTC"
|
|
164
|
-
}).format(e).replace(/ /g, "-"), r = new Intl.DateTimeFormat("en-GB", {
|
|
165
|
-
hour: "2-digit",
|
|
166
|
-
minute: "2-digit",
|
|
167
|
-
second: "2-digit",
|
|
168
|
-
hour12: !1,
|
|
169
|
-
timeZone: "UTC",
|
|
170
|
-
timeZoneName: "short"
|
|
171
|
-
}).format(e);
|
|
172
|
-
return t + " " + r;
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* Format log message and severity and log it.
|
|
176
|
-
* @param string message
|
|
177
|
-
* @param LogSeverity severity
|
|
178
|
-
* @param string prefix
|
|
179
|
-
*/
|
|
180
|
-
formatMessage(e, t, r) {
|
|
181
|
-
return `[${this.formatLogDate(/* @__PURE__ */ new Date())}] ${r} ${t}: ${e}`;
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* Log message with severity and timestamp.
|
|
185
|
-
* @param string message
|
|
186
|
-
* @param LogSeverity severity
|
|
187
|
-
* @param string prefix
|
|
188
|
-
*/
|
|
189
|
-
log(e, t, r) {
|
|
190
|
-
t === void 0 && (t = "Info");
|
|
191
|
-
const o = this.formatMessage(
|
|
192
|
-
e,
|
|
193
|
-
t,
|
|
194
|
-
r ?? "Playground"
|
|
195
|
-
);
|
|
196
|
-
this.logRaw(o);
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* Log message without severity and timestamp.
|
|
200
|
-
* @param string log
|
|
201
|
-
*/
|
|
202
|
-
logRaw(e) {
|
|
203
|
-
this.logs.push(e), console.debug(e);
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* Get all logs.
|
|
207
|
-
* @returns string[]
|
|
208
|
-
*/
|
|
209
|
-
getLogs() {
|
|
210
|
-
return [...this.logs];
|
|
211
|
-
}
|
|
212
|
-
/**
|
|
213
|
-
* Add context data.
|
|
214
|
-
*/
|
|
215
|
-
addContext(e) {
|
|
216
|
-
this.context = { ...this.context, ...e };
|
|
217
|
-
}
|
|
218
|
-
/**
|
|
219
|
-
* Get context data.
|
|
220
|
-
*/
|
|
221
|
-
getContext() {
|
|
222
|
-
return { ...this.context };
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
const c = new f();
|
|
226
|
-
function h(n) {
|
|
227
|
-
n.addWindowErrorListener(), n.addServiceWorkerMessageListener();
|
|
228
|
-
}
|
|
229
|
-
function g(n, e) {
|
|
230
|
-
n.addPlaygroundRequestEndListener(e);
|
|
231
|
-
}
|
|
232
|
-
function m(n) {
|
|
233
|
-
n.addEventListener("activate", () => {
|
|
234
|
-
n.clients.matchAll().then((e) => {
|
|
235
|
-
const t = {
|
|
236
|
-
numberOfOpenPlaygroundTabs: e.filter(
|
|
237
|
-
// Only count top-level frames to get the number of tabs.
|
|
238
|
-
(r) => r.frameType === "top-level"
|
|
239
|
-
).length
|
|
240
|
-
};
|
|
241
|
-
n.clients.matchAll({
|
|
242
|
-
// We don't claim the clients, so we need to include uncontrolled clients to inform all tabs.
|
|
243
|
-
includeUncontrolled: !0
|
|
244
|
-
}).then((r) => {
|
|
245
|
-
for (const o of r)
|
|
246
|
-
o.postMessage(t);
|
|
247
|
-
});
|
|
248
|
-
});
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
function w(n, e) {
|
|
252
|
-
n.addEventListener(n.fatalErrorEvent, e);
|
|
253
|
-
}
|
|
254
|
-
export {
|
|
255
|
-
f as Logger,
|
|
256
|
-
w as addCrashListener,
|
|
257
|
-
g as collectPhpLogs,
|
|
258
|
-
h as collectWindowErrors,
|
|
259
|
-
c as logger,
|
|
260
|
-
m as reportServiceWorkerMetrics
|
|
261
|
-
};
|