@owlmeans/route 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 +561 -0
- package/build/.gitkeep +0 -0
- package/build/consts.d.ts +13 -0
- package/build/consts.d.ts.map +1 -0
- package/build/consts.js +15 -0
- package/build/consts.js.map +1 -0
- package/build/helper.d.ts +12 -0
- package/build/helper.d.ts.map +1 -0
- package/build/helper.js +40 -0
- package/build/helper.js.map +1 -0
- package/build/index.d.ts +5 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +5 -0
- package/build/index.js.map +1 -0
- package/build/model.d.ts +5 -0
- package/build/model.d.ts.map +1 -0
- package/build/model.js +20 -0
- package/build/model.js.map +1 -0
- package/build/types.d.ts +35 -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/route.d.ts +9 -0
- package/build/utils/route.d.ts.map +1 -0
- package/build/utils/route.js +103 -0
- package/build/utils/route.js.map +1 -0
- package/build/utils/service.d.ts +4 -0
- package/build/utils/service.d.ts.map +1 -0
- package/build/utils/service.js +5 -0
- package/build/utils/service.js.map +1 -0
- package/build/utils/types.d.ts +5 -0
- package/build/utils/types.d.ts.map +1 -0
- package/build/utils/types.js +2 -0
- package/build/utils/types.js.map +1 -0
- package/package.json +40 -0
- package/src/consts.ts +16 -0
- package/src/helper.ts +54 -0
- package/src/index.ts +5 -0
- package/src/model.ts +25 -0
- package/src/types.ts +40 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/route.ts +121 -0
- package/src/utils/service.ts +9 -0
- package/src/utils/types.ts +5 -0
- package/tsconfig.json +14 -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,561 @@
|
|
|
1
|
+
# @owlmeans/route
|
|
2
|
+
|
|
3
|
+
Cross-environment routing library for OwlMeans applications that provides structures for URLs, URIs, aliases, permissions, and validations.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The `@owlmeans/route` module is a core component of the OwlMeans Common library suite that provides routing functionality as part of the OwlMeans Common Module approach (described in `@owlmeans/context`). This module is not self-sufficient and is designed to work within the OwlMeans Common Module ecosystem.
|
|
8
|
+
|
|
9
|
+
### Understanding "Modules" in OwlMeans Common Libraries
|
|
10
|
+
|
|
11
|
+
The term "module" in the context of OwlMeans Common libraries refers not to a programmatic module but to a **URL unit** in the system. The OwlMeans Common libraries are intended for fullstack microservices and microclients development, where modules serve as a central registry for URL structures.
|
|
12
|
+
|
|
13
|
+
Modules provide several key capabilities:
|
|
14
|
+
|
|
15
|
+
- **URL Declaration and Nesting** - Define hierarchical URL structures that can be shared across services
|
|
16
|
+
- **Context-Aware Transformation** - Transform module definitions into routes based on frontend or backend context
|
|
17
|
+
- **Handler Attachment** - On the backend, attach handlers to routes; on the frontend, specify which components to render
|
|
18
|
+
- **URL Generation** - Generate final URLs for navigation or API calls on both backend and frontend
|
|
19
|
+
- **Centralized Registration** - Provide a single place where all possible routes are registered, allowing micro-applications and micro-services to seamlessly address different parts of the system
|
|
20
|
+
|
|
21
|
+
This approach enables consistent URL management across distributed systems while maintaining flexibility for different deployment contexts.
|
|
22
|
+
|
|
23
|
+
### Key Features
|
|
24
|
+
|
|
25
|
+
- **Routes** - Cross-environment structures consisting of URLs, URIs, aliases, permissions, and validations (POJO)
|
|
26
|
+
- **Route Models** - Wrapper objects that add behavior to route POJOs with resolution capabilities
|
|
27
|
+
- **Service Routes** - Routes that define service endpoints and configurations
|
|
28
|
+
- **Resolution Logic** - Context-aware route resolution with parent-child relationships
|
|
29
|
+
- **Helper Functions** - Utilities for creating, manipulating, and working with routes
|
|
30
|
+
|
|
31
|
+
## Core Concepts
|
|
32
|
+
|
|
33
|
+
### Route
|
|
34
|
+
A route is a cross-environment structure that defines how to access a particular endpoint or resource. It includes:
|
|
35
|
+
- **Alias** - Unique identifier for the route
|
|
36
|
+
- **Path** - URL path pattern
|
|
37
|
+
- **Parent** - Optional parent route for hierarchical structures
|
|
38
|
+
- **Method** - HTTP method (GET, POST, PUT, PATCH)
|
|
39
|
+
- **Protocol** - Communication protocol (HTTP, WebSocket)
|
|
40
|
+
- **Security** - Whether the route requires secure connections
|
|
41
|
+
|
|
42
|
+
### Route Model
|
|
43
|
+
A route model wraps a route POJO with additional behavior, particularly the ability to resolve the route within a given context.
|
|
44
|
+
|
|
45
|
+
### Service Route
|
|
46
|
+
A service route is an object that describes the base URL of a service (host, port, and other connection details). It differs from a regular route object, which describes a specific URL within a service.
|
|
47
|
+
|
|
48
|
+
## Installation
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npm install @owlmeans/route
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## API Reference
|
|
55
|
+
|
|
56
|
+
### Types
|
|
57
|
+
|
|
58
|
+
#### CommonRoute
|
|
59
|
+
Main route interface that extends BasicRoute with additional properties.
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
interface CommonRoute extends BasicRoute {
|
|
63
|
+
alias: string // Unique identifier for the route
|
|
64
|
+
path: string // URL path pattern
|
|
65
|
+
parent?: string // Optional parent route alias
|
|
66
|
+
default?: boolean // Whether this is a default route
|
|
67
|
+
method?: RouteMethod // HTTP method
|
|
68
|
+
protocol?: RouteProtocols // Communication protocol
|
|
69
|
+
secure?: boolean // Whether secure connection is required
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
#### CommonServiceRoute
|
|
74
|
+
Service route interface that describes the base URL of a service.
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
interface CommonServiceRoute extends BasicRoute {
|
|
78
|
+
home?: string // Home path for the service
|
|
79
|
+
service: string // Service identifier
|
|
80
|
+
default?: boolean // Whether this is a default service
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Note:** A service route describes the base URL of a service (such as host and port), while a regular route describes a specific URL within that service.
|
|
85
|
+
|
|
86
|
+
#### BasicRoute
|
|
87
|
+
Base route interface with common properties.
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
interface BasicRoute {
|
|
91
|
+
type: AppType // Application type (Backend/Frontend)
|
|
92
|
+
service?: string // Service identifier
|
|
93
|
+
host?: string // Host address
|
|
94
|
+
port?: number // Port number
|
|
95
|
+
base?: string // Base path
|
|
96
|
+
resolved: boolean // Whether route is resolved
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
#### CommonRouteModel
|
|
101
|
+
Route model that wraps a route with resolution capabilities.
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
interface CommonRouteModel {
|
|
105
|
+
route: CommonRoute // The wrapped route
|
|
106
|
+
resolve: <C extends BasicConfig, T extends BasicContext<C>>(context: T) => Promise<CommonRoute>
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
#### RouteOptions
|
|
111
|
+
Partial CommonRoute options for route creation.
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
interface RouteOptions extends Partial<CommonRoute> {
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Constants
|
|
119
|
+
|
|
120
|
+
#### RouteMethod
|
|
121
|
+
Enumeration of supported HTTP methods.
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
enum RouteMethod {
|
|
125
|
+
GET = 'get',
|
|
126
|
+
POST = 'post',
|
|
127
|
+
PATCH = 'patch',
|
|
128
|
+
PUT = 'put'
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
#### RouteProtocols
|
|
133
|
+
Enumeration of supported communication protocols.
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
enum RouteProtocols {
|
|
137
|
+
WEB = 'http',
|
|
138
|
+
SOCKET = 'ws'
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
#### SEP
|
|
143
|
+
Path separator constant.
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
const SEP = '/'
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
#### PARAM
|
|
150
|
+
Parameter prefix constant.
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
const PARAM = ':'
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Core Functions
|
|
157
|
+
|
|
158
|
+
#### route(alias, path, opts?)
|
|
159
|
+
Creates a route model from the given parameters.
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
const route: CreateRouteSignature<CommonRouteModel> = (alias, path, opts?) => CommonRouteModel
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Parameters:**
|
|
166
|
+
- `alias: string` - Unique identifier for the route
|
|
167
|
+
- `path: string` - URL path pattern
|
|
168
|
+
- `opts?: RouteOptions | string` - Route options or parent route alias
|
|
169
|
+
|
|
170
|
+
**Returns:** `CommonRouteModel` - Route model with resolve capability
|
|
171
|
+
|
|
172
|
+
**Example:**
|
|
173
|
+
```typescript
|
|
174
|
+
const userRoute = route('user', '/api/users/:id', {
|
|
175
|
+
method: RouteMethod.GET,
|
|
176
|
+
protocol: RouteProtocols.WEB
|
|
177
|
+
})
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### createRoute(alias, path, opts?)
|
|
181
|
+
Creates a route POJO without wrapping it in a model.
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
const createRoute: CreateRouteSignature<CommonRoute> = (alias, path, opts?) => CommonRoute
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**Parameters:**
|
|
188
|
+
- `alias: string` - Unique identifier for the route
|
|
189
|
+
- `path: string` - URL path pattern
|
|
190
|
+
- `opts?: RouteOptions | string` - Route options or parent route alias
|
|
191
|
+
|
|
192
|
+
**Returns:** `CommonRoute` - Route POJO
|
|
193
|
+
|
|
194
|
+
**Example:**
|
|
195
|
+
```typescript
|
|
196
|
+
const apiRoute = createRoute('api', '/api', {
|
|
197
|
+
type: AppType.Backend,
|
|
198
|
+
secure: true
|
|
199
|
+
})
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
#### makeRouteModel(route)
|
|
203
|
+
Creates a route model from a route POJO.
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
const makeRouteModel = (route: CommonRoute): CommonRouteModel
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
**Parameters:**
|
|
210
|
+
- `route: CommonRoute` - Route POJO to wrap
|
|
211
|
+
|
|
212
|
+
**Returns:** `CommonRouteModel` - Route model with resolve capability
|
|
213
|
+
|
|
214
|
+
### Helper Functions
|
|
215
|
+
|
|
216
|
+
#### normalizePath(path)
|
|
217
|
+
Normalizes a URL path by removing leading/trailing slashes and trimming whitespace.
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
const normalizePath = (path: string): string
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**Parameters:**
|
|
224
|
+
- `path: string` - Path to normalize
|
|
225
|
+
|
|
226
|
+
**Returns:** `string` - Normalized path
|
|
227
|
+
|
|
228
|
+
**Example:**
|
|
229
|
+
```typescript
|
|
230
|
+
normalizePath('/api/users/') // Returns 'api/users'
|
|
231
|
+
normalizePath(' /api/ ') // Returns 'api'
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
#### rtype(type, opts?)
|
|
235
|
+
Creates route options with a specific application type.
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
const rtype = (type: AppType, opts?: RouteOptions | string): Partial<RouteOptions>
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**Parameters:**
|
|
242
|
+
- `type: AppType` - Application type (Backend/Frontend)
|
|
243
|
+
- `opts?: RouteOptions | string` - Additional options or parent route alias
|
|
244
|
+
|
|
245
|
+
**Returns:** `Partial<RouteOptions>` - Route options with type set
|
|
246
|
+
|
|
247
|
+
#### backend(opts?, method?)
|
|
248
|
+
Creates route options configured for backend routes.
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
const backend = (opts?: RouteOptions | string | null, method?: RouteOptions | RouteMethod): Partial<RouteOptions>
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
**Parameters:**
|
|
255
|
+
- `opts?: RouteOptions | string | null` - Route options or parent route alias
|
|
256
|
+
- `method?: RouteOptions | RouteMethod` - HTTP method or additional options
|
|
257
|
+
|
|
258
|
+
**Returns:** `Partial<RouteOptions>` - Backend route options
|
|
259
|
+
|
|
260
|
+
**Example:**
|
|
261
|
+
```typescript
|
|
262
|
+
const backendRoute = route('api', '/api', backend(null, RouteMethod.GET))
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
#### frontend(opts?, def?)
|
|
266
|
+
Creates route options configured for frontend routes.
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
const frontend = (opts?: RouteOptions | string | null, def?: RouteOptions | boolean): Partial<RouteOptions>
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
**Parameters:**
|
|
273
|
+
- `opts?: RouteOptions | string | null` - Route options or parent route alias
|
|
274
|
+
- `def?: RouteOptions | boolean` - Default flag or additional options
|
|
275
|
+
|
|
276
|
+
**Returns:** `Partial<RouteOptions>` - Frontend route options
|
|
277
|
+
|
|
278
|
+
**Example:**
|
|
279
|
+
```typescript
|
|
280
|
+
const frontendRoute = route('home', '/', frontend(null, true))
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
#### service(service, opts?)
|
|
284
|
+
Creates route options with a specific service identifier.
|
|
285
|
+
|
|
286
|
+
```typescript
|
|
287
|
+
const service = (service: string, opts?: Partial<RouteOptions>): Partial<RouteOptions>
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
**Parameters:**
|
|
291
|
+
- `service: string` - Service identifier
|
|
292
|
+
- `opts?: Partial<RouteOptions>` - Additional route options
|
|
293
|
+
|
|
294
|
+
**Returns:** `Partial<RouteOptions>` - Route options with service set
|
|
295
|
+
|
|
296
|
+
#### socket(opts?, secondary?)
|
|
297
|
+
Creates route options configured for WebSocket routes.
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
const socket = (opts?: RouteOptions | string | null, secondary?: RouteOptions): Partial<RouteOptions>
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
**Parameters:**
|
|
304
|
+
- `opts?: RouteOptions | string | null` - Route options or parent route alias
|
|
305
|
+
- `secondary?: RouteOptions` - Additional options
|
|
306
|
+
|
|
307
|
+
**Returns:** `Partial<RouteOptions>` - WebSocket route options
|
|
308
|
+
|
|
309
|
+
**Example:**
|
|
310
|
+
```typescript
|
|
311
|
+
const socketRoute = route('ws', '/socket', socket())
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Utility Functions
|
|
315
|
+
|
|
316
|
+
#### resolve(route)
|
|
317
|
+
Creates a route resolution function that resolves the route within a given context.
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
const resolve = <C extends Config, T extends BasicContext<C>>(route: CommonRoute) => (context: T) => Promise<CommonRoute>
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
**Parameters:**
|
|
324
|
+
- `route: CommonRoute` - Route to resolve
|
|
325
|
+
|
|
326
|
+
**Returns:** `(context: T) => Promise<CommonRoute>` - Resolution function
|
|
327
|
+
|
|
328
|
+
**Features:**
|
|
329
|
+
- Resolves parent routes recursively
|
|
330
|
+
- Handles service route resolution
|
|
331
|
+
- Manages path concatenation
|
|
332
|
+
- Applies security settings
|
|
333
|
+
- Detects circular dependencies
|
|
334
|
+
|
|
335
|
+
#### getParentRoute(context, route)
|
|
336
|
+
Retrieves and resolves the parent route for a given route.
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
const getParentRoute = async <C extends Config, T extends BasicContext<C>>(context: T, route: CommonRoute): Promise<CommonRoute | null>
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
**Parameters:**
|
|
343
|
+
- `context: T` - Application context
|
|
344
|
+
- `route: CommonRoute` - Route to find parent for
|
|
345
|
+
|
|
346
|
+
**Returns:** `Promise<CommonRoute | null>` - Parent route or null if no parent
|
|
347
|
+
|
|
348
|
+
#### overrideParams(route, overrides, filter?)
|
|
349
|
+
Overrides route parameters with provided values.
|
|
350
|
+
|
|
351
|
+
```typescript
|
|
352
|
+
const overrideParams = (route: CommonRoute, overrides?: Partial<CommonRoute>, filter?: string[]) => void
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
**Parameters:**
|
|
356
|
+
- `route: CommonRoute` - Route to modify
|
|
357
|
+
- `overrides?: Partial<CommonRoute>` - Parameters to override
|
|
358
|
+
- `filter?: string[]` - Optional filter for which parameters to override
|
|
359
|
+
|
|
360
|
+
#### prependBase(route)
|
|
361
|
+
Prepends the base path to a route's path.
|
|
362
|
+
|
|
363
|
+
```typescript
|
|
364
|
+
const prependBase = (route: CommonRoute) => string
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
**Parameters:**
|
|
368
|
+
- `route: CommonRoute` - Route to process
|
|
369
|
+
|
|
370
|
+
**Returns:** `string` - Path with base prepended
|
|
371
|
+
|
|
372
|
+
#### isServiceRoute(obj)
|
|
373
|
+
Type guard to check if an object is a service route.
|
|
374
|
+
|
|
375
|
+
```typescript
|
|
376
|
+
const isServiceRoute = (obj?: Object): obj is CommonServiceRoute
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
**Parameters:**
|
|
380
|
+
- `obj?: Object` - Object to check
|
|
381
|
+
|
|
382
|
+
**Returns:** `boolean` - True if object is a service route
|
|
383
|
+
|
|
384
|
+
#### isServiceRouteResolved(route)
|
|
385
|
+
Type guard to check if a service route is resolved.
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
const isServiceRouteResolved = (route: CommonServiceRoute): route is ResolvedServiceRoute
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
**Parameters:**
|
|
392
|
+
- `route: CommonServiceRoute` - Service route to check
|
|
393
|
+
|
|
394
|
+
**Returns:** `boolean` - True if service route is resolved
|
|
395
|
+
|
|
396
|
+
## Usage Examples
|
|
397
|
+
|
|
398
|
+
### Basic Route Creation
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
import { route, RouteMethod, RouteProtocols } from '@owlmeans/route'
|
|
402
|
+
|
|
403
|
+
// Create a simple API route
|
|
404
|
+
const userRoute = route('user', '/api/users/:id', {
|
|
405
|
+
method: RouteMethod.GET,
|
|
406
|
+
protocol: RouteProtocols.WEB
|
|
407
|
+
})
|
|
408
|
+
|
|
409
|
+
// Create a nested route with parent
|
|
410
|
+
const userProfileRoute = route('userProfile', '/profile', 'user')
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
### Backend Route Configuration
|
|
414
|
+
|
|
415
|
+
```typescript
|
|
416
|
+
import { route, backend, RouteMethod } from '@owlmeans/route'
|
|
417
|
+
|
|
418
|
+
// Create a backend API route
|
|
419
|
+
const apiRoute = route('api', '/api', backend())
|
|
420
|
+
|
|
421
|
+
// Create a POST endpoint
|
|
422
|
+
const createUserRoute = route('createUser', '/users', backend('api', RouteMethod.POST))
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### Frontend Route Configuration
|
|
426
|
+
|
|
427
|
+
```typescript
|
|
428
|
+
import { route, frontend } from '@owlmeans/route'
|
|
429
|
+
|
|
430
|
+
// Create a default frontend route
|
|
431
|
+
const homeRoute = route('home', '/', frontend(null, true))
|
|
432
|
+
|
|
433
|
+
// Create a nested frontend route
|
|
434
|
+
const aboutRoute = route('about', '/about', frontend())
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### WebSocket Route Configuration
|
|
438
|
+
|
|
439
|
+
```typescript
|
|
440
|
+
import { route, socket } from '@owlmeans/route'
|
|
441
|
+
|
|
442
|
+
// Create a WebSocket route
|
|
443
|
+
const chatRoute = route('chat', '/chat', socket())
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### Route Resolution
|
|
447
|
+
|
|
448
|
+
```typescript
|
|
449
|
+
import { route, backend } from '@owlmeans/route'
|
|
450
|
+
|
|
451
|
+
// Create a route that needs resolution
|
|
452
|
+
const apiRoute = route('api', '/api', backend())
|
|
453
|
+
|
|
454
|
+
// Resolve the route with context
|
|
455
|
+
const resolvedRoute = await apiRoute.resolve(context)
|
|
456
|
+
console.log(resolvedRoute.host) // Resolved host
|
|
457
|
+
console.log(resolvedRoute.port) // Resolved port
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
### Service Route Usage
|
|
461
|
+
|
|
462
|
+
```typescript
|
|
463
|
+
import { route, service, backend } from '@owlmeans/route'
|
|
464
|
+
|
|
465
|
+
// Create a route with service configuration
|
|
466
|
+
const userServiceRoute = route('userService', '/users', {
|
|
467
|
+
...backend(),
|
|
468
|
+
...service('user-service')
|
|
469
|
+
})
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
## Client-Side Usage
|
|
473
|
+
|
|
474
|
+
For client-side applications, consider using the `@owlmeans/client-route` package which extends this module with additional client-specific functionality:
|
|
475
|
+
|
|
476
|
+
```typescript
|
|
477
|
+
import { route as baseRoute } from '@owlmeans/route'
|
|
478
|
+
import { route as clientRoute } from '@owlmeans/client-route'
|
|
479
|
+
|
|
480
|
+
// Create a base route
|
|
481
|
+
const userRoute = baseRoute('user', '/users/:id')
|
|
482
|
+
|
|
483
|
+
// Wrap with client functionality
|
|
484
|
+
const clientUserRoute = clientRoute(userRoute)
|
|
485
|
+
|
|
486
|
+
// Access client-specific features
|
|
487
|
+
console.log(clientUserRoute.route.partialPath) // '/users/:id'
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
The `@owlmeans/client-route` package provides:
|
|
491
|
+
- **Partial Path Preservation** - Maintains original path patterns for client-side processing
|
|
492
|
+
- **Parameter Extraction** - Utilities for extracting route parameters
|
|
493
|
+
- **Promise-based Resolution** - Enhanced resolution tracking for client applications
|
|
494
|
+
|
|
495
|
+
See the `@owlmeans/client-route` documentation for complete client-side routing capabilities.
|
|
496
|
+
|
|
497
|
+
## Integration with OwlMeans Context
|
|
498
|
+
|
|
499
|
+
The route module is part of the OwlMeans Common Module approach and integrates seamlessly with the OwlMeans context system (see `@owlmeans/context` for more details on the Common Module approach). This module is not self-sufficient and requires the context system to function properly.
|
|
500
|
+
|
|
501
|
+
### Working with Modules and Routes
|
|
502
|
+
|
|
503
|
+
In the OwlMeans ecosystem, modules define URL structures that can be transformed into routes based on the deployment context. Here's how they work together:
|
|
504
|
+
|
|
505
|
+
```typescript
|
|
506
|
+
import { route, backend } from '@owlmeans/route'
|
|
507
|
+
import { BasicContext } from '@owlmeans/context'
|
|
508
|
+
|
|
509
|
+
// Define a module with route structure
|
|
510
|
+
const apiModule = {
|
|
511
|
+
_module: true,
|
|
512
|
+
route: route('api', '/api', backend()),
|
|
513
|
+
|
|
514
|
+
// Nested routes within the module
|
|
515
|
+
users: route('users', '/users', 'api'),
|
|
516
|
+
posts: route('posts', '/posts', 'api'),
|
|
517
|
+
|
|
518
|
+
// Resolution logic
|
|
519
|
+
resolve: async (context) => {
|
|
520
|
+
await apiModule.route.resolve(context)
|
|
521
|
+
await apiModule.users.resolve(context)
|
|
522
|
+
await apiModule.posts.resolve(context)
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// Use the module in different contexts
|
|
527
|
+
const resolvedRoute = await apiModule.route.resolve(context)
|
|
528
|
+
|
|
529
|
+
// Generate URLs for navigation or API calls
|
|
530
|
+
const userApiUrl = await apiModule.users.resolve(backendContext) // Backend API URL
|
|
531
|
+
const userPageUrl = await apiModule.users.resolve(frontendContext) // Frontend page URL
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
### Module-Based Architecture Benefits
|
|
535
|
+
|
|
536
|
+
- **Centralized Route Definition** - All routes are defined in modules and shared across services
|
|
537
|
+
- **Context-Aware Resolution** - Same route definitions work for both frontend and backend
|
|
538
|
+
- **Consistent URL Generation** - URLs are generated consistently across the entire system
|
|
539
|
+
- **Service Integration** - Modules can span multiple microservices while maintaining coherent routing
|
|
540
|
+
|
|
541
|
+
## Error Handling
|
|
542
|
+
|
|
543
|
+
The module provides comprehensive error handling:
|
|
544
|
+
|
|
545
|
+
- **SyntaxError** - Thrown for configuration errors, missing services, or circular dependencies
|
|
546
|
+
- **Type Guards** - Used to ensure type safety when working with service routes
|
|
547
|
+
- **Validation** - Route parameters are validated during resolution
|
|
548
|
+
|
|
549
|
+
## Best Practices
|
|
550
|
+
|
|
551
|
+
1. **Use Aliases** - Always provide meaningful aliases for routes
|
|
552
|
+
2. **Hierarchical Structure** - Organize routes in a parent-child hierarchy when appropriate
|
|
553
|
+
3. **Service Configuration** - Configure services properly in the context for route resolution
|
|
554
|
+
4. **Security** - Set appropriate security flags for routes
|
|
555
|
+
5. **Type Safety** - Use TypeScript interfaces and type guards for better development experience
|
|
556
|
+
|
|
557
|
+
## Related Modules
|
|
558
|
+
|
|
559
|
+
- **@owlmeans/context** - Provides the context system for route resolution
|
|
560
|
+
- **@owlmeans/client-route** - Client-side route implementations and extensions with additional functionality like partial path preservation and parameter extraction
|
|
561
|
+
- **@owlmeans/server-route** - Server-side route implementations
|
package/build/.gitkeep
ADDED
|
File without changes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare enum RouteMethod {
|
|
2
|
+
GET = "get",
|
|
3
|
+
POST = "post",
|
|
4
|
+
PATCH = "patch",
|
|
5
|
+
PUT = "put"
|
|
6
|
+
}
|
|
7
|
+
export declare const SEP = "/";
|
|
8
|
+
export declare const PARAM = ":";
|
|
9
|
+
export declare enum RouteProtocols {
|
|
10
|
+
WEB = "http",
|
|
11
|
+
SOCKET = "ws"
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=consts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AACA,oBAAY,WAAW;IACrB,GAAG,QAAQ;IACX,IAAI,SAAS;IACb,KAAK,UAAU;IACf,GAAG,QAAQ;CACZ;AAED,eAAO,MAAM,GAAG,MAAM,CAAA;AAEtB,eAAO,MAAM,KAAK,MAAM,CAAA;AAExB,oBAAY,cAAc;IACxB,GAAG,SAAS;IACZ,MAAM,OAAO;CACd"}
|
package/build/consts.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export var RouteMethod;
|
|
2
|
+
(function (RouteMethod) {
|
|
3
|
+
RouteMethod["GET"] = "get";
|
|
4
|
+
RouteMethod["POST"] = "post";
|
|
5
|
+
RouteMethod["PATCH"] = "patch";
|
|
6
|
+
RouteMethod["PUT"] = "put";
|
|
7
|
+
})(RouteMethod || (RouteMethod = {}));
|
|
8
|
+
export const SEP = '/';
|
|
9
|
+
export const PARAM = ':';
|
|
10
|
+
export var RouteProtocols;
|
|
11
|
+
(function (RouteProtocols) {
|
|
12
|
+
RouteProtocols["WEB"] = "http";
|
|
13
|
+
RouteProtocols["SOCKET"] = "ws";
|
|
14
|
+
})(RouteProtocols || (RouteProtocols = {}));
|
|
15
|
+
//# sourceMappingURL=consts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consts.js","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AACA,MAAM,CAAN,IAAY,WAKX;AALD,WAAY,WAAW;IACrB,0BAAW,CAAA;IACX,4BAAa,CAAA;IACb,8BAAe,CAAA;IACf,0BAAW,CAAA;AACb,CAAC,EALW,WAAW,KAAX,WAAW,QAKtB;AAED,MAAM,CAAC,MAAM,GAAG,GAAG,GAAG,CAAA;AAEtB,MAAM,CAAC,MAAM,KAAK,GAAG,GAAG,CAAA;AAExB,MAAM,CAAN,IAAY,cAGX;AAHD,WAAY,cAAc;IACxB,8BAAY,CAAA;IACZ,+BAAa,CAAA;AACf,CAAC,EAHW,cAAc,KAAd,cAAc,QAGzB"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { AppType } from '@owlmeans/context';
|
|
2
|
+
import { RouteMethod } from './consts.js';
|
|
3
|
+
import type { CommonRouteModel, RouteOptions } from './types.js';
|
|
4
|
+
import type { CreateRouteSignature } from './utils/types.js';
|
|
5
|
+
export declare const route: CreateRouteSignature<CommonRouteModel>;
|
|
6
|
+
export declare const normalizePath: (path: string) => string;
|
|
7
|
+
export declare const rtype: (type: AppType, opts?: RouteOptions | string) => Partial<RouteOptions>;
|
|
8
|
+
export declare const backend: (opts?: RouteOptions | string | null, method?: RouteOptions | RouteMethod) => Partial<RouteOptions>;
|
|
9
|
+
export declare const service: (service: string, opts?: Partial<RouteOptions>) => Partial<RouteOptions>;
|
|
10
|
+
export declare const socket: (opts?: RouteOptions | string | null, secondary?: RouteOptions) => Partial<RouteOptions>;
|
|
11
|
+
export declare const frontend: (opts?: RouteOptions | string | null, def?: RouteOptions | boolean) => Partial<RouteOptions>;
|
|
12
|
+
//# sourceMappingURL=helper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAuB,MAAM,aAAa,CAAA;AAE9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAChE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAE5D,eAAO,MAAM,KAAK,EAAE,oBAAoB,CAAC,gBAAgB,CACT,CAAA;AAEhD,eAAO,MAAM,aAAa,SAAU,MAAM,KAAG,MAM5C,CAAA;AAED,eAAO,MAAM,KAAK,SAAU,OAAO,SAAS,YAAY,GAAG,MAAM,KAAG,OAAO,CAAC,YAAY,CAEvF,CAAA;AAED,eAAO,MAAM,OAAO,UAAW,YAAY,GAAG,MAAM,GAAG,IAAI,WAAW,YAAY,GAAG,WAAW,KAAG,OAAO,CAAC,YAAY,CAQtH,CAAA;AAED,eAAO,MAAM,OAAO,YAAa,MAAM,SAAS,OAAO,CAAC,YAAY,CAAC,KAAG,OAAO,CAAC,YAAY,CAI3F,CAAA;AAED,eAAO,MAAM,MAAM,UAAW,YAAY,GAAG,MAAM,GAAG,IAAI,cAAc,YAAY,KAAG,OAAO,CAAC,YAAY,CAM1G,CAAA;AAED,eAAO,MAAM,QAAQ,UAAW,YAAY,GAAG,MAAM,GAAG,IAAI,QAAQ,YAAY,GAAG,OAAO,KAAG,OAAO,CAAC,YAAY,CAQhH,CAAA"}
|
package/build/helper.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { AppType } from '@owlmeans/context';
|
|
2
|
+
import { RouteProtocols, SEP } from './consts.js';
|
|
3
|
+
import { createRoute, makeRouteModel } from './model.js';
|
|
4
|
+
export const route = (alias, path, opts) => makeRouteModel(createRoute(alias, path, opts));
|
|
5
|
+
export const normalizePath = (path) => {
|
|
6
|
+
path = path.trim();
|
|
7
|
+
path = path.endsWith(SEP) ? path.slice(0, -1) : path;
|
|
8
|
+
path = path.startsWith(SEP) ? path.substring(1) : path;
|
|
9
|
+
return path;
|
|
10
|
+
};
|
|
11
|
+
export const rtype = (type, opts) => ({ type, ...(typeof opts === 'string' ? { parent: opts } : opts) });
|
|
12
|
+
export const backend = (opts, method) => {
|
|
13
|
+
if (typeof method === 'string') {
|
|
14
|
+
opts = typeof opts === 'string' ? { parent: opts, method } : { method, ...(opts ?? {}) };
|
|
15
|
+
}
|
|
16
|
+
else if (typeof method === 'object') {
|
|
17
|
+
opts = typeof opts === 'string' ? { ...method, parent: opts } : { ...opts, ...method };
|
|
18
|
+
}
|
|
19
|
+
return rtype(AppType.Backend, opts);
|
|
20
|
+
};
|
|
21
|
+
export const service = (service, opts) => {
|
|
22
|
+
opts = opts ?? {};
|
|
23
|
+
opts.service = service;
|
|
24
|
+
return opts;
|
|
25
|
+
};
|
|
26
|
+
export const socket = (opts, secondary) => {
|
|
27
|
+
const route = backend(opts, secondary);
|
|
28
|
+
route.protocol = RouteProtocols.SOCKET;
|
|
29
|
+
return route;
|
|
30
|
+
};
|
|
31
|
+
export const frontend = (opts, def) => {
|
|
32
|
+
if (typeof def === 'boolean') {
|
|
33
|
+
opts = typeof opts === 'string' ? { parent: opts, default: def } : { default: def, ...(opts ?? {}) };
|
|
34
|
+
}
|
|
35
|
+
else if (typeof def === 'object') {
|
|
36
|
+
opts = typeof opts === 'object' ? { ...opts, ...def } : { parent: opts, ...def };
|
|
37
|
+
}
|
|
38
|
+
return rtype(AppType.Frontend, opts);
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=helper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helper.js","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"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"}
|