@owlmeans/web-wl 0.1.2 → 0.1.4

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/README.md CHANGED
@@ -1,744 +1,54 @@
1
1
  # @owlmeans/web-wl
2
2
 
3
- Web-specific whitelabeling functionality for OwlMeans Common Libraries. This package provides React components and browser-optimized services for implementing client-side whitelabeling, enabling web applications to dynamically customize branding, theming, and content based on entity-specific configurations.
3
+ Web whitelabel service factory, module declarations, and React components for managing whitelabel content in browser apps.
4
4
 
5
5
  ## Overview
6
6
 
7
- The `@owlmeans/web-wl` package serves as the web-specific implementation of the OwlMeans Whitelabeling Subsystem, designed for React-based frontend applications with focus on dynamic branding and user experience customization. It provides:
8
-
9
- - **Web Whitelabeling Service**: Browser-optimized service for loading and caching whitelabeling data
10
- - **React Components**: React components for whitelabel-aware UI elements
11
- - **Caching Strategy**: Efficient client-side caching of whitelabeling configurations
12
- - **API Integration**: Seamless integration with server-side whitelabeling providers
13
- - **Performance Optimization**: Optimized loading and rendering of dynamic branding content
14
-
15
- This package follows the OwlMeans "quadra" pattern as the **web** implementation, complementing:
16
- - **@owlmeans/wled**: Common whitelabeling declarations and base functionality *(base package)*
17
- - **@owlmeans/client-wl**: Base client whitelabeling functionality
18
- - **@owlmeans/server-wl**: Server-side whitelabeling implementation
19
- - **@owlmeans/web-wl**: Web browser whitelabeling implementation *(this package)*
7
+ - `makeWlService(alias?)` web-side whitelabel service factory
8
+ - `wlModules` (exported as `modules`) — web-side whitelabel module declarations
9
+ - Components for displaying whitelabel content
10
+ - `DEFAULT_ALIAS` `'wl-web-serivce'`
20
11
 
21
12
  ## Installation
22
13
 
23
14
  ```bash
24
- npm install @owlmeans/web-wl
15
+ bun add @owlmeans/web-wl
25
16
  ```
26
17
 
27
- ## Dependencies
28
-
29
- This package requires and integrates with:
30
- - `@owlmeans/wled`: Core whitelabeling types and modules
31
- - `@owlmeans/client`: Base client functionality
32
- - `@owlmeans/client-module`: Client module system for API calls
33
- - `@owlmeans/context`: Context management and service registration
34
- - React: Peer dependency for web components
35
-
36
- ## Key Concepts
37
-
38
- ### Web Whitelabeling Service
39
- Browser-optimized service that:
40
- - **Loads Whitelabeling Data**: Fetches entity-specific branding from server APIs
41
- - **Caches Configurations**: Implements client-side caching for performance
42
- - **Extracts Data**: Provides convenient access to specific whitelabeling data types
43
- - **Handles Errors**: Graceful error handling for failed whitelabeling requests
44
-
45
- ### React Component Integration
46
- React components that automatically adapt to whitelabeling configurations:
47
- - **Dynamic Branding**: Components that change appearance based on entity branding
48
- - **Conditional Rendering**: Show/hide content based on whitelabeling rules
49
- - **Theme Integration**: Automatic theme switching based on entity configurations
50
- - **Performance**: Optimized rendering with minimal re-renders
18
+ ## Usage
51
19
 
52
- ### Client-side Caching
53
- Efficient caching strategy:
54
- - **Memory Caching**: In-memory cache for frequently accessed configurations
55
- - **Cache Invalidation**: Smart cache invalidation strategies
56
- - **Performance**: Reduced API calls and improved user experience
57
-
58
- ## API Reference
59
-
60
- ### Factory Functions
61
-
62
- #### `makeWlService(alias?: string): WlWebService`
63
-
64
- Creates a web whitelabeling service instance with caching capabilities.
20
+ Register the service and module declarations:
65
21
 
66
22
  ```typescript
67
- import { makeWlService } from '@owlmeans/web-wl'
23
+ import { makeWlService, modules as wlModules } from '@owlmeans/web-wl'
68
24
 
69
- const wlService = makeWlService('main-wl')
70
- context.registerService(wlService)
25
+ context.registerService(makeWlService())
26
+ const modules = [...baseModules, ...wlModules, ...appModules]
71
27
  ```
