@hkdigital/lib-core 0.4.35 → 0.4.36
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/CLAUDE.md
CHANGED
|
@@ -38,6 +38,12 @@ This is a modern SvelteKit library built with Svelte 5 and Skeleton.dev v3 compo
|
|
|
38
38
|
- English for all documentation and comments
|
|
39
39
|
- No dollar signs in variable names (reserved for Svelte)
|
|
40
40
|
|
|
41
|
+
### Testing Commands
|
|
42
|
+
- Run all tests: `pnpm test`
|
|
43
|
+
- Run specific test file: `pnpm test:file path/to/test.js`
|
|
44
|
+
- Run tests in directory: `pnpm test:file src/lib/logging/`
|
|
45
|
+
- Use `pnpm test:file` for single test execution - it's cross-platform compatible
|
|
46
|
+
|
|
41
47
|
### ESLint Rule Suppression
|
|
42
48
|
- Use specific rule suppression instead of blanket disables
|
|
43
49
|
- For unused variables in method signatures (e.g., base class methods to be overridden):
|
package/dist/logging/README.md
CHANGED
|
@@ -103,40 +103,92 @@ export async function handle({ event, resolve }) {
|
|
|
103
103
|
### Client-side logging (src/hooks.client.js)
|
|
104
104
|
|
|
105
105
|
```javascript
|
|
106
|
-
import {
|
|
106
|
+
import { initClientServices } from '$lib/services/client.js';
|
|
107
|
+
import { getClientLogger } from '$lib/logging/client.js';
|
|
107
108
|
|
|
108
|
-
|
|
109
|
+
export async function init() {
|
|
110
|
+
// Init services
|
|
111
|
+
try {
|
|
112
|
+
await initClientServices();
|
|
113
|
+
|
|
114
|
+
getClientLogger().info('Client initialization complete');
|
|
115
|
+
} catch (error) {
|
|
116
|
+
getClientLogger().error('Client initialization failed',
|
|
117
|
+
/** @type {Error} */ (error));
|
|
118
|
+
// throw error;
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
getClientLogger().info('Client application initialized', {
|
|
122
|
+
userAgent: navigator.userAgent,
|
|
123
|
+
viewport: `${window.innerWidth}x${window.innerHeight}`
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
109
127
|
|
|
110
128
|
/** @type {import('@sveltejs/kit').HandleClientError} */
|
|
111
129
|
export function handleError({ error, event }) {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
130
|
+
// Handle SvelteKit-specific errors:
|
|
131
|
+
// navigation errors, load function failures, component errors, ...
|
|
132
|
+
getClientLogger().error(/** @type {Error} */ (error), {
|
|
133
|
+
url: event.url?.pathname,
|
|
134
|
+
userAgent: navigator.userAgent
|
|
115
135
|
});
|
|
116
136
|
}
|
|
137
|
+
```
|
|
117
138
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
logger
|
|
133
|
-
|
|
139
|
+
### Client Service Integration
|
|
140
|
+
|
|
141
|
+
When integrating with a service management system, you can set up global
|
|
142
|
+
error handling and forward service logs to the main logger:
|
|
143
|
+
|
|
144
|
+
```javascript
|
|
145
|
+
import { ServiceManager } from '$hklib-core/services/index.js';
|
|
146
|
+
import { initClientLogger } from '$lib/logging/client.js';
|
|
147
|
+
|
|
148
|
+
/** @type {ServiceManager} */
|
|
149
|
+
let manager;
|
|
150
|
+
|
|
151
|
+
export async function initClientServices() {
|
|
152
|
+
if (!manager) {
|
|
153
|
+
const logger = initClientLogger();
|
|
154
|
+
|
|
155
|
+
// Catch errors and unhandled promise rejections
|
|
156
|
+
|
|
157
|
+
// Log unhandled errors
|
|
158
|
+
window.addEventListener('error', (event) => {
|
|
159
|
+
logger.error(event, { url: window.location.pathname });
|
|
160
|
+
event.preventDefault();
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// Log unhandled promise rejections
|
|
164
|
+
window.addEventListener('unhandledrejection', (event) => {
|
|
165
|
+
logger.error(event, { url: window.location.pathname });
|
|
166
|
+
// Ignored by Firefox
|
|
167
|
+
event.preventDefault();
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
manager = new ServiceManager({ debug: true });
|
|
171
|
+
|
|
172
|
+
// Listen to all log events and forward them to the logger
|
|
173
|
+
manager.onLogEvent((logEvent) => {
|
|
174
|
+
logger.logFromEvent(logEvent);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// Register services
|
|
178
|
+
manager.register(SERVICE_AUDIO, AudioService);
|
|
179
|
+
manager.register(SERVICE_EVENT_LOG, EventLogService);
|
|
180
|
+
manager.register(SERVICE_PLAYER_DATA, PlayerDataService);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
await manager.startAll();
|
|
184
|
+
return manager;
|
|
134
185
|
}
|
|
135
186
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
187
|
+
export function getManager() {
|
|
188
|
+
if (!manager) {
|
|
189
|
+
throw new Error('Client services should be initialised first');
|
|
190
|
+
}
|
|
191
|
+
return manager;
|
|
140
192
|
}
|
|
141
193
|
```
|
|
142
194
|
|
|
@@ -381,8 +381,22 @@ export class ConsoleAdapter {
|
|
|
381
381
|
'node_modules/vite-deps'
|
|
382
382
|
);
|
|
383
383
|
|
|
384
|
+
// Clean up pnpm paths - convert complex pnpm paths to simple package names
|
|
385
|
+
// Before: node_modules/.pnpm/@hkdigital+lib-core@0.4.35_@eslint+js@9.35.0_.../node_modules/@hkdigital/lib-core/dist/...
|
|
386
|
+
// After: @hkdigital/lib-core/dist/...
|
|
387
|
+
cleaned = cleaned.replace(
|
|
388
|
+
/node_modules\/\.pnpm\/([^\/]+)@[^_]+[^\/]*\/node_modules\/([^\/]+(?:\/[^\/]+)?)\//g,
|
|
389
|
+
'$2/'
|
|
390
|
+
);
|
|
391
|
+
|
|
392
|
+
// Clean up regular node_modules paths for known HK packages
|
|
393
|
+
cleaned = cleaned.replace(
|
|
394
|
+
/node_modules\/@hkdigital\/([^\/]+)\//g,
|
|
395
|
+
'@hkdigital/$1/'
|
|
396
|
+
);
|
|
397
|
+
|
|
384
398
|
// Clean up query parameters on source files
|
|
385
|
-
cleaned = cleaned.replace(/\?
|
|
399
|
+
cleaned = cleaned.replace(/\?[tv]=[a-f0-9]+/g, '');
|
|
386
400
|
|
|
387
401
|
// Skip vite-deps (Svelte framework internals) but keep other node_modules
|
|
388
402
|
if (cleaned.includes('node_modules/vite-deps')) {
|
|
@@ -404,8 +404,6 @@ export function isMeaningfulFunctionName(functionName) {
|
|
|
404
404
|
if (
|
|
405
405
|
!functionName ||
|
|
406
406
|
functionName === '' ||
|
|
407
|
-
functionName.includes('<') ||
|
|
408
|
-
functionName.includes('/') ||
|
|
409
407
|
functionName.startsWith('async ') ||
|
|
410
408
|
functionName === 'async' ||
|
|
411
409
|
functionName === 'Promise' ||
|
|
@@ -416,6 +414,13 @@ export function isMeaningfulFunctionName(functionName) {
|
|
|
416
414
|
return false;
|
|
417
415
|
}
|
|
418
416
|
|
|
417
|
+
// Skip pure anonymous functions (just '<' without a parent function name)
|
|
418
|
+
if (functionName === '<' || functionName === '</') {
|
|
419
|
+
return false;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// Allow function names that contain '/<' (anonymous functions within named functions)
|
|
423
|
+
// These are meaningful as they show "parentFunction/<anonymous>"
|
|
419
424
|
return true;
|
|
420
425
|
}
|
|
421
426
|
|
|
@@ -429,17 +434,35 @@ export function parseFunctionName(frame) {
|
|
|
429
434
|
// Handle both Firefox format: "functionName@file:line:col"
|
|
430
435
|
// and Node.js format: "at functionName (file:line:col)" or "at Module.functionName (file:line:col)"
|
|
431
436
|
|
|
437
|
+
let functionName = null;
|
|
438
|
+
|
|
432
439
|
// Firefox format
|
|
433
440
|
const firefoxMatch = frame.match(/^([^@]+)@/);
|
|
434
441
|
if (firefoxMatch) {
|
|
435
|
-
|
|
442
|
+
functionName = firefoxMatch[1];
|
|
443
|
+
} else {
|
|
444
|
+
// Node.js format
|
|
445
|
+
const nodeMatch = frame.match(/^\s*at\s+(?:Module\.)?([^\s(]+)/);
|
|
446
|
+
if (nodeMatch) {
|
|
447
|
+
functionName = nodeMatch[1];
|
|
448
|
+
}
|
|
436
449
|
}
|
|
437
450
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
if (nodeMatch) {
|
|
441
|
-
return nodeMatch[1];
|
|
451
|
+
if (!functionName) {
|
|
452
|
+
return null;
|
|
442
453
|
}
|
|
443
454
|
|
|
444
|
-
|
|
455
|
+
// Clean up common patterns
|
|
456
|
+
functionName = functionName.trim();
|
|
457
|
+
|
|
458
|
+
// Handle anonymous functions within named functions
|
|
459
|
+
// Convert "functionName/<" to "functionName (anonymous)"
|
|
460
|
+
if (functionName.endsWith('/<')) {
|
|
461
|
+
const baseName = functionName.slice(0, -2);
|
|
462
|
+
if (baseName) {
|
|
463
|
+
functionName = `${baseName} (anonymous)`;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
return functionName;
|
|
445
468
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hkdigital/lib-core",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.36",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "HKdigital",
|
|
6
6
|
"url": "https://hkdigital.nl"
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"format": "prettier --write .",
|
|
28
28
|
"lint": "run-s lint:*",
|
|
29
29
|
"test": "run-s test:unit-run",
|
|
30
|
+
"test:file": "vitest run",
|
|
30
31
|
"prepack": "run-s prepack:*",
|
|
31
32
|
"publish:npm": "run-s publish:npm:version publish:npm:publish git:push",
|
|
32
33
|
"upgrade:hk": "run-s upgrade:hk:update pnpm:install",
|