@owlmeans/client 0.1.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/LICENSE +21 -0
- package/README.md +688 -0
- package/build/app.d.ts +4 -0
- package/build/app.d.ts.map +1 -0
- package/build/app.js +10 -0
- package/build/app.js.map +1 -0
- package/build/components/index.d.ts +4 -0
- package/build/components/index.d.ts.map +1 -0
- package/build/components/index.js +3 -0
- package/build/components/index.js.map +1 -0
- package/build/components/modal.d.ts +7 -0
- package/build/components/modal.d.ts.map +1 -0
- package/build/components/modal.js +66 -0
- package/build/components/modal.js.map +1 -0
- package/build/components/toggle.d.ts +3 -0
- package/build/components/toggle.d.ts.map +1 -0
- package/build/components/toggle.js +20 -0
- package/build/components/toggle.js.map +1 -0
- package/build/components/types.d.ts +50 -0
- package/build/components/types.d.ts.map +1 -0
- package/build/components/types.js +2 -0
- package/build/components/types.js.map +1 -0
- package/build/consts.d.ts +5 -0
- package/build/consts.d.ts.map +1 -0
- package/build/consts.js +5 -0
- package/build/consts.js.map +1 -0
- package/build/context.d.ts +8 -0
- package/build/context.d.ts.map +1 -0
- package/build/context.js +47 -0
- package/build/context.js.map +1 -0
- package/build/debug.d.ts +4 -0
- package/build/debug.d.ts.map +1 -0
- package/build/debug.js +12 -0
- package/build/debug.js.map +1 -0
- package/build/errors.d.ts +18 -0
- package/build/errors.d.ts.map +1 -0
- package/build/errors.js +34 -0
- package/build/errors.js.map +1 -0
- package/build/helper.d.ts +4 -0
- package/build/helper.d.ts.map +1 -0
- package/build/helper.js +30 -0
- package/build/helper.js.map +1 -0
- package/build/index.d.ts +15 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +15 -0
- package/build/index.js.map +1 -0
- package/build/module.d.ts +3 -0
- package/build/module.d.ts.map +1 -0
- package/build/module.js +4 -0
- package/build/module.js.map +1 -0
- package/build/navigate.d.ts +3 -0
- package/build/navigate.d.ts.map +1 -0
- package/build/navigate.js +39 -0
- package/build/navigate.js.map +1 -0
- package/build/router.d.ts +5 -0
- package/build/router.d.ts.map +1 -0
- package/build/router.js +53 -0
- package/build/router.js.map +1 -0
- package/build/services/debug.d.ts +6 -0
- package/build/services/debug.d.ts.map +1 -0
- package/build/services/debug.js +83 -0
- package/build/services/debug.js.map +1 -0
- package/build/services/index.d.ts +2 -0
- package/build/services/index.d.ts.map +1 -0
- package/build/services/index.js +2 -0
- package/build/services/index.js.map +1 -0
- package/build/store.d.ts +4 -0
- package/build/store.d.ts.map +1 -0
- package/build/store.js +49 -0
- package/build/store.js.map +1 -0
- package/build/types.d.ts +57 -0
- package/build/types.d.ts.map +1 -0
- package/build/types.js +2 -0
- package/build/types.js.map +1 -0
- package/build/utils/index.d.ts +4 -0
- package/build/utils/index.d.ts.map +1 -0
- package/build/utils/index.js +4 -0
- package/build/utils/index.js.map +1 -0
- package/build/utils/module.d.ts +3 -0
- package/build/utils/module.d.ts.map +1 -0
- package/build/utils/module.js +8 -0
- package/build/utils/module.js.map +1 -0
- package/build/utils/route.d.ts +16 -0
- package/build/utils/route.d.ts.map +1 -0
- package/build/utils/route.js +65 -0
- package/build/utils/route.js.map +1 -0
- package/build/utils/router.d.ts +16 -0
- package/build/utils/router.d.ts.map +1 -0
- package/build/utils/router.js +36 -0
- package/build/utils/router.js.map +1 -0
- package/build/value.d.ts +4 -0
- package/build/value.d.ts.map +1 -0
- package/build/value.js +48 -0
- package/build/value.js.map +1 -0
- package/package.json +66 -0
- package/src/app.tsx +17 -0
- package/src/components/index.ts +4 -0
- package/src/components/modal.ts +89 -0
- package/src/components/toggle.ts +22 -0
- package/src/components/types.ts +57 -0
- package/src/consts.ts +7 -0
- package/src/context.ts +61 -0
- package/src/debug.ts +14 -0
- package/src/errors.ts +44 -0
- package/src/helper.tsx +51 -0
- package/src/index.ts +15 -0
- package/src/module.ts +6 -0
- package/src/navigate.ts +51 -0
- package/src/router.ts +78 -0
- package/src/services/debug.ts +102 -0
- package/src/services/index.ts +2 -0
- package/src/store.ts +57 -0
- package/src/types.ts +72 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/module.ts +14 -0
- package/src/utils/route.tsx +82 -0
- package/src/utils/router.ts +60 -0
- package/src/value.ts +60 -0
- package/tsconfig.json +15 -0
- package/tsconfig.tsbuildinfo +1 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 OwlMeans Common — Fullstack typescript framework
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,688 @@
|
|
|
1
|
+
# @owlmeans/client
|
|
2
|
+
|
|
3
|
+
A comprehensive React client library for OwlMeans Common applications. This package provides a complete foundation for building React-based frontend applications with integrated routing, state management, context handling, and component utilities.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The `@owlmeans/client` package extends the base `@owlmeans/client-context` package with React-specific functionality. It provides:
|
|
8
|
+
|
|
9
|
+
- **React Integration**: Complete React integration with hooks and context providers
|
|
10
|
+
- **Routing System**: Advanced routing with React Router integration and module-based navigation
|
|
11
|
+
- **Application Framework**: App component and router setup for complete applications
|
|
12
|
+
- **State Management**: Integrated state management with resource-based persistence
|
|
13
|
+
- **Context Management**: Enhanced client context with React-specific capabilities
|
|
14
|
+
- **UI Components**: Core UI components and utilities for React applications
|
|
15
|
+
- **Navigation Utilities**: Programmatic navigation and router interaction
|
|
16
|
+
- **Debug Services**: Development and debugging utilities
|
|
17
|
+
|
|
18
|
+
This package is designed for environment-agnostic React applications and can be extended with platform-specific implementations:
|
|
19
|
+
- **@owlmeans/web-client**: Web DOM-specific React implementation
|
|
20
|
+
- **@owlmeans/native-client**: React Native-specific implementation
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install @owlmeans/client react react-router react-router-dom
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Core Concepts
|
|
29
|
+
|
|
30
|
+
### Application Architecture
|
|
31
|
+
The library follows the OwlMeans pattern where modules represent URL units that can be transformed into React routes with associated components.
|
|
32
|
+
|
|
33
|
+
### Context-Driven Development
|
|
34
|
+
All functionality is built around a central context that manages services, resources, modules, and application state.
|
|
35
|
+
|
|
36
|
+
### Module-Based Routing
|
|
37
|
+
Routes are generated from modules, providing a unified approach to both frontend routing and backend API endpoints.
|
|
38
|
+
|
|
39
|
+
## API Reference
|
|
40
|
+
|
|
41
|
+
### Factory Functions
|
|
42
|
+
|
|
43
|
+
#### `makeClientContext<C, T>(cfg: C): T`
|
|
44
|
+
|
|
45
|
+
Creates an enhanced client context with React-specific capabilities.
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { makeClientContext } from '@owlmeans/client'
|
|
49
|
+
import { AppType, Layer } from '@owlmeans/context'
|
|
50
|
+
|
|
51
|
+
const context = makeClientContext({
|
|
52
|
+
service: 'my-app',
|
|
53
|
+
type: AppType.Frontend,
|
|
54
|
+
layer: Layer.Service,
|
|
55
|
+
ready: false,
|
|
56
|
+
services: {},
|
|
57
|
+
brand: {},
|
|
58
|
+
trusted: []
|
|
59
|
+
})
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Parameters:**
|
|
63
|
+
- `cfg`: ClientConfig - Configuration object for the context
|
|
64
|
+
|
|
65
|
+
**Returns:** Enhanced ClientContext with React-specific capabilities
|
|
66
|
+
|
|
67
|
+
### Core Interfaces
|
|
68
|
+
|
|
69
|
+
#### `ClientContext<C extends ClientConfig>`
|
|
70
|
+
|
|
71
|
+
Enhanced client context interface that extends BasicClientContext with React-specific functionality.
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
interface ClientContext<C extends ClientConfig = ClientConfig> extends BasicClientContext<C>,
|
|
75
|
+
ConfigResourceAppend,
|
|
76
|
+
StateResourceAppend,
|
|
77
|
+
ModalServiceAppend,
|
|
78
|
+
DebugServiceAppend {
|
|
79
|
+
|
|
80
|
+
// React-specific methods
|
|
81
|
+
registerRerenderer(listener: CallableFunction): () => void
|
|
82
|
+
rerender(): void
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Enhanced Capabilities:**
|
|
87
|
+
- **Config Resource**: Configuration management and persistence
|
|
88
|
+
- **State Resource**: Application state management
|
|
89
|
+
- **Modal Service**: Modal dialog management
|
|
90
|
+
- **Debug Service**: Development and debugging utilities
|
|
91
|
+
- **Rerender System**: Component rerendering coordination
|
|
92
|
+
|
|
93
|
+
#### `RouterModel`
|
|
94
|
+
|
|
95
|
+
Interface for defining application routing structure.
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
interface RouterModel {
|
|
99
|
+
routes: RouteObject[]
|
|
100
|
+
resolve<C, T>(context: T): Promise<RouteObject[]>
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
#### `Navigator`
|
|
105
|
+
|
|
106
|
+
Interface for programmatic navigation throughout the application.
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
interface Navigator {
|
|
110
|
+
_navigate: NavigateFunction
|
|
111
|
+
navigate<R>(module: ClientModule, request?: R): Promise<void>
|
|
112
|
+
go<R>(alias: string, request?: R): Promise<void>
|
|
113
|
+
back(): Promise<void>
|
|
114
|
+
pressBack(): () => void
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
#### `NavRequest<T>`
|
|
119
|
+
|
|
120
|
+
Interface for navigation requests with additional client-specific options.
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
interface NavRequest<T = Record<string, any>> extends Partial<AbstractRequest<T>> {
|
|
124
|
+
replace?: boolean // Replace current route in history
|
|
125
|
+
silent?: boolean // Navigate without triggering side effects
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### `ModuleContextParams<T>`
|
|
130
|
+
|
|
131
|
+
Parameters passed to route components when rendered.
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
interface ModuleContextParams<T = {}> {
|
|
135
|
+
alias: string // Module alias
|
|
136
|
+
params: AbstractRequest<T>['params'] // Route parameters
|
|
137
|
+
path: string // Current path
|
|
138
|
+
context: ClientContext // Application context
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
#### `RoutedComponent<ExtraProps>`
|
|
143
|
+
|
|
144
|
+
Function component interface for route-rendered components.
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
interface RoutedComponent<ExtraProps = {}> extends FC<PropsWithChildren<ModuleContextParams & ExtraProps>> {
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### React Components
|
|
152
|
+
|
|
153
|
+
#### `<App />`
|
|
154
|
+
|
|
155
|
+
Main application component that provides context and routing.
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
interface AppProps extends PropsWithChildren {
|
|
159
|
+
context: ClientContext<any>
|
|
160
|
+
provide?: RouterProvider | RemixRouter
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const App: FC<AppProps>
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
**Usage:**
|
|
167
|
+
```typescript
|
|
168
|
+
import { App, makeClientContext } from '@owlmeans/client'
|
|
169
|
+
|
|
170
|
+
const context = makeClientContext(config)
|
|
171
|
+
|
|
172
|
+
function MyApp() {
|
|
173
|
+
return (
|
|
174
|
+
<App context={context} provide={routerProvider}>
|
|
175
|
+
<div>Application content</div>
|
|
176
|
+
</App>
|
|
177
|
+
)
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
#### `<Router />`
|
|
182
|
+
|
|
183
|
+
Internal router component that manages React Router integration.
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
interface RouterProps {
|
|
187
|
+
provide: RouterProvider | RemixRouter
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const Router: FC<RouterProps>
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**Note:** Usually used internally by the App component.
|
|
194
|
+
|
|
195
|
+
### React Hooks
|
|
196
|
+
|
|
197
|
+
#### `useContext(): ClientContext`
|
|
198
|
+
|
|
199
|
+
Hook to access the application context from any component.
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
import { useContext } from '@owlmeans/client'
|
|
203
|
+
|
|
204
|
+
function MyComponent() {
|
|
205
|
+
const context = useContext()
|
|
206
|
+
|
|
207
|
+
// Access services
|
|
208
|
+
const authService = context.service('auth')
|
|
209
|
+
|
|
210
|
+
// Access resources
|
|
211
|
+
const stateResource = context.state()
|
|
212
|
+
|
|
213
|
+
return <div>Component content</div>
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Context Management
|
|
218
|
+
|
|
219
|
+
#### Enhanced Context Methods
|
|
220
|
+
|
|
221
|
+
The ClientContext provides additional methods beyond the basic context:
|
|
222
|
+
|
|
223
|
+
**`registerRerenderer(listener: CallableFunction): () => void`**
|
|
224
|
+
- **Purpose**: Register a listener for application-wide rerenders
|
|
225
|
+
- **Usage**: Component synchronization and global state updates
|
|
226
|
+
- **Returns**: Cleanup function to unregister the listener
|
|
227
|
+
|
|
228
|
+
**`rerender(): void`**
|
|
229
|
+
- **Purpose**: Trigger a rerender of all registered components
|
|
230
|
+
- **Usage**: Global state changes that require UI updates
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
const context = makeClientContext(config)
|
|
234
|
+
|
|
235
|
+
// Register for rerenders
|
|
236
|
+
const cleanup = context.registerRerenderer(() => {
|
|
237
|
+
console.log('Application rerendered')
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
// Trigger rerender
|
|
241
|
+
context.rerender()
|
|
242
|
+
|
|
243
|
+
// Cleanup when done
|
|
244
|
+
cleanup()
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Navigation System
|
|
248
|
+
|
|
249
|
+
#### Router Utilities
|
|
250
|
+
|
|
251
|
+
**`buildModuleTree(context: ClientContext): ModuleTree`**
|
|
252
|
+
Builds a tree structure from registered modules for routing.
|
|
253
|
+
|
|
254
|
+
**`initializeRouter(context: ClientContext): Promise<RouteObject[]>`**
|
|
255
|
+
Initializes the router with routes generated from modules.
|
|
256
|
+
|
|
257
|
+
**`createRouteRenderer(module: ClientModule): ComponentType`**
|
|
258
|
+
Creates a React component that renders the appropriate component for a module.
|
|
259
|
+
|
|
260
|
+
#### Navigation Methods
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
import { navigate, go, back } from '@owlmeans/client'
|
|
264
|
+
|
|
265
|
+
// Navigate to a specific module
|
|
266
|
+
await navigate(userModule, { params: { id: '123' } })
|
|
267
|
+
|
|
268
|
+
// Navigate by alias
|
|
269
|
+
await go('user-profile', { params: { id: '123' } })
|
|
270
|
+
|
|
271
|
+
// Go back in history
|
|
272
|
+
await back()
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### State Management
|
|
276
|
+
|
|
277
|
+
The package integrates with `@owlmeans/state` for application state management:
|
|
278
|
+
|
|
279
|
+
```typescript
|
|
280
|
+
// Access state resource
|
|
281
|
+
const stateResource = context.state()
|
|
282
|
+
|
|
283
|
+
// Save application state
|
|
284
|
+
await stateResource.save({
|
|
285
|
+
id: 'app-state',
|
|
286
|
+
data: { theme: 'dark', language: 'en' }
|
|
287
|
+
})
|
|
288
|
+
|
|
289
|
+
// Load application state
|
|
290
|
+
const state = await stateResource.load('app-state')
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Configuration Management
|
|
294
|
+
|
|
295
|
+
The package integrates with `@owlmeans/config` for configuration management:
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
// Access config resource
|
|
299
|
+
const configResource = context.config()
|
|
300
|
+
|
|
301
|
+
// Load configuration
|
|
302
|
+
const config = await configResource.load('app-config')
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Modal Management
|
|
306
|
+
|
|
307
|
+
Built-in modal service for managing dialogs:
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
// Access modal service
|
|
311
|
+
const modalService = context.modal()
|
|
312
|
+
|
|
313
|
+
// Show modal
|
|
314
|
+
modalService.show('confirm-dialog', {
|
|
315
|
+
title: 'Confirm Action',
|
|
316
|
+
message: 'Are you sure?'
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
// Hide modal
|
|
320
|
+
modalService.hide('confirm-dialog')
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Debug Service
|
|
324
|
+
|
|
325
|
+
Development and debugging utilities:
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
// Access debug service
|
|
329
|
+
const debugService = context.debug()
|
|
330
|
+
|
|
331
|
+
// Log debug information
|
|
332
|
+
debugService.log('module-routing', 'Route resolved', { alias: 'users' })
|
|
333
|
+
|
|
334
|
+
// Enable debug mode
|
|
335
|
+
debugService.enable('all')
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### Utility Functions
|
|
339
|
+
|
|
340
|
+
#### Route Creation
|
|
341
|
+
|
|
342
|
+
**`createModuleRoute(module: ClientModule, component: ComponentType): RouteObject`**
|
|
343
|
+
Creates a React Router route object from a module and component.
|
|
344
|
+
|
|
345
|
+
**`resolveModulePath(module: ClientModule): string`**
|
|
346
|
+
Resolves the final path for a module considering parent relationships.
|
|
347
|
+
|
|
348
|
+
#### Component Utilities
|
|
349
|
+
|
|
350
|
+
**`withModuleContext(component: ComponentType): RoutedComponent`**
|
|
351
|
+
Higher-order component that injects module context into components.
|
|
352
|
+
|
|
353
|
+
```typescript
|
|
354
|
+
import { withModuleContext } from '@owlmeans/client'
|
|
355
|
+
|
|
356
|
+
const UserProfile = withModuleContext(({ alias, params, context }) => {
|
|
357
|
+
const userId = params.id
|
|
358
|
+
return <div>User Profile for {userId}</div>
|
|
359
|
+
})
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
## Usage Examples
|
|
363
|
+
|
|
364
|
+
### Basic Application Setup
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
import React from 'react'
|
|
368
|
+
import { createRoot } from 'react-dom/client'
|
|
369
|
+
import { App, makeClientContext } from '@owlmeans/client'
|
|
370
|
+
import { createBrowserRouter } from 'react-router-dom'
|
|
371
|
+
import { AppType, Layer } from '@owlmeans/context'
|
|
372
|
+
|
|
373
|
+
// Create application context
|
|
374
|
+
const context = makeClientContext({
|
|
375
|
+
service: 'my-app',
|
|
376
|
+
type: AppType.Frontend,
|
|
377
|
+
layer: Layer.Service,
|
|
378
|
+
ready: false,
|
|
379
|
+
services: {},
|
|
380
|
+
brand: { name: 'My App' },
|
|
381
|
+
trusted: []
|
|
382
|
+
})
|
|
383
|
+
|
|
384
|
+
// Register modules and services
|
|
385
|
+
context.registerModules(modules)
|
|
386
|
+
context.registerService(authService)
|
|
387
|
+
|
|
388
|
+
// Configure and initialize
|
|
389
|
+
await context.configure().init()
|
|
390
|
+
|
|
391
|
+
// Create router provider
|
|
392
|
+
const routerProvider = (routes) => createBrowserRouter(routes)
|
|
393
|
+
|
|
394
|
+
// Render application
|
|
395
|
+
const root = createRoot(document.getElementById('root'))
|
|
396
|
+
root.render(
|
|
397
|
+
<App context={context} provide={routerProvider}>
|
|
398
|
+
<header>My Application</header>
|
|
399
|
+
</App>
|
|
400
|
+
)
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### Module-Based Routing
|
|
404
|
+
|
|
405
|
+
```typescript
|
|
406
|
+
import { module, filter, body } from '@owlmeans/module'
|
|
407
|
+
import { route } from '@owlmeans/route'
|
|
408
|
+
import { UserProfile, UserList } from './components'
|
|
409
|
+
|
|
410
|
+
// Define modules with associated components
|
|
411
|
+
const userListModule = module(route('users', '/users'), {
|
|
412
|
+
component: UserList
|
|
413
|
+
})
|
|
414
|
+
|
|
415
|
+
const userProfileModule = module(
|
|
416
|
+
route('user-profile', '/users/:id'),
|
|
417
|
+
filter(params({
|
|
418
|
+
type: 'object',
|
|
419
|
+
properties: { id: { type: 'string' } },
|
|
420
|
+
required: ['id']
|
|
421
|
+
})),
|
|
422
|
+
{ component: UserProfile }
|
|
423
|
+
)
|
|
424
|
+
|
|
425
|
+
// Register modules
|
|
426
|
+
context.registerModules([userListModule, userProfileModule])
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### Programmatic Navigation
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
import { useContext, navigate, go } from '@owlmeans/client'
|
|
433
|
+
|
|
434
|
+
function NavigationExample() {
|
|
435
|
+
const context = useContext()
|
|
436
|
+
|
|
437
|
+
const handleUserClick = async (userId: string) => {
|
|
438
|
+
const userModule = context.module('user-profile')
|
|
439
|
+
await navigate(userModule, {
|
|
440
|
+
params: { id: userId },
|
|
441
|
+
replace: false
|
|
442
|
+
})
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
const handleBackClick = async () => {
|
|
446
|
+
await go('users')
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
return (
|
|
450
|
+
<div>
|
|
451
|
+
<button onClick={() => handleUserClick('123')}>
|
|
452
|
+
View User
|
|
453
|
+
</button>
|
|
454
|
+
<button onClick={handleBackClick}>
|
|
455
|
+
Back to Users
|
|
456
|
+
</button>
|
|
457
|
+
</div>
|
|
458
|
+
)
|
|
459
|
+
}
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
### Context Usage in Components
|
|
463
|
+
|
|
464
|
+
```typescript
|
|
465
|
+
import { useContext } from '@owlmeans/client'
|
|
466
|
+
|
|
467
|
+
function UserDashboard() {
|
|
468
|
+
const context = useContext()
|
|
469
|
+
|
|
470
|
+
// Access services
|
|
471
|
+
const authService = context.service('auth')
|
|
472
|
+
const apiService = context.service('api')
|
|
473
|
+
|
|
474
|
+
// Access resources
|
|
475
|
+
const stateResource = context.state()
|
|
476
|
+
const configResource = context.config()
|
|
477
|
+
|
|
478
|
+
// Access utilities
|
|
479
|
+
const modalService = context.modal()
|
|
480
|
+
const debugService = context.debug()
|
|
481
|
+
|
|
482
|
+
const handleSaveState = async () => {
|
|
483
|
+
await stateResource.save({
|
|
484
|
+
id: 'dashboard-state',
|
|
485
|
+
data: { collapsed: false, activeTab: 'users' }
|
|
486
|
+
})
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
const handleShowModal = () => {
|
|
490
|
+
modalService.show('settings-modal')
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
return (
|
|
494
|
+
<div>
|
|
495
|
+
<h1>Dashboard</h1>
|
|
496
|
+
<button onClick={handleSaveState}>Save State</button>
|
|
497
|
+
<button onClick={handleShowModal}>Settings</button>
|
|
498
|
+
</div>
|
|
499
|
+
)
|
|
500
|
+
}
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
### Advanced Router Configuration
|
|
504
|
+
|
|
505
|
+
```typescript
|
|
506
|
+
import { createBrowserRouter } from 'react-router-dom'
|
|
507
|
+
import { initializeRouter } from '@owlmeans/client'
|
|
508
|
+
|
|
509
|
+
// Custom router provider with error handling
|
|
510
|
+
const customRouterProvider = async (routes) => {
|
|
511
|
+
return createBrowserRouter(routes, {
|
|
512
|
+
future: {
|
|
513
|
+
v7_normalizeFormMethod: true
|
|
514
|
+
}
|
|
515
|
+
})
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// Use with App component
|
|
519
|
+
<App context={context} provide={customRouterProvider}>
|
|
520
|
+
<ApplicationShell />
|
|
521
|
+
</App>
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
### Component with Module Context
|
|
525
|
+
|
|
526
|
+
```typescript
|
|
527
|
+
import { RoutedComponent } from '@owlmeans/client'
|
|
528
|
+
|
|
529
|
+
const ProductDetails: RoutedComponent<{ extraProp: string }> = ({
|
|
530
|
+
alias,
|
|
531
|
+
params,
|
|
532
|
+
context,
|
|
533
|
+
extraProp
|
|
534
|
+
}) => {
|
|
535
|
+
const productId = params.id
|
|
536
|
+
const debugService = context.debug()
|
|
537
|
+
|
|
538
|
+
debugService.log('product-view', 'Viewing product', { productId })
|
|
539
|
+
|
|
540
|
+
return (
|
|
541
|
+
<div>
|
|
542
|
+
<h1>Product {productId}</h1>
|
|
543
|
+
<p>Extra prop: {extraProp}</p>
|
|
544
|
+
</div>
|
|
545
|
+
)
|
|
546
|
+
}
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
### State and Configuration Management
|
|
550
|
+
|
|
551
|
+
```typescript
|
|
552
|
+
import { useContext } from '@owlmeans/client'
|
|
553
|
+
import { useEffect, useState } from 'react'
|
|
554
|
+
|
|
555
|
+
function AppSettings() {
|
|
556
|
+
const context = useContext()
|
|
557
|
+
const [settings, setSettings] = useState(null)
|
|
558
|
+
|
|
559
|
+
useEffect(() => {
|
|
560
|
+
const loadSettings = async () => {
|
|
561
|
+
const stateResource = context.state()
|
|
562
|
+
const saved = await stateResource.load('app-settings')
|
|
563
|
+
setSettings(saved?.data || { theme: 'light' })
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
loadSettings()
|
|
567
|
+
}, [])
|
|
568
|
+
|
|
569
|
+
const saveSettings = async (newSettings) => {
|
|
570
|
+
const stateResource = context.state()
|
|
571
|
+
await stateResource.save({
|
|
572
|
+
id: 'app-settings',
|
|
573
|
+
data: newSettings
|
|
574
|
+
})
|
|
575
|
+
setSettings(newSettings)
|
|
576
|
+
context.rerender() // Trigger global rerender if needed
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
return (
|
|
580
|
+
<div>
|
|
581
|
+
<h2>Settings</h2>
|
|
582
|
+
{settings && (
|
|
583
|
+
<div>
|
|
584
|
+
<label>
|
|
585
|
+
Theme:
|
|
586
|
+
<select
|
|
587
|
+
value={settings.theme}
|
|
588
|
+
onChange={(e) => saveSettings({ ...settings, theme: e.target.value })}
|
|
589
|
+
>
|
|
590
|
+
<option value="light">Light</option>
|
|
591
|
+
<option value="dark">Dark</option>
|
|
592
|
+
</select>
|
|
593
|
+
</label>
|
|
594
|
+
</div>
|
|
595
|
+
)}
|
|
596
|
+
</div>
|
|
597
|
+
)
|
|
598
|
+
}
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
## Error Handling
|
|
602
|
+
|
|
603
|
+
The package integrates with the OwlMeans error system:
|
|
604
|
+
|
|
605
|
+
```typescript
|
|
606
|
+
import { OwlMeansError } from '@owlmeans/error'
|
|
607
|
+
|
|
608
|
+
// Error boundaries for React components
|
|
609
|
+
class AppErrorBoundary extends React.Component {
|
|
610
|
+
state = { hasError: false, error: null }
|
|
611
|
+
|
|
612
|
+
static getDerivedStateFromError(error) {
|
|
613
|
+
return { hasError: true, error }
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
componentDidCatch(error) {
|
|
617
|
+
const context = this.props.context
|
|
618
|
+
const debugService = context.debug()
|
|
619
|
+
debugService.error('app-error', 'Application error', error)
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
render() {
|
|
623
|
+
if (this.state.hasError) {
|
|
624
|
+
return <div>Something went wrong</div>
|
|
625
|
+
}
|
|
626
|
+
return this.props.children
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
## Performance Considerations
|
|
632
|
+
|
|
633
|
+
1. **Context Optimization**: The context system is optimized for minimal re-renders
|
|
634
|
+
2. **Lazy Loading**: Components and modules can be loaded on demand
|
|
635
|
+
3. **State Persistence**: Application state is efficiently managed and persisted
|
|
636
|
+
4. **Route Optimization**: Routes are generated efficiently from module definitions
|
|
637
|
+
|
|
638
|
+
## Integration with Other Packages
|
|
639
|
+
|
|
640
|
+
### Client Ecosystem
|
|
641
|
+
```typescript
|
|
642
|
+
// Client authentication
|
|
643
|
+
import { makeAuthService } from '@owlmeans/client-auth'
|
|
644
|
+
|
|
645
|
+
// Client resources
|
|
646
|
+
import { makeResourceService } from '@owlmeans/client-resource'
|
|
647
|
+
|
|
648
|
+
// Client modules
|
|
649
|
+
import { modules } from '@owlmeans/client-module'
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
### Platform-Specific Extensions
|
|
653
|
+
```typescript
|
|
654
|
+
// Web DOM implementation
|
|
655
|
+
import { makeWebClient } from '@owlmeans/web-client'
|
|
656
|
+
|
|
657
|
+
// React Native implementation
|
|
658
|
+
import { makeNativeClient } from '@owlmeans/native-client'
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
## Best Practices
|
|
662
|
+
|
|
663
|
+
1. **Single Context**: Use one primary context per application
|
|
664
|
+
2. **Module Organization**: Organize modules hierarchically for better route structure
|
|
665
|
+
3. **State Management**: Use the integrated state resource for application state
|
|
666
|
+
4. **Error Boundaries**: Implement error boundaries for robust error handling
|
|
667
|
+
5. **Performance**: Leverage lazy loading for large applications
|
|
668
|
+
6. **Context Access**: Use the provided hook rather than direct context access
|
|
669
|
+
|
|
670
|
+
## Dependencies
|
|
671
|
+
|
|
672
|
+
This package depends on:
|
|
673
|
+
- `@owlmeans/client-context` - Basic client context functionality
|
|
674
|
+
- `@owlmeans/client-module` - Client-side module system
|
|
675
|
+
- `@owlmeans/client-resource` - Client-side resource management
|
|
676
|
+
- `@owlmeans/config` - Configuration management
|
|
677
|
+
- `@owlmeans/context` - Core context system
|
|
678
|
+
- `@owlmeans/state` - State management
|
|
679
|
+
- `react` - React library (peer dependency)
|
|
680
|
+
- `react-router` - React Router (peer dependency)
|
|
681
|
+
|
|
682
|
+
## Related Packages
|
|
683
|
+
|
|
684
|
+
- [`@owlmeans/web-client`](../web-client) - Web DOM-specific React implementation
|
|
685
|
+
- [`@owlmeans/native-client`](../native-client) - React Native implementation
|
|
686
|
+
- [`@owlmeans/client-context`](../client-context) - Basic client context
|
|
687
|
+
- [`@owlmeans/client-module`](../client-module) - Client module system
|
|
688
|
+
- [`@owlmeans/client-auth`](../client-auth) - Client authentication
|
package/build/app.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAA;AAC/B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAK1C,eAAO,MAAM,GAAG,EAAE,EAAE,CAAC,QAAQ,CAS5B,CAAA"}
|