72
28
 
73
- **Parameters:**
74
- - `alias`: Optional service alias (defaults to `DEFAULT_ALIAS`)
75
-
76
- **Returns:** `WlWebService` - Web whitelabeling service instance
29
+ Downstream variants (e.g., `@owlmeans/web-wl-manager`) extend this with manager-store helpers like `setupWlManagerStore<C, T>(context)`.
77
30
 
78
- ### Core Interfaces
31
+ ## API
79
32
 
80
- #### `WlWebService`
33
+ ### `makeWlService(alias?)`
81
34
 
82
- Web-specific whitelabeling service interface.
35
+ Creates the web whitelabel service. `alias` defaults to `DEFAULT_ALIAS` (`'wl-web-serivce'`).
83
36
 
84
- ```typescript
85
- interface WlWebService extends InitializedService {
86
- load: (entityId: string) => Promise<ProvidedWLSet>
87
- extract: <T>(key: string, set: ProvidedWLSet) => T | undefined
88
- }
89
- ```
90
-
91
- **Methods:**
92
-
93
- **`load(entityId: string): Promise<ProvidedWLSet>`**
94
- - **Purpose**: Load complete whitelabeling data set for an entity
95
- - **Parameters**: `entityId` - Entity identifier
96
- - **Returns**: Promise resolving to whitelabeling data set
97
- - **Behavior**:
98
- - Checks cache first for existing data
99
- - Makes API call to server if not cached
100
- - Caches successful responses
101
- - Returns comprehensive whitelabeling data
102
-
103
- **`extract<T>(key: string, set: ProvidedWLSet): T | undefined`**
104
- - **Purpose**: Extract specific whitelabeling data type from a data set
105
- - **Parameters**:
106
- - `key` - Provider key (e.g., 'company-provider', 'styles-provider')
107
- - `set` - Whitelabeling data set
108
- - **Returns**: Extracted data of type T or undefined if not found
109
- - **Usage**: Convenient access to specific provider data
110
-
111
- #### `ProvidedWLSet`
112
-
113
- Collection of whitelabeling data from multiple providers.
114
-
115
- ```typescript
116
- interface ProvidedWLSet<T extends Record<string, any> = Record<string, any>> {
117
- [providerKey: string]: ProvidedWL<T>
118
- }
119
- ```
37
+ ### `modules`
120
38
 
121
- #### `Config`
39
+ Array of web-side module declarations for whitelabel content (re-exported as `wlModules` in downstream variants).
122
40
 
123
- Configuration interface for web whitelabeling.
41
+ ### Components
124
42
 
125
- ```typescript
126
- interface Config extends ClientConfig {
127
- // Inherits client configuration
128
- // Plus whitelabeling-specific web settings
129
- }
130
- ```
131
-
132
- #### `Context<C extends Config = Config>`
133
-
134
- Web context interface with whitelabeling support.
135
-
136
- ```typescript
137
- interface Context<C extends Config = Config> extends ClientContext<C> {
138
- // Inherits client context functionality
139
- // With typed configuration for whitelabeling
140
- }
141
- ```
142
-
143
- ### React Components
144
-
145
- #### Whitelabeling Provider Component
146
-
147
- ```typescript
148
- interface WlProviderProps {
149
- entityId: string // Entity to load whitelabeling for
150
- children: React.ReactNode // Child components
151
- fallback?: React.ReactNode // Fallback content while loading
152
- onError?: (error: Error) => void // Error handler
153
- }
154
-
155
- const WlProvider: FC<WlProviderProps> = (props) => { /* ... */ }
156
- ```
157
-
158
- #### Whitelabel-aware Components
159
-
160
- ```typescript
161
- interface WlBrandProps {
162
- entityId: string
163
- type: 'square' | 'wide' // Logo type
164
- alt?: string // Alt text
165
- fallback?: React.ReactNode // Fallback if no logo
166
- }
167
-
168
- const WlBrand: FC<WlBrandProps> = (props) => { /* ... */ }
169
-
170
- interface WlThemeProps {
171
- entityId: string
172
- children: React.ReactNode
173
- }
174
-
175
- const WlTheme: FC<WlThemeProps> = (props) => { /* ... */ }
176
- ```
43
+ React components from `./components` (re-exported at root) for rendering whitelabel content.
177
44
 
178
45
  ### Constants
179
46
 
