@php-wasm/logger 0.6.15 → 0.7.0

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.js CHANGED
@@ -1 +1 @@
1
- "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(s){t.onload=t.onerror=null,s.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,s,a){super(n);let i;a!=null&&a.lastModified&&(i=new Date),(!i||isNaN(i.getFullYear()))&&(i=new Date),this.lastModifiedDate=i,this.lastModified=i.getMilliseconds(),this.name=s||""}}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 s=n.byobRequest.view,i=await r.slice(t,t+s.byteLength).arrayBuffer(),d=new Uint8Array(i);new Uint8Array(s.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 f extends EventTarget{constructor(e){super(),this.fatalErrorEvent="playground-fatal-error",this.logs=[],this.windowConnected=!1,this.lastPHPLogLength=0,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)}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}}const c=new f;function g(o){o.addWindowErrorListener()}function h(o,e){o.addPlaygroundRequestEndListener(e)}function w(o,e){o.addEventListener(o.fatalErrorEvent,e)}exports.Logger=f;exports.addFatalErrorListener=w;exports.collectPhpLogs=h;exports.collectWindowErrors=g;exports.logger=c;
1
+ "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;
package/index.mjs CHANGED
@@ -1,42 +1,42 @@
1
1
  const u = function() {
2
- var o;
3
- return typeof process < "u" && ((o = process.release) == null ? void 0 : o.name) === "node" ? "NODE" : typeof window < "u" ? "WEB" : (
2
+ var n;
3
+ return typeof process < "u" && ((n = process.release) == null ? void 0 : n.name) === "node" ? "NODE" : typeof window < "u" ? "WEB" : (
4
4
  // @ts-ignore
5
5
  typeof WorkerGlobalScope < "u" && // @ts-ignore
6
6
  self instanceof WorkerGlobalScope ? "WORKER" : "NODE"
7
7
  );
8
8
  }();
9
9
  if (u === "NODE") {
10
- let o = function(t) {
11
- return new Promise(function(r, n) {
12
- t.onload = t.onerror = function(s) {
13
- t.onload = t.onerror = null, s.type === "load" ? r(t.result) : n(new Error("Failed to read the blob/file"));
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
14
  };
15
15
  });
16
16
  }, e = function() {
17
- const t = new Uint8Array([1, 2, 3, 4]), n = new File([t], "test").stream();
17
+ const t = new Uint8Array([1, 2, 3, 4]), o = new File([t], "test").stream();
18
18
  try {
19
- return n.getReader({ mode: "byob" }), !0;
19
+ return o.getReader({ mode: "byob" }), !0;
20
20
  } catch {
21
21
  return !1;
22
22
  }
23
23
  };
24
24
  if (typeof File > "u") {
25
25
  class t extends Blob {
26
- constructor(n, s, a) {
27
- super(n);
28
- let i;
29
- a != null && a.lastModified && (i = /* @__PURE__ */ new Date()), (!i || isNaN(i.getFullYear())) && (i = /* @__PURE__ */ new Date()), this.lastModifiedDate = i, this.lastModified = i.getMilliseconds(), this.name = s || "";
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
30
  }
31
31
  }
32
32
  global.File = t;
33
33
  }
34
34
  typeof Blob.prototype.arrayBuffer > "u" && (Blob.prototype.arrayBuffer = function() {
35
35
  const r = new FileReader();
36
- return r.readAsArrayBuffer(this), o(r);
36
+ return r.readAsArrayBuffer(this), n(r);
37
37
  }), typeof Blob.prototype.text > "u" && (Blob.prototype.text = function() {
38
38
  const r = new FileReader();
39
- return r.readAsText(this), o(r);
39
+ return r.readAsText(this), n(r);
40
40
  }), (typeof Blob.prototype.stream > "u" || !e()) && (Blob.prototype.stream = function() {
41
41
  let t = 0;
42
42
  const r = this;
@@ -45,31 +45,31 @@ if (u === "NODE") {
45
45
  // 0.5 MB seems like a reasonable chunk size, let's adjust
46
46
  // this if needed.
47
47
  autoAllocateChunkSize: 512 * 1024,
48
- async pull(n) {
49
- const s = n.byobRequest.view, i = await r.slice(
48
+ async pull(o) {
49
+ const i = o.byobRequest.view, s = await r.slice(
50
50
  t,
51
- t + s.byteLength
52
- ).arrayBuffer(), d = new Uint8Array(i);
53
- new Uint8Array(s.buffer).set(d);
51
+ t + i.byteLength
52
+ ).arrayBuffer(), d = new Uint8Array(s);
53
+ new Uint8Array(i.buffer).set(d);
54
54
  const l = d.byteLength;
55
- n.byobRequest.respond(l), t += l, t >= r.size && n.close();
55
+ o.byobRequest.respond(l), t += l, t >= r.size && o.close();
56
56
  }
57
57
  });
58
58
  });
59
59
  }
60
60
  if (u === "NODE" && typeof CustomEvent > "u") {
61
- class o extends Event {
61
+ class n extends Event {
62
62
  constructor(t, r = {}) {
63
63
  super(t, r), this.detail = r.detail;
64
64
  }
65
65
  initCustomEvent() {
66
66
  }
67
67
  }
68
- globalThis.CustomEvent = o;
68
+ globalThis.CustomEvent = n;
69
69
  }
70
70
  class f extends EventTarget {
71
71
  constructor(e) {
72
- super(), this.fatalErrorEvent = "playground-fatal-error", this.logs = [], this.windowConnected = !1, this.lastPHPLogLength = 0, this.errorLogPath = "/wordpress/wp-content/debug.log", e && (this.errorLogPath = 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
73
  }
74
74
  /**
75
75
  * Read the WordPress debug.log file and return its content.
@@ -114,6 +114,18 @@ class f extends EventTarget {
114
114
  this.logUnhandledRejection.bind(this)
115
115
  ), this.windowConnected = !0);
116
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
+ }
117
129
  /**
118
130
  * Register a listener for the request.end event and log the data.
119
131
  * @param UniversalPHP playground instance
@@ -176,12 +188,12 @@ class f extends EventTarget {
176
188
  */
177
189
  log(e, t, r) {
178
190
  t === void 0 && (t = "Info");
179
- const n = this.formatMessage(
191
+ const o = this.formatMessage(
180
192
  e,
181
193
  t,
182
194
  r ?? "Playground"
183
195
  );
184
- this.logRaw(n);
196
+ this.logRaw(o);
185
197
  }
186
198
  /**
187
199
  * Log message without severity and timestamp.
@@ -195,23 +207,55 @@ class f extends EventTarget {
195
207
  * @returns string[]
196
208
  */
197
209
  getLogs() {
198
- return this.logs;
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 };
199
223
  }
200
224
  }
201
225
  const c = new f();
202
- function h(o) {
203
- o.addWindowErrorListener();
226
+ function h(n) {
227
+ n.addWindowErrorListener(), n.addServiceWorkerMessageListener();
228
+ }
229
+ function g(n, e) {
230
+ n.addPlaygroundRequestEndListener(e);
204
231
  }
205
- function g(o, e) {
206
- o.addPlaygroundRequestEndListener(e);
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
+ });
207
250
  }
208
- function w(o, e) {
209
- o.addEventListener(o.fatalErrorEvent, e);
251
+ function w(n, e) {
252
+ n.addEventListener(n.fatalErrorEvent, e);
210
253
  }
211
254
  export {
212
255
  f as Logger,
213
- w as addFatalErrorListener,
256
+ w as addCrashListener,
214
257
  g as collectPhpLogs,
215
258
  h as collectWindowErrors,
216
- c as logger
259
+ c as logger,
260
+ m as reportServiceWorkerMetrics
217
261
  };
package/lib/logger.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ /// <reference lib="webworker" />
1
2
  import { UniversalPHP } from '../../../universal/src/index.ts/src/lib/universal-php';
2
3
  /**
3
4
  * Log severity levels.
@@ -24,6 +25,10 @@ export declare class Logger extends EventTarget {
24
25
  * The length of the last PHP log.
25
26
  */
26
27
  private lastPHPLogLength;
28
+ /**
29
+ * Context data
30
+ */
31
+ private context;
27
32
  /**
28
33
  * The path to the error log file.
29
34
  */
@@ -52,6 +57,11 @@ export declare class Logger extends EventTarget {
52
57
  * Register a listener for the window error events and log the data.
53
58
  */
54
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.
63
+ */
64
+ addServiceWorkerMessageListener(): void;
55
65
  /**
56
66
  * Register a listener for the request.end event and log the data.
57
67
  * @param UniversalPHP playground instance
@@ -88,6 +98,14 @@ export declare class Logger extends EventTarget {
88
98
  * @returns string[]
89
99
  */
90
100
  getLogs(): string[];
101
+ /**
102
+ * Add context data.
103
+ */
104
+ addContext(data: Record<string, any>): void;
105
+ /**
106
+ * Get context data.
107
+ */
108
+ getContext(): Record<string, any>;
91
109
  }
92
110
  /**
93
111
  * The logger instance.
@@ -105,11 +123,21 @@ export declare function collectWindowErrors(loggerInstance: Logger): void;
105
123
  */
106
124
  export declare function collectPhpLogs(loggerInstance: Logger, playground: UniversalPHP): void;
107
125
  /**
108
- * Add a listener for the fatal Playground errors.
109
- * These errors include Playground errors like Asyncify errors. PHP errors won't trigger this event.
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;
135
+ /**
136
+ * Add a listener for the Playground crashes.
137
+ * These crashes include Playground errors like Asyncify errors.
110
138
  * The callback function will receive an Event object with logs in the detail property.
111
139
  *
112
140
  * @param loggerInstance The logger instance
113
141
  * @param callback The callback function
114
142
  */
115
- export declare function addFatalErrorListener(loggerInstance: Logger, callback: EventListenerOrEventListenerObject): void;
143
+ export declare function 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.6.15",
3
+ "version": "0.7.0",
4
4
  "description": "A logger for PHP-wasm clients like Playground and WP-now.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -25,5 +25,5 @@
25
25
  "node": ">=18.18.0",
26
26
  "npm": ">=8.11.0"
27
27
  },
28
- "gitHead": "e05126da329a26535905b0ab65415d20118f0197"
28
+ "gitHead": "c5eba3d709f2821c4303521e8c81b962e3bcca23"
29
29
  }