@hkdigital/lib-core 0.4.28 → 0.4.30
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 +350 -0
- package/README.md +10 -4
- package/dist/logging/index.d.ts +1 -1
- package/dist/logging/index.js +2 -2
- package/dist/logging/internal/adapters/console.js +1 -1
- package/dist/logging/internal/factories/client.js +1 -1
- package/dist/logging/internal/factories/server.js +1 -1
- package/dist/logging/internal/logger/Logger.js +1 -1
- package/dist/services/README.md +36 -2
- package/dist/services/service-manager/ServiceManager.d.ts +24 -4
- package/dist/services/service-manager/ServiceManager.js +84 -52
- package/dist/services/service-manager/constants.d.ts +2 -0
- package/dist/services/service-manager/constants.js +3 -0
- package/dist/services/service-manager/typedef.d.ts +8 -19
- package/dist/services/service-manager/typedef.js +6 -11
- package/dist/services/service-manager/util.d.ts +35 -0
- package/dist/services/service-manager/util.js +90 -0
- package/dist/state/machines/finite-state-machine/constants.js +2 -2
- package/package.json +7 -4
- /package/dist/logging/{constants.d.ts → levels.d.ts} +0 -0
- /package/dist/logging/{constants.js → levels.js} +0 -0
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
# SvelteKit Library
|
|
2
|
+
|
|
3
|
+
## Project Overview
|
|
4
|
+
This is a modern SvelteKit library built with Svelte 5 and Skeleton.dev v3 components. The project emphasizes accessibility, clean code standards, and modern JavaScript patterns.
|
|
5
|
+
|
|
6
|
+
## Architecture & Structure
|
|
7
|
+
- **Framework**: SvelteKit with Svelte 5 runes
|
|
8
|
+
- **UI Components**: Skeleton.dev version 3
|
|
9
|
+
- **Package Manager**: PNPM
|
|
10
|
+
- **Language**: Modern JavaScript (ES6+), no TypeScript
|
|
11
|
+
- **Module System**: ES Modules only (import/export)
|
|
12
|
+
|
|
13
|
+
## Key Technical Decisions
|
|
14
|
+
- Uses Svelte 5 runes (`$state()`, `$derived()`, `$effect()`, `$props()`) for state management
|
|
15
|
+
- Snippet syntax with `{@render children()}` instead of deprecated `<slot />`
|
|
16
|
+
- WCAG 2.1 Level AA accessibility compliance
|
|
17
|
+
- 80-character line limit with rare exceptions
|
|
18
|
+
- Two-space indentation
|
|
19
|
+
- Descriptive camelCase naming conventions
|
|
20
|
+
|
|
21
|
+
## Component Patterns
|
|
22
|
+
- All components use `let { ... } = $props()` with JSDoc type annotations
|
|
23
|
+
- Props always include `classes` and `...attrs` for flexibility
|
|
24
|
+
- Event handlers use Svelte 5 syntax (`onclick`, `onchange`)
|
|
25
|
+
- Snippet props typed as `import('svelte').Snippet`
|
|
26
|
+
- Private methods use hash prefix (`#methodName`)
|
|
27
|
+
|
|
28
|
+
## JavaScript Class Patterns
|
|
29
|
+
- Use modern ES private methods with hash prefix: `#methodName()` instead of `_methodName()`
|
|
30
|
+
- Private fields also use hash prefix: `#privateField`
|
|
31
|
+
- Apply this to all JavaScript classes, not just Svelte components
|
|
32
|
+
- Never use `@private` in JSDoc for methods that start with `#` - the hash already indicates privacy
|
|
33
|
+
|
|
34
|
+
## Development Standards
|
|
35
|
+
- Readable code over concise code
|
|
36
|
+
- Explicit error handling with try/catch for async operations
|
|
37
|
+
- JSDoc comments for all functions and variables
|
|
38
|
+
- English for all documentation and comments
|
|
39
|
+
- No dollar signs in variable names (reserved for Svelte)
|
|
40
|
+
|
|
41
|
+
### ESLint Rule Suppression
|
|
42
|
+
- Use specific rule suppression instead of blanket disables
|
|
43
|
+
- For unused variables in method signatures (e.g., base class methods to be overridden):
|
|
44
|
+
```javascript
|
|
45
|
+
// eslint-disable-next-line no-unused-vars
|
|
46
|
+
async _configure(newConfig, oldConfig = null) {
|
|
47
|
+
// Override in subclass
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Documentation & Comment Style
|
|
52
|
+
- **80-character line limit** - strictly enforce for ALL code and documentation
|
|
53
|
+
- Applies to code lines, JSDoc comments, parameter descriptions, and all text
|
|
54
|
+
- Wrap long JSDoc descriptions across multiple lines
|
|
55
|
+
- Break long parameter lists and descriptions at 80 characters
|
|
56
|
+
- **JSDoc formatting conventions:**
|
|
57
|
+
- Blank line between description and first `@param`
|
|
58
|
+
- Blank line between last `@param` and `@returns`
|
|
59
|
+
- No blank lines between consecutive `@param` tags with short descriptions
|
|
60
|
+
- Add extra newlines between `@param` entries ONLY when they have multi-line descriptions for better readability
|
|
61
|
+
- For long parameter types or descriptions, place description on next line:
|
|
62
|
+
```javascript
|
|
63
|
+
// Multi-line @param descriptions (use extra newlines between)
|
|
64
|
+
/**
|
|
65
|
+
* Convert a path string to an array path
|
|
66
|
+
*
|
|
67
|
+
* @param {string|string[]} path
|
|
68
|
+
* String or array path (e.g. "some.path.to")
|
|
69
|
+
*
|
|
70
|
+
* @param {string} [pathSeparator=PATH_SEPARATOR]
|
|
71
|
+
* A custom path separator to use instead of the default "."
|
|
72
|
+
*
|
|
73
|
+
* @returns {string[]} array path (e.g. ["some", "path", "to"])
|
|
74
|
+
*/
|
|
75
|
+
|
|
76
|
+
// Short descriptions (no extra newlines needed)
|
|
77
|
+
/**
|
|
78
|
+
* Log an info message
|
|
79
|
+
*
|
|
80
|
+
* @param {string} message - Log message
|
|
81
|
+
* @param {*} [details] - Additional details
|
|
82
|
+
*
|
|
83
|
+
* @returns {boolean} True if the log was emitted
|
|
84
|
+
*/
|
|
85
|
+
```
|
|
86
|
+
- **Concise descriptions** - avoid obvious/redundant explanations
|
|
87
|
+
- Keep only essential information that adds value for developers
|
|
88
|
+
- Remove descriptions that simply restate parameter names or types
|
|
89
|
+
- Examples:
|
|
90
|
+
- ✅ `@property {number} [exp] - Expiration time (seconds since epoch)`
|
|
91
|
+
- ❌ `@property {number} [exp] - Expiration time - timestamp when the JWT expires`
|
|
92
|
+
- ✅ `@property {boolean} [ignoreExpiration] - Skip expiration validation`
|
|
93
|
+
- ❌ `@property {boolean} [ignoreExpiration] - If true, do not validate the expiration of the token`
|
|
94
|
+
|
|
95
|
+
## Writing Style
|
|
96
|
+
- Use normal English capitalization rules - avoid unnecessary capitals
|
|
97
|
+
- Don't capitalize common nouns like "server", "client", "button", "error", "validation", etc.
|
|
98
|
+
- Only capitalize proper nouns, beginnings of sentences, and official names
|
|
99
|
+
- Examples:
|
|
100
|
+
- ✅ "server-side validation" not "Server-side Validation"
|
|
101
|
+
- ✅ "expect function" not "Expect Function"
|
|
102
|
+
- ✅ "client error" not "Client Error"
|
|
103
|
+
- ✅ "JavaScript" (proper noun) but "validation error" (common noun)
|
|
104
|
+
|
|
105
|
+
## Import Path Conventions
|
|
106
|
+
- Use `$lib/domain/...` imports for cross-domain references (e.g., `$lib/media/image.js`, `$lib/network/http.js`)
|
|
107
|
+
- Use relative imports (`./` or `../`) when staying within the same main folder under `$lib`
|
|
108
|
+
- **Always include file extensions** (`.js`, `.svelte`) in import statements
|
|
109
|
+
- **For cross-domain imports, use specific export files** (e.g., `parsers.js`, `valibot.js`) rather than directory-only paths - this ensures compatibility outside the library
|
|
110
|
+
- **For local imports within the same domain**, import specific files directly (e.g., `./ClassName.js`) rather than using local index files
|
|
111
|
+
- Examples:
|
|
112
|
+
- ✅ `import { ImageLoader } from '$lib/media/image.js'` (cross-domain import)
|
|
113
|
+
- ✅ `import ImageLoader from './ImageLoader.svelte.js'` (local import within same domain)
|
|
114
|
+
- ✅ `import IterableTree from './IterableTree.js'` (local import within same domain)
|
|
115
|
+
- ✅ `import { v } from '$lib/valibot/valibot.js'` (cross-domain with specific export file)
|
|
116
|
+
- ✅ `import { HumanUrl, Email } from '$lib/valibot/parsers.js'` (cross-domain with specific export file)
|
|
117
|
+
- ❌ `import { v, HumanUrl } from '$lib/valibot'` (missing specific export file)
|
|
118
|
+
- ❌ `import { IterableTree } from './index.js'` (local index when specific file should be used)
|
|
119
|
+
- ❌ `import something from '../../media/image.js'` (cross-domain relative import)
|
|
120
|
+
|
|
121
|
+
## Class Export Conventions
|
|
122
|
+
- **All classes should be default exports**: `export default class ClassName`
|
|
123
|
+
- **Import classes without destructuring**: `import ClassName from './ClassName.js'`
|
|
124
|
+
- Examples:
|
|
125
|
+
- ✅ `export default class HkPromise extends Promise {}`
|
|
126
|
+
- ✅ `import HkPromise from './HkPromise.js'`
|
|
127
|
+
- ❌ `export class HkPromise extends Promise {}` (named export)
|
|
128
|
+
- ❌ `import { HkPromise } from './HkPromise.js'` (destructuring import)
|
|
129
|
+
|
|
130
|
+
## Accessibility Requirements
|
|
131
|
+
- Proper ARIA roles, states, and properties
|
|
132
|
+
- Descriptive aria-labels for interactive elements
|
|
133
|
+
- Keyboard navigation support
|
|
134
|
+
- Logical tab order and focus management
|
|
135
|
+
- Proper heading hierarchy
|
|
136
|
+
- Screen reader compatibility (VoiceOver, NVDA)
|
|
137
|
+
|
|
138
|
+
## Common Patterns to Follow
|
|
139
|
+
- Server/client code separation in SvelteKit
|
|
140
|
+
- Clear component hierarchy
|
|
141
|
+
- Minimal, targeted changes to working code
|
|
142
|
+
- Ask before making assumptions about existing structure
|
|
143
|
+
- Focus on specific requests rather than general improvements
|
|
144
|
+
|
|
145
|
+
## Design System Usage in Examples
|
|
146
|
+
|
|
147
|
+
When creating examples in `routes/examples/`, always use the HKdigital Design System:
|
|
148
|
+
|
|
149
|
+
### Typography
|
|
150
|
+
- Use complete typography classes: `type-heading-h1`, `type-base-md`, `type-ui-sm`
|
|
151
|
+
- Include dark mode variants when relevant: `type-heading-h1-dark`
|
|
152
|
+
- Never use raw Tailwind text classes like `text-lg` - use `text-base-lg` instead
|
|
153
|
+
|
|
154
|
+
### Spacing
|
|
155
|
+
- Use UI points for element spacing: `p-20up`, `m-10up`, `gap-16up`
|
|
156
|
+
- Use text-based spacing for typography-related spacing: `mb-16bt`, `mt-12ut`
|
|
157
|
+
- Never use raw Tailwind spacing like `p-4` - use `p-4up` instead
|
|
158
|
+
|
|
159
|
+
### Colors
|
|
160
|
+
- Use themed colors: `bg-primary-500`, `bg-surface-100`, `text-error-500`
|
|
161
|
+
- Always use contrast colors for accessibility: `text-primary-contrast-500`
|
|
162
|
+
- Include both light and dark mode considerations
|
|
163
|
+
|
|
164
|
+
### Layout & Components
|
|
165
|
+
- Use design system utilities: `rounded-md`, `border-width-normal`
|
|
166
|
+
- Follow the responsive scaling system built around 1024×768 design reference
|
|
167
|
+
- Use component data attributes: `data-component="button"` `data-role="primary"`
|
|
168
|
+
|
|
169
|
+
### Custom Styling for Examples
|
|
170
|
+
When examples require custom CSS beyond the design system:
|
|
171
|
+
|
|
172
|
+
- Always add a `data-page` attribute to the outer page element
|
|
173
|
+
- Create a `style.css` file alongside the `+page.svelte` file
|
|
174
|
+
- Use `<style src="./style.css"></style>` to include the styles
|
|
175
|
+
- Scope all CSS rules under `[data-page]` to prevent global conflicts
|
|
176
|
+
- Use CSS nesting syntax for better organization
|
|
177
|
+
|
|
178
|
+
**Example structure:**
|
|
179
|
+
```svelte
|
|
180
|
+
<!-- +page.svelte -->
|
|
181
|
+
<div data-page>
|
|
182
|
+
<div data-section="content">
|
|
183
|
+
<!-- example content -->
|
|
184
|
+
</div>
|
|
185
|
+
</div>
|
|
186
|
+
|
|
187
|
+
<style src="./style.css"></style>
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
```css
|
|
191
|
+
/* style.css */
|
|
192
|
+
[data-page] {
|
|
193
|
+
& [data-section="content"] {
|
|
194
|
+
/* scoped styles here */
|
|
195
|
+
position: relative;
|
|
196
|
+
padding: 20px;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
& .custom-element {
|
|
200
|
+
/* more scoped styles */
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Structure
|
|
206
|
+
- Always include proper heading hierarchy (`type-heading-h1`, `type-heading-h2`, etc.)
|
|
207
|
+
- Use semantic HTML with appropriate ARIA attributes
|
|
208
|
+
- Follow WCAG 2.1 Level AA accessibility guidelines
|
|
209
|
+
|
|
210
|
+
### UI Components
|
|
211
|
+
- Always use components from `$lib/ui/primitives/` when available
|
|
212
|
+
- Prefer the `Button` component over raw `<button>` elements
|
|
213
|
+
- Import from the index: `import { Button } from '$lib/ui/primitives.js'`
|
|
214
|
+
- Use snippet syntax: `<Button>{content}</Button>` instead of slot syntax
|
|
215
|
+
|
|
216
|
+
### Example Template
|
|
217
|
+
```svelte
|
|
218
|
+
<script>
|
|
219
|
+
import { Button } from '$lib/ui/primitives.js';
|
|
220
|
+
</script>
|
|
221
|
+
|
|
222
|
+
<div class="container mx-auto p-20up" data-page>
|
|
223
|
+
<h1 class="type-heading-h1 mb-20up">Example Title</h1>
|
|
224
|
+
|
|
225
|
+
<div class="card p-20up mb-20up">
|
|
226
|
+
<p class="type-base-md mb-12bt">Description text</p>
|
|
227
|
+
<Button>
|
|
228
|
+
Action
|
|
229
|
+
</Button>
|
|
230
|
+
</div>
|
|
231
|
+
</div>
|
|
232
|
+
|
|
233
|
+
<!-- Only include if custom CSS is needed -->
|
|
234
|
+
<style src="./style.css"></style>
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Styling System & Tailwind CSS
|
|
238
|
+
|
|
239
|
+
### Critical: Design System Spacing Values
|
|
240
|
+
|
|
241
|
+
**IMPORTANT**: Only use spacing values that exist in the design system configuration. Invalid spacing utilities will cause build failures.
|
|
242
|
+
|
|
243
|
+
#### Available Viewport-Based Spacing (`up` suffix)
|
|
244
|
+
Valid values: `1up`, `2up`, `4up`, `5up`, `6up`, `10up`, `20up`, `30up`, `40up`, `50up`, `60up`, `70up`, `80up`, `90up`, `100up`, `120up`, `140up`, `160up`, `180up`, `200up`
|
|
245
|
+
|
|
246
|
+
#### Available Text-Based Spacing (`ut`, `bt`, `ht` suffixes)
|
|
247
|
+
Valid values: `1ut/bt/ht`, `2ut/bt/ht`, `4ut/bt/ht`, `6ut/bt/ht`, `8ut/bt/ht`, `10ut/bt/ht`, `11ut/bt/ht`, `12ut/bt/ht`, `16ut/bt/ht`, `20ut/bt/ht`, `24ut/bt/ht`, `28ut/bt/ht`, `32ut/bt/ht`, `36ut/bt/ht`, `50ut/bt/ht`
|
|
248
|
+
|
|
249
|
+
#### ❌ Common Invalid Values (Will Cause Build Failures)
|
|
250
|
+
- `p-16up` (use `p-20up` instead)
|
|
251
|
+
- `px-16up py-12up` (use `px-20up py-10up` instead)
|
|
252
|
+
- `mb-16up` (use `mb-20up` instead)
|
|
253
|
+
- Any spacing value not listed above
|
|
254
|
+
|
|
255
|
+
### External CSS Files (`<style src="./style.css">`)
|
|
256
|
+
|
|
257
|
+
When using external CSS files with `@apply` directives, you **MUST** include the `@reference` directive:
|
|
258
|
+
|
|
259
|
+
#### ✅ Correct External CSS
|
|
260
|
+
```css
|
|
261
|
+
/* style.css */
|
|
262
|
+
@reference '../../app.css';
|
|
263
|
+
|
|
264
|
+
[data-page] {
|
|
265
|
+
& .my-component {
|
|
266
|
+
@apply p-20up bg-surface-300 border border-primary-500;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
#### ❌ Broken External CSS
|
|
272
|
+
```css
|
|
273
|
+
/* style.css - MISSING @reference */
|
|
274
|
+
[data-page] {
|
|
275
|
+
& .my-component {
|
|
276
|
+
@apply p-20up bg-surface-300; /* ERROR: Cannot apply unknown utility class */
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Path Resolution for @reference
|
|
282
|
+
|
|
283
|
+
The `@reference` path must be relative to your CSS file's location:
|
|
284
|
+
- From `/src/routes/examples/style.css` → `@reference '../../app.css'`
|
|
285
|
+
- From `/src/routes/examples/ui/style.css` → `@reference '../../../app.css'`
|
|
286
|
+
- From `/src/lib/components/style.css` → `@reference '../../app.css'`
|
|
287
|
+
|
|
288
|
+
### Inline vs External CSS
|
|
289
|
+
|
|
290
|
+
#### Inline Styles (No @reference needed)
|
|
291
|
+
```svelte
|
|
292
|
+
<style>
|
|
293
|
+
[data-page] {
|
|
294
|
+
& .my-component {
|
|
295
|
+
@apply p-20up bg-surface-300 border border-primary-500;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
</style>
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
#### External CSS (Requires @reference)
|
|
302
|
+
```svelte
|
|
303
|
+
<!-- Component.svelte -->
|
|
304
|
+
<div class="my-component">Content</div>
|
|
305
|
+
<style src="./style.css"></style>
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Troubleshooting Build Errors
|
|
309
|
+
|
|
310
|
+
#### "Cannot apply unknown utility class 'p-XYZup'"
|
|
311
|
+
1. Check if the spacing value exists in `VIEWPORT_POINT_SIZES` or `TEXT_POINT_SIZES`
|
|
312
|
+
2. Replace with the nearest valid value (e.g., `16up` → `20up`)
|
|
313
|
+
3. If using external CSS, verify `@reference` directive is present and path is correct
|
|
314
|
+
|
|
315
|
+
#### "Are you using CSS modules or similar and missing @reference?"
|
|
316
|
+
1. Add `@reference '../../app.css'` at the top of your external CSS file
|
|
317
|
+
2. Verify the relative path from CSS file to `src/app.css` is correct
|
|
318
|
+
3. Consider switching to inline styles if path resolution is problematic
|
|
319
|
+
|
|
320
|
+
### Design System Integration
|
|
321
|
+
|
|
322
|
+
#### Always Use Design System Classes
|
|
323
|
+
- ✅ `type-heading-h1`, `type-base-md`, `type-ui-sm`
|
|
324
|
+
- ✅ `p-20up`, `m-10up`, `gap-16up` (viewport-based)
|
|
325
|
+
- ✅ `mb-16bt`, `mt-12ut` (text-based)
|
|
326
|
+
- ✅ `bg-surface-300`, `text-primary-500`, `border-error-500`
|
|
327
|
+
- ❌ Raw Tailwind: `text-lg`, `p-4`, `bg-gray-300`
|
|
328
|
+
|
|
329
|
+
#### Color System
|
|
330
|
+
All design system colors are available with contrast variants:
|
|
331
|
+
- Base colors: `bg-primary-500`, `bg-surface-100`, `bg-error-500`
|
|
332
|
+
- Contrast colors: `text-primary-contrast-500`, `text-surface-contrast-100`
|
|
333
|
+
- Shades: `50`, `100`, `200`, `300`, `400`, `500`, `600`, `700`, `800`, `900`, `950`
|
|
334
|
+
|
|
335
|
+
### CSS Architecture
|
|
336
|
+
- Use `[data-page]` scoping for page-specific styles
|
|
337
|
+
- Use `[data-component]` attributes for component identification
|
|
338
|
+
- Prefer CSS nesting with `&` selector
|
|
339
|
+
- Layer styles: `@layer theme, base, utilities, components`
|
|
340
|
+
|
|
341
|
+
## What Not to Do
|
|
342
|
+
- Don't use deprecated Svelte 4 syntax
|
|
343
|
+
- Don't mix slot and snippet syntax
|
|
344
|
+
- Don't use TypeScript syntax
|
|
345
|
+
- Don't use CommonJS (require/module.exports)
|
|
346
|
+
- Don't use underscore prefixes for private methods
|
|
347
|
+
- Don't use invalid spacing values (e.g., `p-16up`, `mb-14up`) - check design system configuration
|
|
348
|
+
- Don't use external CSS with `@apply` without the `@reference` directive
|
|
349
|
+
- Don't modify unrelated code unless necessary
|
|
350
|
+
- **NEVER run `npm run dev` or `pnpm run dev`** - it interferes with the user's running development server
|
package/README.md
CHANGED
|
@@ -187,10 +187,16 @@ The library includes a comprehensive logging system that provides:
|
|
|
187
187
|
- **Client-side**: Enhanced console logging with structured data display in browser inspector
|
|
188
188
|
- **Consistent API**: Same logging interface for both server and client environments
|
|
189
189
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
- **
|
|
190
|
+
## Documentation
|
|
191
|
+
|
|
192
|
+
For detailed setup guides and configuration:
|
|
193
|
+
- **Project setup**: [docs/setup/new-project.md](./docs/setup/new-project.md) - SvelteKit project setup
|
|
194
|
+
- **Library setup**: [docs/setup/new-lib.md](./docs/setup/new-lib.md) - SvelteKit library setup
|
|
195
|
+
- **Services & logging**: [docs/setup/services-logging.md](./docs/setup/services-logging.md) - Service management architecture
|
|
196
|
+
- **Configuration files**: [docs/config/root-config-files.md](./docs/config/root-config-files.md) - Config file reference
|
|
197
|
+
- **Design system**: [src/lib/design/README.md](./src/lib/design/README.md) - Design tokens and theming
|
|
198
|
+
- **Vite configuration**: [src/lib/config/README.md](./src/lib/config/README.md) - Build configuration
|
|
199
|
+
- **Logging system**: [src/lib/logging/README.md](./src/lib/logging/README.md) - Server and client logging
|
|
194
200
|
|
|
195
201
|
### Update
|
|
196
202
|
|
package/dist/logging/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { createServerLogger } from "./internal/factories/server.js";
|
|
2
2
|
export { createClientLogger } from "./internal/factories/client.js";
|
|
3
3
|
export { Logger } from "./internal/logger/index.js";
|
|
4
|
-
export * from "./
|
|
4
|
+
export * from "./levels.js";
|
|
5
5
|
export * from "./typedef.js";
|
package/dist/logging/index.js
CHANGED
|
@@ -5,6 +5,6 @@ export { createClientLogger } from './internal/factories/client.js';
|
|
|
5
5
|
// Logger (for advanced usage)
|
|
6
6
|
export { Logger } from './internal/logger/index.js';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
export * from './levels.js';
|
|
9
|
+
|
|
10
10
|
export * from './typedef.js';
|
package/dist/services/README.md
CHANGED
|
@@ -237,6 +237,37 @@ const systemHealth = await manager.checkHealth();
|
|
|
237
237
|
|
|
238
238
|
### Error Handling and Recovery
|
|
239
239
|
|
|
240
|
+
### Logging Configuration
|
|
241
|
+
|
|
242
|
+
ServiceManager provides centralized logging control for all services:
|
|
243
|
+
|
|
244
|
+
```javascript
|
|
245
|
+
const manager = new ServiceManager({
|
|
246
|
+
debug: true, // Sets defaultLogLevel to DEBUG
|
|
247
|
+
defaultLogLevel: 'INFO', // Default level for all services
|
|
248
|
+
managerLogLevel: 'DEBUG', // Level for ServiceManager itself
|
|
249
|
+
serviceLogLevels: { // Per-service levels
|
|
250
|
+
database: 'ERROR',
|
|
251
|
+
auth: 'DEBUG'
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
// Change manager log level at runtime
|
|
256
|
+
manager.setManagerLogLevel('ERROR');
|
|
257
|
+
|
|
258
|
+
// Change service log levels at runtime
|
|
259
|
+
manager.setServiceLogLevel('database', 'INFO');
|
|
260
|
+
|
|
261
|
+
// Set multiple service levels at once
|
|
262
|
+
manager.setServiceLogLevel({
|
|
263
|
+
database: 'INFO',
|
|
264
|
+
auth: 'DEBUG'
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
// Parse string format
|
|
268
|
+
manager.setServiceLogLevel('database:info,auth:debug');
|
|
269
|
+
```
|
|
270
|
+
|
|
240
271
|
### ServiceManager events
|
|
241
272
|
|
|
242
273
|
ServiceManager emits these events (constants from `$lib/services/service-manager/constants.js`):
|
|
@@ -264,14 +295,14 @@ await manager.recoverService('database');
|
|
|
264
295
|
Forward all service log events to a centralised logger:
|
|
265
296
|
|
|
266
297
|
```javascript
|
|
267
|
-
import { ServiceManager
|
|
298
|
+
import { ServiceManager } from '$lib/services/index.js';
|
|
268
299
|
import { createServerLogger } from '$lib/logging/index.js';
|
|
269
300
|
|
|
270
301
|
const manager = new ServiceManager();
|
|
271
302
|
const logger = createServerLogger('SystemLogger');
|
|
272
303
|
|
|
273
304
|
// Listen to all log events and forward them to the logger
|
|
274
|
-
manager.
|
|
305
|
+
const unsubscribe = manager.onServiceLogEvent((logEvent) => {
|
|
275
306
|
logger.logFromEvent('manager:service:log', logEvent);
|
|
276
307
|
});
|
|
277
308
|
|
|
@@ -280,6 +311,9 @@ manager.register('database', DatabaseService, { ... });
|
|
|
280
311
|
manager.register('auth', AuthService, { ... });
|
|
281
312
|
|
|
282
313
|
await manager.startAll();
|
|
314
|
+
|
|
315
|
+
// Cleanup when done
|
|
316
|
+
unsubscribe();
|
|
283
317
|
```
|
|
284
318
|
|
|
285
319
|
## Plugins
|
|
@@ -129,12 +129,32 @@ export class ServiceManager extends EventEmitter {
|
|
|
129
129
|
*/
|
|
130
130
|
isRunning(name: string): Promise<boolean>;
|
|
131
131
|
/**
|
|
132
|
-
*
|
|
132
|
+
* Listen to log messages emitted by individual services
|
|
133
133
|
*
|
|
134
|
-
* @param {
|
|
135
|
-
*
|
|
134
|
+
* @param {Function} listener - Log event handler
|
|
135
|
+
*
|
|
136
|
+
* @returns {Function} Unsubscribe function
|
|
137
|
+
*/
|
|
138
|
+
onServiceLogEvent(listener: Function): Function;
|
|
139
|
+
/**
|
|
140
|
+
* Set log level for the ServiceManager itself
|
|
141
|
+
*
|
|
142
|
+
* @param {string} level - Log level to set for the ServiceManager
|
|
143
|
+
*/
|
|
144
|
+
setManagerLogLevel(level: string): void;
|
|
145
|
+
/**
|
|
146
|
+
* Set log level for individual services
|
|
147
|
+
*
|
|
148
|
+
* @param {string|Object<string,string>} nameOrConfig
|
|
149
|
+
* Service configuration:
|
|
150
|
+
* - String with service name: 'auth' (requires level parameter)
|
|
151
|
+
* - String with config: 'auth:debug,database:info'
|
|
152
|
+
* - Object: { auth: 'debug', database: 'info' }
|
|
153
|
+
* @param {string} [level] - Log level (required when nameOrConfig is service name)
|
|
136
154
|
*/
|
|
137
|
-
|
|
155
|
+
setServiceLogLevel(nameOrConfig: string | {
|
|
156
|
+
[x: string]: string;
|
|
157
|
+
}, level?: string): void;
|
|
138
158
|
/**
|
|
139
159
|
* Get all services with a specific tag
|
|
140
160
|
*
|
|
@@ -51,11 +51,11 @@
|
|
|
51
51
|
*
|
|
52
52
|
* @example
|
|
53
53
|
* // Logging control
|
|
54
|
-
* // Set
|
|
55
|
-
* manager.
|
|
54
|
+
* // Set manager log level (affects all services)
|
|
55
|
+
* manager.setManagerLogLevel('DEBUG');
|
|
56
56
|
*
|
|
57
57
|
* // Set specific service log level
|
|
58
|
-
* manager.
|
|
58
|
+
* manager.setServiceLogLevel('database', 'ERROR');
|
|
59
59
|
*
|
|
60
60
|
* // Listen to all service logs
|
|
61
61
|
* manager.on('service:log', (logEvent) => {
|
|
@@ -64,7 +64,10 @@
|
|
|
64
64
|
*/
|
|
65
65
|
|
|
66
66
|
import { EventEmitter } from '../../generic/events.js';
|
|
67
|
-
import { Logger, DEBUG, INFO
|
|
67
|
+
import { Logger, DEBUG, INFO } from '../../logging/index.js';
|
|
68
|
+
|
|
69
|
+
import { SERVICE_LOG } from './constants.js';
|
|
70
|
+
import { parseServiceLogLevels } from './util.js';
|
|
68
71
|
|
|
69
72
|
import {
|
|
70
73
|
STATE_NOT_CREATED,
|
|
@@ -103,18 +106,29 @@ export class ServiceManager extends EventEmitter {
|
|
|
103
106
|
/** @type {Map<string, ServiceEntry>} */
|
|
104
107
|
this.services = new Map();
|
|
105
108
|
|
|
109
|
+
const defaultLogLevel =
|
|
110
|
+
config.defaultLogLevel || (config.debug ? DEBUG : INFO);
|
|
111
|
+
const managerLogLevel = config.managerLogLevel || defaultLogLevel;
|
|
112
|
+
const serviceLogLevels = config.serviceLogLevels;
|
|
113
|
+
|
|
106
114
|
/** @type {Logger} */
|
|
107
|
-
this.logger = new Logger('ServiceManager',
|
|
115
|
+
this.logger = new Logger('ServiceManager', managerLogLevel);
|
|
108
116
|
|
|
109
117
|
/** @type {ServiceManagerConfig} */
|
|
110
118
|
this.config = {
|
|
111
119
|
debug: config.debug ?? false,
|
|
112
120
|
autoStart: config.autoStart ?? false,
|
|
113
121
|
stopTimeout: config.stopTimeout || 10000,
|
|
114
|
-
|
|
122
|
+
defaultLogLevel
|
|
123
|
+
// managerLogLevel will be set bysetManagerLogLevel()
|
|
124
|
+
// serviceLogLevels will be set by setServiceLogLevel()
|
|
115
125
|
};
|
|
116
126
|
|
|
117
|
-
this
|
|
127
|
+
this.setManagerLogLevel(managerLogLevel);
|
|
128
|
+
|
|
129
|
+
if (serviceLogLevels) {
|
|
130
|
+
this.setServiceLogLevel(serviceLogLevels);
|
|
131
|
+
}
|
|
118
132
|
}
|
|
119
133
|
|
|
120
134
|
/**
|
|
@@ -474,34 +488,70 @@ export class ServiceManager extends EventEmitter {
|
|
|
474
488
|
}
|
|
475
489
|
|
|
476
490
|
/**
|
|
477
|
-
*
|
|
491
|
+
* Listen to log messages emitted by individual services
|
|
478
492
|
*
|
|
479
|
-
* @param {
|
|
480
|
-
*
|
|
493
|
+
* @param {Function} listener - Log event handler
|
|
494
|
+
*
|
|
495
|
+
* @returns {Function} Unsubscribe function
|
|
481
496
|
*/
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
497
|
+
onServiceLogEvent(listener) {
|
|
498
|
+
return this.on(SERVICE_LOG, listener);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Set log level for the ServiceManager itself
|
|
503
|
+
*
|
|
504
|
+
* @param {string} level - Log level to set for the ServiceManager
|
|
505
|
+
*/
|
|
506
|
+
setManagerLogLevel(level) {
|
|
507
|
+
this.config.managerLogLevel = level;
|
|
508
|
+
this.logger.setLevel(level);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
* Set log level for individual services
|
|
513
|
+
*
|
|
514
|
+
* @param {string|Object<string,string>} nameOrConfig
|
|
515
|
+
* Service configuration:
|
|
516
|
+
* - String with service name: 'auth' (requires level parameter)
|
|
517
|
+
* - String with config: 'auth:debug,database:info'
|
|
518
|
+
* - Object: { auth: 'debug', database: 'info' }
|
|
519
|
+
* @param {string} [level] - Log level (required when nameOrConfig is service name)
|
|
520
|
+
*/
|
|
521
|
+
setServiceLogLevel(nameOrConfig, level) {
|
|
522
|
+
/** @type {{[name:string]: string}} */
|
|
523
|
+
let serviceLevels = {};
|
|
524
|
+
|
|
525
|
+
if (typeof nameOrConfig === 'string') {
|
|
526
|
+
if (nameOrConfig.includes(':')) {
|
|
527
|
+
// Parse string config: 'auth:debug,database:info'
|
|
528
|
+
serviceLevels = parseServiceLogLevels(nameOrConfig);
|
|
529
|
+
} else {
|
|
530
|
+
// Single service name
|
|
531
|
+
if (!level) {
|
|
532
|
+
throw new Error(
|
|
533
|
+
`Level parameter required for service '${nameOrConfig}'`
|
|
534
|
+
);
|
|
492
535
|
}
|
|
536
|
+
serviceLevels[nameOrConfig] = level;
|
|
493
537
|
}
|
|
494
538
|
} else {
|
|
495
|
-
//
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
539
|
+
// Object config: { auth: 'debug', database: 'info' }
|
|
540
|
+
serviceLevels = nameOrConfig;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
if (!this.config.serviceLogLevels) {
|
|
544
|
+
this.config.serviceLogLevels = {};
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// Apply service-specific log levels
|
|
548
|
+
for (const [name, logLevel] of Object.entries(serviceLevels)) {
|
|
549
|
+
this.config.serviceLogLevels[name] = logLevel;
|
|
500
550
|
|
|
501
551
|
// Apply to existing instance
|
|
502
552
|
const instance = this.get(name);
|
|
503
553
|
if (instance) {
|
|
504
|
-
instance.setLogLevel(
|
|
554
|
+
instance.setLogLevel(logLevel);
|
|
505
555
|
}
|
|
506
556
|
}
|
|
507
557
|
}
|
|
@@ -586,23 +636,6 @@ export class ServiceManager extends EventEmitter {
|
|
|
586
636
|
}
|
|
587
637
|
}
|
|
588
638
|
|
|
589
|
-
/**
|
|
590
|
-
* Setup logging configuration based on config.dev
|
|
591
|
-
*/
|
|
592
|
-
#setupLogging() {
|
|
593
|
-
// Set default log levels based on config.debug flag
|
|
594
|
-
if (this.config.debug) {
|
|
595
|
-
this.config.logConfig.defaultLevel = DEBUG;
|
|
596
|
-
} else {
|
|
597
|
-
this.config.logConfig.defaultLevel = WARN;
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
// Apply config
|
|
601
|
-
if (this.config.logConfig.globalLevel) {
|
|
602
|
-
this.logger.setLevel(this.config.logConfig.globalLevel);
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
|
|
606
639
|
/**
|
|
607
640
|
* Get the appropriate log level for a service
|
|
608
641
|
*
|
|
@@ -611,21 +644,20 @@ export class ServiceManager extends EventEmitter {
|
|
|
611
644
|
* @returns {string|undefined} Log level or undefined
|
|
612
645
|
*/
|
|
613
646
|
#getServiceLogLevel(name) {
|
|
614
|
-
const config = this.config
|
|
647
|
+
const config = this.config;
|
|
615
648
|
|
|
616
649
|
// Check in order of precedence:
|
|
617
|
-
// 1.
|
|
618
|
-
if (config.
|
|
619
|
-
return config.
|
|
650
|
+
// 1. Service-specific level
|
|
651
|
+
if (config.serviceLogLevels?.[name]) {
|
|
652
|
+
return config.serviceLogLevels[name];
|
|
620
653
|
}
|
|
621
654
|
|
|
622
|
-
// 2.
|
|
623
|
-
if (config.
|
|
624
|
-
return config.
|
|
655
|
+
// 2. Default level fallback
|
|
656
|
+
if (config.defaultLogLevel) {
|
|
657
|
+
return config.defaultLogLevel;
|
|
625
658
|
}
|
|
626
659
|
|
|
627
|
-
// 3.
|
|
628
|
-
// Return undefined to let the service use its own default
|
|
660
|
+
// 3. No fallback - let service use its own default
|
|
629
661
|
return undefined;
|
|
630
662
|
}
|
|
631
663
|
|
|
@@ -2,3 +2,5 @@ export const SERVICE_STATE_CHANGED: "service:state-changed";
|
|
|
2
2
|
export const SERVICE_HEALTH_CHANGED: "service:health-changed";
|
|
3
3
|
export const SERVICE_ERROR: "service:error";
|
|
4
4
|
export const SERVICE_LOG: "service:log";
|
|
5
|
+
export const ANY_LOG_LEVEL: "*";
|
|
6
|
+
export const ANY_SERVICE_NAME: "*";
|
|
@@ -3,3 +3,6 @@ export const SERVICE_STATE_CHANGED = 'service:state-changed';
|
|
|
3
3
|
export const SERVICE_HEALTH_CHANGED = 'service:health-changed';
|
|
4
4
|
export const SERVICE_ERROR = 'service:error';
|
|
5
5
|
export const SERVICE_LOG = 'service:log';
|
|
6
|
+
|
|
7
|
+
export const ANY_LOG_LEVEL = '*';
|
|
8
|
+
export const ANY_SERVICE_NAME = '*';
|
|
@@ -38,30 +38,19 @@ export type ServiceManagerConfig = {
|
|
|
38
38
|
*/
|
|
39
39
|
stopTimeout?: number;
|
|
40
40
|
/**
|
|
41
|
-
* -
|
|
41
|
+
* - Default log level for new services
|
|
42
42
|
*/
|
|
43
|
-
|
|
43
|
+
defaultLogLevel?: string;
|
|
44
44
|
/**
|
|
45
|
-
* -
|
|
46
|
-
*/
|
|
47
|
-
logConfig?: LogConfig;
|
|
48
|
-
};
|
|
49
|
-
/**
|
|
50
|
-
* Logging configuration
|
|
51
|
-
*/
|
|
52
|
-
export type LogConfig = {
|
|
53
|
-
/**
|
|
54
|
-
* - Default log level for services
|
|
55
|
-
*/
|
|
56
|
-
defaultLevel?: string;
|
|
57
|
-
/**
|
|
58
|
-
* - Override level for all services
|
|
45
|
+
* - Initial log level for ServiceManager
|
|
59
46
|
*/
|
|
60
|
-
|
|
47
|
+
managerLogLevel?: string;
|
|
61
48
|
/**
|
|
62
|
-
*
|
|
49
|
+
* Per-service log levels:
|
|
50
|
+
* - String: "auth:debug,database:info"
|
|
51
|
+
* - Object: { auth: "debug", database: "info" }
|
|
63
52
|
*/
|
|
64
|
-
|
|
53
|
+
serviceLogLevels?: string | {
|
|
65
54
|
[x: string]: string;
|
|
66
55
|
};
|
|
67
56
|
};
|
|
@@ -52,17 +52,12 @@
|
|
|
52
52
|
* @property {boolean} [debug=false] - Debug mode switch
|
|
53
53
|
* @property {boolean} [autoStart=false] - Auto-start services on registration
|
|
54
54
|
* @property {number} [stopTimeout=10000] - Default timeout for stopping services
|
|
55
|
-
* @property {string} [
|
|
56
|
-
* @property {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* @typedef {Object} LogConfig
|
|
63
|
-
* @property {string} [defaultLevel] - Default log level for services
|
|
64
|
-
* @property {string} [globalLevel] - Override level for all services
|
|
65
|
-
* @property {Object<string, string>} [serviceLevels] - Per-service log levels
|
|
55
|
+
* @property {string} [defaultLogLevel] - Default log level for new services
|
|
56
|
+
* @property {string} [managerLogLevel] - Initial log level for ServiceManager
|
|
57
|
+
* @property {string|Object<string,string>} [serviceLogLevels]
|
|
58
|
+
* Per-service log levels:
|
|
59
|
+
* - String: "auth:debug,database:info"
|
|
60
|
+
* - Object: { auth: "debug", database: "info" }
|
|
66
61
|
*/
|
|
67
62
|
|
|
68
63
|
/**
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse comma-separated service:level configuration string
|
|
3
|
+
*
|
|
4
|
+
* @param {string} configString
|
|
5
|
+
* Comma-separated string like "auth:debug,database:info,cache:warn"
|
|
6
|
+
*
|
|
7
|
+
* @returns {Object<string, string>} Service name to log level mapping
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const config = parseServiceLogLevels("auth:debug,database:info");
|
|
11
|
+
* // Returns: { auth: "debug", database: "info" }
|
|
12
|
+
*/
|
|
13
|
+
export function parseServiceLogLevels(configString: string): {
|
|
14
|
+
[x: string]: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Expand log levels to include higher severity levels
|
|
18
|
+
*
|
|
19
|
+
* @param {{[name:string]: string}} serviceLevels
|
|
20
|
+
* Service name to log level mapping
|
|
21
|
+
*
|
|
22
|
+
* @returns {Object<string, string[]>} Service name to array of log levels
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* const levels = expandLogLevels({ auth: "debug", cache: "warn" });
|
|
26
|
+
* // Returns: {
|
|
27
|
+
* // auth: ["debug", "info", "warn", "error"],
|
|
28
|
+
* // cache: ["warn", "error"]
|
|
29
|
+
* // }
|
|
30
|
+
*/
|
|
31
|
+
export function expandLogLevels(serviceLevels: {
|
|
32
|
+
[name: string]: string;
|
|
33
|
+
}): {
|
|
34
|
+
[x: string]: string[];
|
|
35
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Service Manager utility functions
|
|
3
|
+
*
|
|
4
|
+
* Provides utility functions for parsing service configurations, handling
|
|
5
|
+
* log level hierarchies, and managing service-specific operations.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { DEBUG, INFO, WARN, ERROR } from '../../logging/index.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Parse comma-separated service:level configuration string
|
|
12
|
+
*
|
|
13
|
+
* @param {string} configString
|
|
14
|
+
* Comma-separated string like "auth:debug,database:info,cache:warn"
|
|
15
|
+
*
|
|
16
|
+
* @returns {Object<string, string>} Service name to log level mapping
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* const config = parseServiceLogLevels("auth:debug,database:info");
|
|
20
|
+
* // Returns: { auth: "debug", database: "info" }
|
|
21
|
+
*/
|
|
22
|
+
export function parseServiceLogLevels(configString) {
|
|
23
|
+
if (!configString || typeof configString !== 'string') {
|
|
24
|
+
/** @type {Object<string, string>} */
|
|
25
|
+
return {};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** @type {Object<string, string>} */
|
|
29
|
+
const result = {};
|
|
30
|
+
|
|
31
|
+
const services = configString.split(',');
|
|
32
|
+
|
|
33
|
+
for (const serviceExpression of services) {
|
|
34
|
+
const trimmed = serviceExpression.trim();
|
|
35
|
+
if (!trimmed) continue;
|
|
36
|
+
|
|
37
|
+
const parts = trimmed.split(':');
|
|
38
|
+
if (parts.length === 2) {
|
|
39
|
+
const [serviceName, logLevel] = parts;
|
|
40
|
+
result[serviceName.trim()] = logLevel.trim();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Expand log levels to include higher severity levels
|
|
49
|
+
*
|
|
50
|
+
* @param {{[name:string]: string}} serviceLevels
|
|
51
|
+
* Service name to log level mapping
|
|
52
|
+
*
|
|
53
|
+
* @returns {Object<string, string[]>} Service name to array of log levels
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* const levels = expandLogLevels({ auth: "debug", cache: "warn" });
|
|
57
|
+
* // Returns: {
|
|
58
|
+
* // auth: ["debug", "info", "warn", "error"],
|
|
59
|
+
* // cache: ["warn", "error"]
|
|
60
|
+
* // }
|
|
61
|
+
*/
|
|
62
|
+
export function expandLogLevels(serviceLevels) {
|
|
63
|
+
/** @type {Object<string, string[]>} */
|
|
64
|
+
const result = {};
|
|
65
|
+
|
|
66
|
+
for (const [serviceName, level] of Object.entries(serviceLevels)) {
|
|
67
|
+
const levels = [];
|
|
68
|
+
|
|
69
|
+
switch (level.toLowerCase()) {
|
|
70
|
+
case DEBUG:
|
|
71
|
+
levels.push(DEBUG, INFO, WARN, ERROR);
|
|
72
|
+
break;
|
|
73
|
+
case INFO:
|
|
74
|
+
levels.push(INFO, WARN, ERROR);
|
|
75
|
+
break;
|
|
76
|
+
case WARN:
|
|
77
|
+
levels.push(WARN, ERROR);
|
|
78
|
+
break;
|
|
79
|
+
case ERROR:
|
|
80
|
+
levels.push(ERROR);
|
|
81
|
+
break;
|
|
82
|
+
default:
|
|
83
|
+
levels.push(level);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
result[serviceName] = levels;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
* Event emitted when entering a state
|
|
7
7
|
* @type {string}
|
|
8
8
|
*/
|
|
9
|
-
export const ENTER = '
|
|
9
|
+
export const ENTER = '_enter';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Event emitted when exiting a state
|
|
13
13
|
* @type {string}
|
|
14
14
|
*/
|
|
15
|
-
export const EXIT = '
|
|
15
|
+
export const EXIT = '_exit';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hkdigital/lib-core",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.30",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "HKdigital",
|
|
6
6
|
"url": "https://hkdigital.nl"
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
},
|
|
53
53
|
"files": [
|
|
54
54
|
"dist",
|
|
55
|
+
"CLAUDE.md",
|
|
55
56
|
"!dist/**/*.test.*",
|
|
56
57
|
"!dist/**/*.spec.*",
|
|
57
58
|
"!dist/**/testdata.*",
|
|
@@ -76,13 +77,17 @@
|
|
|
76
77
|
"@skeletonlabs/skeleton": "^3.1.7",
|
|
77
78
|
"@steeze-ui/heroicons": "^2.4.2",
|
|
78
79
|
"@sveltejs/kit": "^2.28.0",
|
|
80
|
+
"@tailwindcss/postcss": "^4.1.11",
|
|
81
|
+
"autoprefixer": "^10.4.21",
|
|
79
82
|
"eslint-plugin-import": "^2.32.0",
|
|
80
83
|
"jsonwebtoken": "^9.0.0",
|
|
81
84
|
"pino": "^9.8.0",
|
|
82
85
|
"pino-pretty": "^13.1.1",
|
|
86
|
+
"postcss": "^8.5.6",
|
|
83
87
|
"runed": "^0.31.1",
|
|
84
88
|
"svelte": "^5.38.1",
|
|
85
89
|
"svelte-preprocess": "^6.0.3",
|
|
90
|
+
"tailwindcss": "^4.1.11",
|
|
86
91
|
"valibot": "^1.1.0",
|
|
87
92
|
"vite-imagetools": "^8.0.0"
|
|
88
93
|
},
|
|
@@ -98,6 +103,7 @@
|
|
|
98
103
|
"@tailwindcss/typography": "^0.5.16",
|
|
99
104
|
"@testing-library/svelte": "^5.2.8",
|
|
100
105
|
"@testing-library/user-event": "^14.6.1",
|
|
106
|
+
"@tailwindcss/postcss": "^4.1.11",
|
|
101
107
|
"@types/eslint": "^9.6.1",
|
|
102
108
|
"@types/node": "^24.2.1",
|
|
103
109
|
"autoprefixer": "^10.4.21",
|
|
@@ -128,8 +134,5 @@
|
|
|
128
134
|
"vite": "^7.1.2",
|
|
129
135
|
"vite-imagetools": "^8.0.0",
|
|
130
136
|
"vitest": "^3.2.4"
|
|
131
|
-
},
|
|
132
|
-
"dependencies": {
|
|
133
|
-
"@tailwindcss/postcss": "^4.1.11"
|
|
134
137
|
}
|
|
135
138
|
}
|
|
File without changes
|
|
File without changes
|