180
- #### `DEFAULT_ALIAS`
181
-
182
- Default service alias for whitelabeling service.
183
-
184
- ```typescript
185
- const DEFAULT_ALIAS = 'wl-web-service'
186
- ```
187
-
188
- ## Usage Examples
189
-
190
- ### Basic Web Whitelabeling Setup
191
-
192
- ```typescript
193
- import { makeWlService } from '@owlmeans/web-wl'
194
- import { makeWebContext } from '@owlmeans/web-client'
195
-
196
- // Create web context
197
- const context = makeWebContext(config)
198
-
199
- // Create and register whitelabeling service
200
- const wlService = makeWlService()
201
- context.registerService(wlService)
202
-
203
- // Initialize context
204
- await context.configure().init()
205
-
206
- // Load whitelabeling data for an entity
207
- const entityId = 'company-123'
208
- const whitelabelData = await wlService.load(entityId)
209
-
210
- console.log('Whitelabeling data:', whitelabelData)
211
- ```
212
-
213
- ### React Component Integration
214
-
215
- ```typescript
216
- import React, { useEffect, useState } from 'react'
217
- import { useContext } from '@owlmeans/client'
218
- import type { WlWebService, ProvidedWLSet } from '@owlmeans/web-wl'
219
- import type { CompanyInfo, CustomStyles, CustomMedia } from '@owlmeans/wled'
220
-
221
- interface WhitelabeledAppProps {
222
- entityId: string
223
- children: React.ReactNode
224
- }
225
-
226
- const WhitelabeledApp: React.FC<WhitelabeledAppProps> = ({ entityId, children }) => {
227
- const context = useContext()
228
- const [whitelabelData, setWhitelabelData] = useState<ProvidedWLSet | null>(null)
229
- const [loading, setLoading] = useState(true)
230
- const [error, setError] = useState<Error | null>(null)
231
-
232
- useEffect(() => {
233
- const loadWhitelabeling = async () => {
234
- try {
235
- setLoading(true)
236
- const wlService = context.service<WlWebService>('wl-web-service')
237
- const data = await wlService.load(entityId)
238
- setWhitelabelData(data)
239
- } catch (err) {
240
- setError(err as Error)
241
- } finally {
242
- setLoading(false)
243
- }
244
- }
245
-
246
- loadWhitelabeling()
247
- }, [entityId, context])
248
-
249
- if (loading) {
250
- return <div>Loading branding...</div>
251
- }
252
-
253
- if (error) {
254
- return <div>Error loading branding: {error.message}</div>
255
- }
256
-
257
- if (!whitelabelData) {
258
- return <div>No branding data available</div>
259
- }
260
-
261
- // Extract specific whitelabeling data
262
- const wlService = context.service<WlWebService>('wl-web-service')
263
- const companyInfo = wlService.extract<CompanyInfo>('company-provider', whitelabelData)
264
- const customStyles = wlService.extract<CustomStyles>('styles-provider', whitelabelData)
265
- const customMedia = wlService.extract<CustomMedia>('media-provider', whitelabelData)
266
-
267
- return (
268
- <WhitelabelThemeProvider styles={customStyles}>
269
- <div className="whitelabeled-app">
270
- <header>
271
- {customMedia?.brand?.wideLogo && (
272
- <img
273
- src={customMedia.brand.wideLogo}
274
- alt={companyInfo?.fullName || 'Logo'}
275
- className="company-logo"
276
- />
277
- )}
278
- <h1>{companyInfo?.fullName || 'Application'}</h1>
279
- </header>
280
-
281
- <main>
282
- {children}
283
- </main>
284
-
285
- <footer>
286
- <p>{companyInfo?.description}</p>
287
- </footer>
288
- </div>
289
- </WhitelabelThemeProvider>
290
- )
291
- }
292
- ```
293
-
294
- ### Dynamic Theme Application
295
-
296
- ```typescript
297
- import React, { useMemo } from 'react'
298
- import { ThemeProvider, createTheme } from '@mui/material/styles'
299
- import type { CustomStyles } from '@owlmeans/wled'
300
-
301
- interface WhitelabelThemeProviderProps {
302
- styles?: CustomStyles
303
- children: React.ReactNode
304
- }
305
-
306
- const WhitelabelThemeProvider: React.FC<WhitelabelThemeProviderProps> = ({
307
- styles,
308
- children
309
- }) => {
310
- const theme = useMemo(() => {
311
- const baseTheme = createTheme()
312
-
313
- if (!styles) {
314
- return baseTheme
315
- }
316
-
317
- return createTheme({
318
- ...baseTheme,
319
- palette: {
320
- ...baseTheme.palette,
321
- primary: {
322
- main: styles.colors.primaryColor,
323
- contrastText: '#ffffff'
324
- },
325
- secondary: {
326
- main: styles.colors.secondaryColor || baseTheme.palette.secondary.main
327
- },
328
- background: {
329
- default: styles.colors.primaryBackground || baseTheme.palette.background.default,
330
- paper: styles.colors.secondaryBackground || baseTheme.palette.background.paper
331
- }
332
- },
333
- typography: {
334
- ...baseTheme.typography,
335
- fontFamily: styles.font.fontFamily || baseTheme.typography.fontFamily,
336
- fontSize: styles.font.basicSize || baseTheme.typography.fontSize
337
- }
338
- })
339
- }, [styles])
340
-
341
- return (
342
- <ThemeProvider theme={theme}>
343
- {children}
344
- </ThemeProvider>
345
- )
346
- }
347
- ```
348
-
349
- ### Whitelabel-aware Components
350
-
351
- ```typescript
352
- import React from 'react'
353
- import { useContext } from '@owlmeans/client'
354
- import type { WlWebService } from '@owlmeans/web-wl'
355
- import type { CustomMedia } from '@owlmeans/wled'
356
-
357
- interface CompanyLogoProps {
358
- entityId: string
359
- type?: 'square' | 'wide'
360
- className?: string
361
- alt?: string
362
- }
363
-
364
- const CompanyLogo: React.FC<CompanyLogoProps> = ({
365
- entityId,
366
- type = 'wide',
367
- className,
368
- alt = 'Company Logo'
369
- }) => {
370
- const context = useContext()
371
- const [logoUrl, setLogoUrl] = React.useState<string | null>(null)
372
-
373
- React.useEffect(() => {
374
- const loadLogo = async () => {
375
- try {
376
- const wlService = context.service<WlWebService>('wl-web-service')
377
- const whitelabelData = await wlService.load(entityId)
378
- const mediaData = wlService.extract<CustomMedia>('media-provider', whitelabelData)
379
-
380
- const logo = type === 'square'
381
- ? mediaData?.brand?.squareLogo
382
- : mediaData?.brand?.wideLogo
383
-
384
- setLogoUrl(logo || null)
385
- } catch (error) {
386
- console.error('Failed to load company logo:', error)
387
- setLogoUrl(null)
388
- }
389
- }
390
-
391
- loadLogo()
392
- }, [entityId, type, context])
393
-
394
- if (!logoUrl) {
395
- return (
396
- <div className={`company-logo-placeholder ${className || ''}`}>
397
- {alt}
398
- </div>
399
- )
400
- }
401
-
402
- return (
403
- <img
404
- src={logoUrl}
405
- alt={alt}
406
- className={`company-logo ${className || ''}`}
407
- />
408
- )
409
- }
410
-
411
- // Usage
412
- <CompanyLogo
413
- entityId="company-123"
414
- type="wide"
415
- className="header-logo"
416
- alt="Acme Corporation"
417
- />
418
- ```
419
-
420
- ### Custom Hook for Whitelabeling
421
-
422
- ```typescript
423
- import { useState, useEffect } from 'react'
424
- import { useContext } from '@owlmeans/client'
425
- import type { WlWebService, ProvidedWLSet } from '@owlmeans/web-wl'
426
-
427
- interface UseWhitelabelResult<T = any> {
428
- data: T | null
429
- loading: boolean
430
- error: Error | null
431
- reload: () => void
432
- }
433
-
434
- export const useWhitelabel = <T = any>(
435
- entityId: string,
436
- providerKey?: string
437
- ): UseWhitelabelResult<T> => {
438
- const context = useContext()
439
- const [data, setData] = useState<T | null>(null)
440
- const [loading, setLoading] = useState(true)
441
- const [error, setError] = useState<Error | null>(null)
442
-
443
- const loadData = async () => {
444
- try {
445
- setLoading(true)
446
- setError(null)
447
-
448
- const wlService = context.service<WlWebService>('wl-web-service')
449
- const whitelabelData = await wlService.load(entityId)
450
-
451
- if (providerKey) {
452
- const extracted = wlService.extract<T>(providerKey, whitelabelData)
453
- setData(extracted || null)
454
- } else {
455
- setData(whitelabelData as T)
456
- }
457
- } catch (err) {
458
- setError(err as Error)
459
- setData(null)
460
- } finally {
461
- setLoading(false)
462
- }
463
- }
464
-
465
- useEffect(() => {
466
- loadData()
467
- }, [entityId, providerKey])
468
-
469
- return {
470
- data,
471
- loading,
472
- error,
473
- reload: loadData
474
- }
475
- }
476
-
477
- // Usage examples
478
- const CompanyInfoDisplay: React.FC<{ entityId: string }> = ({ entityId }) => {
479
- const { data: companyInfo, loading, error } = useWhitelabel<CompanyInfo>(
480
- entityId,
481
- 'company-provider'
482
- )
483
-
484
- if (loading) return <div>Loading company info...</div>
485
- if (error) return <div>Error: {error.message}</div>
486
- if (!companyInfo) return <div>No company information available</div>
487
-
488
- return (
489
- <div>
490
- <h2>{companyInfo.fullName}</h2>
491
- <p>{companyInfo.description}</p>
492
- </div>
493
- )
494
- }
495
-
496
- const StylesDisplay: React.FC<{ entityId: string }> = ({ entityId }) => {
497
- const { data: styles, loading, error } = useWhitelabel<CustomStyles>(
498
- entityId,
499
- 'styles-provider'
500
- )
501
-
502
- if (loading || error || !styles) return null
503
-
504
- return (
505
- <div style={{
506
- backgroundColor: styles.colors.primaryBackground,
507
- color: styles.colors.primaryColor,
508
- fontFamily: styles.font.fontFamily
509
- }}>
510
- Custom styled content
511
- </div>
512
- )
513
- }
514
- ```
515
-
516
- ### Multi-entity Whitelabeling
517
-
518
- ```typescript
519
- import React, { useState } from 'react'
520
- import { useWhitelabel } from './useWhitelabel'
521
-
522
- const MultiEntityDemo: React.FC = () => {
523
- const [selectedEntity, setSelectedEntity] = useState('entity-1')
524
-
525
- const entities = [
526
- { id: 'entity-1', name: 'Company A' },
527
- { id: 'entity-2', name: 'Company B' },
528
- { id: 'entity-3', name: 'Company C' }
529
- ]
530
-
531
- const { data: whitelabelData, loading } = useWhitelabel(selectedEntity)
532
-
533
- return (
534
- <div>
535
- <select
536
- value={selectedEntity}
537
- onChange={(e) => setSelectedEntity(e.target.value)}
538
- >
539
- {entities.map(entity => (
540
- <option key={entity.id} value={entity.id}>
541
- {entity.name}
542
- </option>
543
- ))}
544
- </select>
545
-
546
- {loading ? (
547
- <div>Loading whitelabel data...</div>
548
- ) : (
549
- <WhitelabeledApp entityId={selectedEntity}>
550
- <div>Content for {selectedEntity}</div>
551
- </WhitelabeledApp>
552
- )}
553
- </div>
554
- )
555
- }
556
- ```
557
-
558
- ## Caching Strategy
559
-
560
- ### Memory Cache Implementation
561
-
562
- ```typescript
563
- // Internal caching implementation (simplified)
564
- class WhitelabelCache {
565
- private cache = new Map<string, ProvidedWLSet>()
566
- private ttl = 5 * 60 * 1000 // 5 minutes
567
- private timestamps = new Map<string, number>()
568
-
569
- set(entityId: string, data: ProvidedWLSet): void {
570
- this.cache.set(entityId, data)
571
- this.timestamps.set(entityId, Date.now())
572
- }
573
-
574
- get(entityId: string): ProvidedWLSet | undefined {
575
- const timestamp = this.timestamps.get(entityId)
576
- if (timestamp && Date.now() - timestamp > this.ttl) {
577
- this.cache.delete(entityId)
578
- this.timestamps.delete(entityId)
579
- return undefined
580
- }
581
- return this.cache.get(entityId)
582
- }
583
-
584
- clear(): void {
585
- this.cache.clear()
586
- this.timestamps.clear()
587
- }
588
-
589
- invalidate(entityId: string): void {
590
- this.cache.delete(entityId)
591
- this.timestamps.delete(entityId)
592
- }
593
- }
594
- ```
595
-
596
- ### Cache Management
597
-
598
- ```typescript
599
- // Utility functions for cache management
600
- export const clearWhitelabelCache = (context: Context) => {
601
- const wlService = context.service<WlWebService>('wl-web-service')
602
- // Cache clearing would be implemented in the service
603
- }
604
-
605
- export const preloadWhitelabeling = async (
606
- context: Context,
607
- entityIds: string[]
608
- ) => {
609
- const wlService = context.service<WlWebService>('wl-web-service')
610
-
611
- // Preload whitelabeling data for multiple entities
612
- await Promise.all(
613
- entityIds.map(entityId => wlService.load(entityId))
614
- )
615
- }
616
- ```
617
-
618
- ## Error Handling
619
-
620
- ### Graceful Error Handling
621
-
622
- ```typescript
623
- const ErrorBoundaryWhitelabel: React.FC<{
624
- children: React.ReactNode
625
- fallback?: React.ReactNode
626
- }> = ({ children, fallback }) => {
627
- return (
628
- <ErrorBoundary
629
- fallback={fallback || <div>Failed to load branding</div>}
630
- onError={(error) => {
631
- console.error('Whitelabeling error:', error)
632
- // Report to error tracking service
633
- }}
634
- >
635
- {children}
636
- </ErrorBoundary>
637
- )
638
- }
639
-
640
- // Usage
641
- <ErrorBoundaryWhitelabel fallback={<DefaultBranding />}>
642
- <WhitelabeledApp entityId={entityId}>
643
- <AppContent />
644
- </WhitelabeledApp>
645
- </ErrorBoundaryWhitelabel>
646
- ```
647
-
648
- ## Performance Optimization
649
-
650
- ### Lazy Loading and Code Splitting
651
-
652
- ```typescript
653
- import React, { lazy, Suspense } from 'react'
654
-
655
- // Lazy load whitelabel components
656
- const WhitelabeledDashboard = lazy(() => import('./WhitelabeledDashboard'))
657
-
658
- const App: React.FC = () => (
659
- <Suspense fallback={<div>Loading...</div>}>
660
- <WhitelabeledDashboard entityId="company-123" />
661
- </Suspense>
662
- )
663
- ```
664
-
665
- ### Memoization
666
-
667
- ```typescript
668
- import React, { memo, useMemo } from 'react'
669
-
670
- const MemoizedWhitelabelComponent = memo<{ entityId: string }>(({ entityId }) => {
671
- const { data } = useWhitelabel(entityId, 'company-provider')
672
-
673
- const memoizedContent = useMemo(() => {
674
- if (!data) return null
675
-
676
- return (
677
- <div>
678
- <h1>{data.fullName}</h1>
679
- <p>{data.description}</p>
680
- </div>
681
- )
682
- }, [data])
683
-
684
- return memoizedContent
685
- })
686
- ```
687
-
688
- ## Integration with OwlMeans Ecosystem
689
-
690
- ### Context Integration
691
- ```typescript
692
- import { makeWebContext } from '@owlmeans/web-client'
693
-
694
- const context = makeWebContext(config)
695
- const wlService = context.service<WlWebService>('wl-web-service')
696
- ```
697
-
698
- ### Module System Integration
699
- ```typescript
700
- import { modules } from '@owlmeans/web-wl'
701
-
702
- // Modules are automatically integrated via service
703
- context.registerService(wlService)
704
- ```
705
-
706
- ### Client Integration
707
- ```typescript
708
- import { useContext } from '@owlmeans/client'
709
-
710
- const wlService = useContext().service<WlWebService>('wl-web-service')
711
- ```
712
-
713
- ## Best Practices
714
-
715
- 1. **Caching**: Implement appropriate caching strategies for performance
716
- 2. **Error Handling**: Provide graceful fallbacks for failed whitelabeling requests
717
- 3. **Performance**: Use memoization and lazy loading for large applications
718
- 4. **User Experience**: Show loading states during whitelabeling data fetch
719
- 5. **Accessibility**: Ensure dynamic content maintains accessibility standards
720
- 6. **Testing**: Test with different entity configurations and error scenarios
47
+ - `DEFAULT_ALIAS` — `'wl-web-serivce'`
721
48
 
