A lightweight, structured logging and persistence library for Waze Map Editor (WME) userscripts and extensions.
WME LogStream is an asynchronous logging framework designed for developers building userscripts and extensions for the Waze Map Editor (WME).
It handles console branding, multi-tab safe IndexedDB persistence, state delta diffing, and log exporting with a unified, zero-boilerplate API.
- π² Hierarchical Scoping: Scope loggers to specific components (e.g.,
[MyScript] [API] [Auth]). - π¨ Custom Console Styling: Style console output with custom brand colors and prefixes.
- πΎ Asynchronous Persistence: Buffers and persists logs locally to IndexedDB in the background.
- π₯ Multi-Tab Isolation: Prevents session collisions when the editor is open in multiple browser tabs.
- β‘ State Delta Tracking: Deep-diff state objects over time and log only modified properties.
- π¦ Zip Archive Export & Download: Bundle and download stored log sessions directly from the browser.
The library decouples logging API interactions from storage and console outputs:
graph TD
LS[LogStream] -->|Dispatches LogPayload| Dispatcher[Dispatcher]
Dispatcher -->|write| CP[ConsolePipe]
Dispatcher -->|write| IDBP[IndexedDBPipe]
CP --> C[Developer Console]
IDBP --> IDBM[IndexedDBManager]
IDBM --> IDB[(IndexedDB)]
SM[SessionManager] -.-> IDBM
ZS[ZipStreamer] --> IDBM
ZS --> Z[ZIP File Blob]
Install via npm for projects using a bundler (Webpack, Rollup, Vite):
npm install wme-logstreamThen import LogStream in your modules:
import { LogStream } from 'wme-logstream';To load the pre-built global IIFE library directly in your userscript, import it using jsDelivr pointing to the npm package:
// @require https://cdn.jsdelivr.net/npm/editor-x/wme-logstream@latest/dist/index.iife.jsThe library will be available on the global window object as EditorXLogStream.
If you only want customized console logging, setup is synchronous and instant:
import { LogStream } from 'wme-logstream';
const logger = LogStream.create({
minLogLevel: 'DEBUG',
brand: {
prefix: 'MyScript',
color: '#00E676',
},
});
logger.info('Logger initialized.');
logger.debug('Fetching details...', { segmentId: 12345 });To automatically persist log history in IndexedDB with safe multi-tab isolation, simply toggle persist: true. The library handles the asynchronous database and session setup in the background:
import { LogStream } from 'wme-logstream';
const logger = LogStream.create({
minLogLevel: 'DEBUG',
persist: true,
dbPrefix: 'MyScriptDB',
scriptVersion: '1.0.0',
wmeSDK: getWmeSdk({ scriptId: 'myscript', scriptName: 'MyScript' }), // Recommended. Pass an SDK instance.
brand: { prefix: 'MyScript' },
});
// Logs are safely buffered and queued immediately on page load!
logger.info('Script loaded and database logging is active.');Loggers can be nested to show context hierarchies:
const apiLogger = logger.scope('API');
const authLogger = apiLogger.scope('Auth');
logger.info('Starting...'); // [MyScript] [INFO] Starting...
apiLogger.debug('Connecting'); // [MyScript] [DEBUG][API] Connecting
authLogger.error('Failed'); // [MyScript] [ERROR][API][Auth] FailedTrack state mutations over time by logging only differences. You can create a state tracker function:
const trackSettings = logger.createStateTracker('editorSettings');
const state = { theme: 'dark', visibleLayers: ['segments'] };
// Initial state call logs the base state
trackSettings(state);
// Subsequent calls calculate and log only the changed properties
trackSettings({ theme: 'light', visibleLayers: ['segments'] });
// Logs only: { theme: ['dark', 'light'] }Provide users with a simple way to download troubleshooting logs as a compressed ZIP file directly in the browser:
// Triggers a browser download of a zipped archive of all archived log sessions
await logger.downloadLogs('my-script-logs.zip');If you need to retrieve the raw compressed Blob (e.g. to upload to a remote server instead of downloading it):
const zipBlob = await logger.exportLogs();| Property | Type | Default | Description |
|---|---|---|---|
minLogLevel |
'TRACE' | 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | 'FATAL' |
'INFO' |
Minimum level of severity required to log. |
persist |
boolean |
false |
Enable/disable background IndexedDB persistence. |
dbPrefix |
string |
Required if persist is true | Name prefix for the IndexedDB database. |
scriptVersion |
string |
Required if persist is true | Current version of your script/extension. |
wmeSDK |
WmeSDK |
undefined |
Native WME SDK instance to query editor versions. |
maxArchivedSessions |
number |
15 |
Maximum number of archived database sessions to preserve. |
flushIntervalMs |
number |
2000 |
Asynchronous log flush rate to IndexedDB (in ms). |
brand |
ConsolePipeConfig | null |
undefined |
Custom branding config for console outputs (set to null to disable). |
| Property | Type | Default | Description |
|---|---|---|---|
scriptPrefix |
string |
'EditorX' |
Tag prefix displayed in log entries. |
brandColor |
string |
'#00E676' |
Hex color of the brand prefix. |
Install dependencies:
npm installAvailable scripts:
npm run build # Build package distributions (ESM, CJS, IIFE)
npm run test # Run unit tests
npm run lint # Run ESLint validation
npm run format # Run Prettier format check and fixesThis project is licensed under the Apache-2.0 License. See the LICENSE file for details.