722
49
  ## Related Packages
723
50
 
724
- - **@owlmeans/wled**: Core whitelabeling types and modules
725
- - **@owlmeans/client-wl**: Base client whitelabeling functionality
726
- - **@owlmeans/server-wl**: Server-side whitelabeling implementation
727
- - **@owlmeans/client**: Base client functionality
728
- - **@owlmeans/client-module**: Client module system for API calls
729
-
730
- ## TypeScript Support
731
-
732
- This package is written in TypeScript and provides full type safety:
733
-
734
- ```typescript
735
- import type {
736
- WlWebService,
737
- ProvidedWLSet,
738
- Config,
739
- Context
740
- } from '@owlmeans/web-wl'
741
-
742
- const wlService: WlWebService = makeWlService()
743
- const context: Context = makeWebContext(config)
744
- ```
51
+ - [`@owlmeans/wled`](../wled) shared whitelabel types and constants
52
+ - [`@owlmeans/client-wl`](../client-wl) client-side whitelabel placeholder
53
+ - [`@owlmeans/web-client`](../web-client) base web context this service runs in
54
+ - [`@owlmeans/web-panel`](../web-panel) typical app-side `makeContext` foundation
@@ -1,3 +1,3 @@
1
- import type { ClientModule } from '@owlmeans/client-module';
2
- export declare const modules: ClientModule<unknown>[];
1
+ import type { ClientEntrypoint } from '@owlmeans/client-entrypoint';
2
+ export declare const modules: ClientEntrypoint<unknown>[];
3
3
  //# sourceMappingURL=modules.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"modules.d.ts","sourceRoot":"","sources":["../src/modules.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAK3D,eAAO,MAAM,OAAO,EAAgB,YAAY,CAAC,OAAO,CAAC,EAAE,CAAA"}
1
+ {"version":3,"file":"modules.d.ts","sourceRoot":"","sources":["../src/modules.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AAKnE,eAAO,MAAM,OAAO,EAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAA"}
package/build/modules.js CHANGED
@@ -1,4 +1,4 @@
1
- import { elevate } from '@owlmeans/client-module';
1
+ import { elevate } from '@owlmeans/client-entrypoint';
2
2
  import { WL_PROVIDE, modules as wlModules } from '@owlmeans/wled';
3
3
  elevate(wlModules, WL_PROVIDE);
4
4
  export const modules = wlModules;
@@ -1 +1 @@
1
- {"version":3,"file":"modules.js","sourceRoot":"","sources":["../src/modules.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAA;AAEjD,OAAO,EAAE,UAAU,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAEjE,OAAO,CAAC,SAAS,EAAE,UAAU,CAAC,CAAA;AAE9B,MAAM,CAAC,MAAM,OAAO,GAAG,SAAoC,CAAA"}
1
+ {"version":3,"file":"modules.js","sourceRoot":"","sources":["../src/modules.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AAErD,OAAO,EAAE,UAAU,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAEjE,OAAO,CAAC,SAAS,EAAE,UAAU,CAAC,CAAA;AAE9B,MAAM,CAAC,MAAM,OAAO,GAAG,SAAwC,CAAA"}
package/build/service.js CHANGED
@@ -9,7 +9,7 @@ export const makeWlService = (alias = DEFAULT_ALIAS) => {
9
9
  return cache[entityId];
10
10
  }
11
11
  const context = service.assertCtx();
12
- const module = context.module(WL_PROVIDE);
12
+ const module = context.entrypoint(WL_PROVIDE);
13
13
  const [wlSet] = await module.call({ params: { entity: entityId } });
14
14
  return cache[entityId] = wlSet;
15
15
  },
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE3C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAG3C,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,QAAgB,aAAa,EAAgB,EAAE;IAC3E,MAAM,KAAK,GAA0C,EAAE,CAAA;IAEvD,MAAM,OAAO,GAAiB,aAAa,CAAe,KAAK,EAAE;QAC/D,IAAI,EAAE,KAAK,EAAC,QAAQ,EAAC,EAAE;YACrB,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC;gBAC5B,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAA;YACxB,CAAC;YAED,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,EAAmB,CAAA;YAEpD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAA8B,UAAU,CAAC,CAAA;YACtE,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAA;YAEnE,OAAO,KAAK,CAAC,QAAQ,CAAC,GAAG,KAA2B,CAAA;QACtD,CAAC;QAED,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC;KAChC,CAAC,CAAA;IAEF,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE3C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAG3C,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,QAAgB,aAAa,EAAgB,EAAE;IAC3E,MAAM,KAAK,GAA0C,EAAE,CAAA;IAEvD,MAAM,OAAO,GAAiB,aAAa,CAAe,KAAK,EAAE;QAC/D,IAAI,EAAE,KAAK,EAAC,QAAQ,EAAC,EAAE;YACrB,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC;gBAC5B,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAA;YACxB,CAAC;YAED,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,EAAmB,CAAA;YAEpD,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,CAAkC,UAAU,CAAC,CAAA;YAC9E,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAA;YAEnE,OAAO,KAAK,CAAC,QAAQ,CAAC,GAAG,KAA2B,CAAA;QACtD,CAAC;QAED,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC;KAChC,CAAC,CAAA;IAEF,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmeans/web-wl",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -21,18 +21,19 @@
21
21
  }
22
22
  },
23
23
  "dependencies": {
24
- "@owlmeans/client": "^0.1.2",
25
- "@owlmeans/client-module": "^0.1.2",
26
- "@owlmeans/context": "^0.1.2",
27
- "@owlmeans/wled": "^0.1.2"
24
+ "@owlmeans/client": "^0.1.4",
25
+ "@owlmeans/client-entrypoint": "^0.1.4",
26
+ "@owlmeans/context": "^0.1.4",
27
+ "@owlmeans/wled": "^0.1.4"
28
28
  },
29
29
  "peerDependencies": {
30
30
  "react": "*"
31
31
  },
32
32
  "devDependencies": {
33
+ "@owlmeans/dep-config": "workspace:*",
33
34
  "@types/react": "^19.2.7",
34
35
  "nodemon": "^3.1.11",
35
- "typescript": "^5.8.3"
36
+ "typescript": "^6.0.2"
36
37
  },
37
38
  "publishConfig": {
38
39
  "access": "public"
package/src/modules.ts CHANGED
@@ -1,8 +1,8 @@
1
1
 
2
- import { elevate } from '@owlmeans/client-module'
3
- import type { ClientModule } from '@owlmeans/client-module'
2
+ import { elevate } from '@owlmeans/client-entrypoint'
3
+ import type { ClientEntrypoint } from '@owlmeans/client-entrypoint'
4
4
  import { WL_PROVIDE, modules as wlModules } from '@owlmeans/wled'
5
5
 
6
6
  elevate(wlModules, WL_PROVIDE)
7
7
 
8
- export const modules = wlModules as ClientModule<unknown>[]
8
+ export const modules = wlModules as ClientEntrypoint<unknown>[]
package/src/service.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ClientModule } from '@owlmeans/client-module'
1
+ import type { ClientEntrypoint } from '@owlmeans/client-entrypoint'
2
2
  import { DEFAULT_ALIAS } from './consts.js'
3
3
  import type { Config, Context, ProvidedWLSet, WlWebService } from './types.js'
4
4
  import { createService } from '@owlmeans/context'
@@ -16,7 +16,7 @@ export const makeWlService = (alias: string = DEFAULT_ALIAS): WlWebService => {
16
16
 
17
17
  const context = service.assertCtx<Config, Context>()
18
18
 
19
- const module = context.module<ClientModule<ProvidedWLSet>>(WL_PROVIDE)
19
+ const module = context.entrypoint<ClientEntrypoint<ProvidedWLSet>>(WL_PROVIDE)
20
20
  const [wlSet] = await module.call({ params: { entity: entityId } })
21
21
 
22
22
  return cache[entityId] = wlSet as ProvidedWLSet<any>
package/tsconfig.json CHANGED
@@ -1,16 +1,11 @@
1
1
  {
2
2
  "extends": [
3
- "../tsconfig.default.json",
4
- "../tsconfig.react.json",
3
+ "@owlmeans/dep-config/tsconfig.base.json",
4
+ "@owlmeans/dep-config/tsconfig.react.json"
5
5
  ],
6
6
  "compilerOptions": {
7
- "rootDir": "./src/", /* Specify the root folder within your source files. */
8
- "outDir": "./build/", /* Specify an output folder for all emitted files. */
9
- "moduleResolution": "Bundler",
7
+ "rootDir": "./src/",
8
+ "outDir": "./build/"
10
9
  },
11
- "exclude": [
12
- "./dist/**/*",
13
- "./build/**/*",
14
- "./*.ts"
15
- ]
10
+ "exclude": ["./dist/**/*", "./build/**/*", "./*.ts"]
16
11
  }