@owlmeans/client-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 +368 -0
- package/build/.gitkeep +0 -0
- package/build/helper.d.ts +4 -0
- package/build/helper.d.ts.map +1 -0
- package/build/helper.js +8 -0
- package/build/helper.js.map +1 -0
- package/build/index.d.ts +4 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +3 -0
- package/build/index.js.map +1 -0
- package/build/model.d.ts +4 -0
- package/build/model.d.ts.map +1 -0
- package/build/model.js +27 -0
- package/build/model.js.map +1 -0
- package/build/types.d.ts +13 -0
- package/build/types.d.ts.map +1 -0
- package/build/types.js +2 -0
- package/build/types.js.map +1 -0
- package/package.json +34 -0
- package/src/helper.ts +11 -0
- package/src/index.ts +4 -0
- package/src/model.ts +42 -0
- package/src/types.ts +15 -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,368 @@
|
|
|
1
|
+
# @owlmeans/client-route
|
|
2
|
+
|
|
3
|
+
Client-side routing library for OwlMeans applications that extends the base `@owlmeans/route` package with client-specific functionality.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The `@owlmeans/client-route` package is a client-side extension of the `@owlmeans/route` module, providing additional functionality specifically designed for frontend applications. It extends the base routing capabilities with client-specific features such as partial path preservation and parameter extraction.
|
|
8
|
+
|
|
9
|
+
This package is part of the OwlMeans Common library suite and follows the OwlMeans Common Module approach (described in `@owlmeans/context`). Like other modules in the suite, it's designed to work within the OwlMeans Common Module ecosystem and is not self-sufficient.
|
|
10
|
+
|
|
11
|
+
### Key Features
|
|
12
|
+
|
|
13
|
+
- **Client Route Models** - Extends base route models with client-specific behavior
|
|
14
|
+
- **Partial Path Preservation** - Maintains original path patterns for client-side processing
|
|
15
|
+
- **Parameter Extraction** - Utility functions for extracting route parameters
|
|
16
|
+
- **Promise-based Resolution** - Manages asynchronous route resolution with state tracking
|
|
17
|
+
- **Type Safety** - Full TypeScript support with proper type definitions
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @owlmeans/client-route
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Note:** This package depends on `@owlmeans/route` and `@owlmeans/client-context`, which will be installed automatically.
|
|
26
|
+
|
|
27
|
+
## Core Concepts
|
|
28
|
+
|
|
29
|
+
### Client Route
|
|
30
|
+
A client route extends the base `CommonRoute` with additional client-specific properties, particularly the `partialPath` which preserves the original path pattern for client-side processing.
|
|
31
|
+
|
|
32
|
+
### Client Route Model
|
|
33
|
+
A client route model wraps a client route with additional behavior, including promise-based resolution tracking and client-specific resolution logic.
|
|
34
|
+
|
|
35
|
+
### Parameter Extraction
|
|
36
|
+
The package provides utilities to extract parameters from route paths, useful for client-side routing and navigation.
|
|
37
|
+
|
|
38
|
+
## API Reference
|
|
39
|
+
|
|
40
|
+
### Types
|
|
41
|
+
|
|
42
|
+
#### ClientRoute
|
|
43
|
+
Extended route interface with client-specific properties.
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
interface ClientRoute extends CommonRoute {
|
|
47
|
+
partialPath: string // Original path pattern preserved for client use
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Properties:**
|
|
52
|
+
- **partialPath**: `string` - The original path pattern before resolution, useful for client-side routing logic
|
|
53
|
+
|
|
54
|
+
#### ClientRouteModel
|
|
55
|
+
Extended route model with client-specific resolution behavior.
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
interface ClientRouteModel extends CommonRouteModel {
|
|
59
|
+
route: ClientRoute // The wrapped client route
|
|
60
|
+
_resolved?: Promise<void> // Promise tracking resolution state
|
|
61
|
+
_client: true // Client route marker
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Properties:**
|
|
66
|
+
- **route**: `ClientRoute` - The wrapped client route object
|
|
67
|
+
- **_resolved**: `Promise<void>` - Optional promise that tracks the resolution state
|
|
68
|
+
- **_client**: `true` - Marker indicating this is a client route model
|
|
69
|
+
|
|
70
|
+
#### ClientRouteOptions
|
|
71
|
+
Options for configuring client routes.
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
interface ClientRouteOptions {
|
|
75
|
+
overrides?: Partial<ClientRoute> // Route parameter overrides
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Properties:**
|
|
80
|
+
- **overrides**: `Partial<ClientRoute>` - Optional route parameter overrides
|
|
81
|
+
|
|
82
|
+
### Core Functions
|
|
83
|
+
|
|
84
|
+
#### route(route, opts?)
|
|
85
|
+
Wraps a base route model with client-specific functionality.
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
const route: (route: CommonRouteModel, opts?: ClientRouteOptions) => ClientRouteModel
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Parameters:**
|
|
92
|
+
- `route: CommonRouteModel` - Base route model from `@owlmeans/route`
|
|
93
|
+
- `opts?: ClientRouteOptions` - Optional configuration options
|
|
94
|
+
|
|
95
|
+
**Returns:** `ClientRouteModel` - Client route model with enhanced functionality
|
|
96
|
+
|
|
97
|
+
**Features:**
|
|
98
|
+
- Preserves original path as `partialPath`
|
|
99
|
+
- Adds promise-based resolution tracking
|
|
100
|
+
- Provides client-specific resolution logic
|
|
101
|
+
- Supports parameter overrides
|
|
102
|
+
|
|
103
|
+
**Example:**
|
|
104
|
+
```typescript
|
|
105
|
+
import { route as baseRoute } from '@owlmeans/route'
|
|
106
|
+
import { route as clientRoute } from '@owlmeans/client-route'
|
|
107
|
+
|
|
108
|
+
// Create a base route
|
|
109
|
+
const userRoute = baseRoute('user', '/users/:id')
|
|
110
|
+
|
|
111
|
+
// Wrap with client functionality
|
|
112
|
+
const clientUserRoute = clientRoute(userRoute, {
|
|
113
|
+
overrides: {
|
|
114
|
+
secure: true
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
// Use client-specific features
|
|
119
|
+
console.log(clientUserRoute.route.partialPath) // '/users/:id'
|
|
120
|
+
const resolved = await clientUserRoute.resolve(context)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Helper Functions
|
|
124
|
+
|
|
125
|
+
#### isClientRouteModel(route)
|
|
126
|
+
Type guard to check if a route object is a client route model.
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
const isClientRouteModel: (route: Object) => route is ClientRouteModel
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Parameters:**
|
|
133
|
+
- `route: Object` - Object to check
|
|
134
|
+
|
|
135
|
+
**Returns:** `boolean` - True if the object is a client route model
|
|
136
|
+
|
|
137
|
+
**Example:**
|
|
138
|
+
```typescript
|
|
139
|
+
import { isClientRouteModel } from '@owlmeans/client-route'
|
|
140
|
+
|
|
141
|
+
if (isClientRouteModel(routeObject)) {
|
|
142
|
+
// TypeScript knows this is a ClientRouteModel
|
|
143
|
+
console.log(routeObject.route.partialPath)
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
#### extractParams(path)
|
|
148
|
+
Extracts parameter names from a route path.
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
const extractParams: (path: string) => string[]
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**Parameters:**
|
|
155
|
+
- `path: string` - Route path pattern
|
|
156
|
+
|
|
157
|
+
**Returns:** `string[]` - Array of parameter names
|
|
158
|
+
|
|
159
|
+
**Example:**
|
|
160
|
+
```typescript
|
|
161
|
+
import { extractParams } from '@owlmeans/client-route'
|
|
162
|
+
|
|
163
|
+
const params = extractParams('/users/:id/posts/:postId')
|
|
164
|
+
console.log(params) // ['id', 'postId']
|
|
165
|
+
|
|
166
|
+
const simpleParams = extractParams('/api/users/:userId')
|
|
167
|
+
console.log(simpleParams) // ['userId']
|
|
168
|
+
|
|
169
|
+
const noParams = extractParams('/api/users')
|
|
170
|
+
console.log(noParams) // []
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Usage Examples
|
|
174
|
+
|
|
175
|
+
### Basic Client Route Creation
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
import { route as baseRoute } from '@owlmeans/route'
|
|
179
|
+
import { route as clientRoute } from '@owlmeans/client-route'
|
|
180
|
+
|
|
181
|
+
// Create a base route
|
|
182
|
+
const apiRoute = baseRoute('api', '/api/users/:id')
|
|
183
|
+
|
|
184
|
+
// Wrap with client functionality
|
|
185
|
+
const clientApiRoute = clientRoute(apiRoute)
|
|
186
|
+
|
|
187
|
+
// Access client-specific features
|
|
188
|
+
console.log(clientApiRoute.route.partialPath) // '/api/users/:id'
|
|
189
|
+
console.log(clientApiRoute._client) // true
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Route Resolution with State Tracking
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
import { route as baseRoute } from '@owlmeans/route'
|
|
196
|
+
import { route as clientRoute } from '@owlmeans/client-route'
|
|
197
|
+
|
|
198
|
+
const userRoute = baseRoute('user', '/users/:id')
|
|
199
|
+
const clientUserRoute = clientRoute(userRoute)
|
|
200
|
+
|
|
201
|
+
// Resolve the route
|
|
202
|
+
const resolved = await clientUserRoute.resolve(context)
|
|
203
|
+
|
|
204
|
+
// The partial path is preserved
|
|
205
|
+
console.log(resolved.partialPath) // '/users/:id'
|
|
206
|
+
console.log(resolved.path) // '/users/123' (resolved)
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Parameter Extraction
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
import { extractParams } from '@owlmeans/client-route'
|
|
213
|
+
|
|
214
|
+
// Extract parameters from different path patterns
|
|
215
|
+
const userParams = extractParams('/users/:id')
|
|
216
|
+
console.log(userParams) // ['id']
|
|
217
|
+
|
|
218
|
+
const nestedParams = extractParams('/users/:userId/posts/:postId/comments/:commentId')
|
|
219
|
+
console.log(nestedParams) // ['userId', 'postId', 'commentId']
|
|
220
|
+
|
|
221
|
+
// Handle paths with no parameters
|
|
222
|
+
const staticParams = extractParams('/api/health')
|
|
223
|
+
console.log(staticParams) // []
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Type Guards and Validation
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
import { isClientRouteModel } from '@owlmeans/client-route'
|
|
230
|
+
import { route as baseRoute } from '@owlmeans/route'
|
|
231
|
+
import { route as clientRoute } from '@owlmeans/client-route'
|
|
232
|
+
|
|
233
|
+
const baseRouteModel = baseRoute('api', '/api')
|
|
234
|
+
const clientRouteModel = clientRoute(baseRouteModel)
|
|
235
|
+
|
|
236
|
+
console.log(isClientRouteModel(baseRouteModel)) // false
|
|
237
|
+
console.log(isClientRouteModel(clientRouteModel)) // true
|
|
238
|
+
|
|
239
|
+
// Type-safe access
|
|
240
|
+
if (isClientRouteModel(someRoute)) {
|
|
241
|
+
console.log(someRoute.route.partialPath) // TypeScript knows this exists
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Route Overrides
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
import { route as baseRoute } from '@owlmeans/route'
|
|
249
|
+
import { route as clientRoute } from '@owlmeans/client-route'
|
|
250
|
+
|
|
251
|
+
const baseUserRoute = baseRoute('user', '/users/:id')
|
|
252
|
+
|
|
253
|
+
// Override route properties
|
|
254
|
+
const clientUserRoute = clientRoute(baseUserRoute, {
|
|
255
|
+
overrides: {
|
|
256
|
+
secure: true,
|
|
257
|
+
method: RouteMethod.GET
|
|
258
|
+
}
|
|
259
|
+
})
|
|
260
|
+
|
|
261
|
+
console.log(clientUserRoute.route.secure) // true
|
|
262
|
+
console.log(clientUserRoute.route.partialPath) // '/users/:id'
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Integration with OwlMeans Context
|
|
266
|
+
|
|
267
|
+
The client-route package integrates seamlessly with the OwlMeans context system and works in conjunction with other OwlMeans Common modules:
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
import { route as baseRoute, frontend } from '@owlmeans/route'
|
|
271
|
+
import { route as clientRoute } from '@owlmeans/client-route'
|
|
272
|
+
import { makeClientContext } from '@owlmeans/client-context'
|
|
273
|
+
|
|
274
|
+
// Create a frontend route
|
|
275
|
+
const homeRoute = baseRoute('home', '/', frontend())
|
|
276
|
+
|
|
277
|
+
// Wrap with client functionality
|
|
278
|
+
const clientHomeRoute = clientRoute(homeRoute)
|
|
279
|
+
|
|
280
|
+
// Use with client context
|
|
281
|
+
const context = makeClientContext(config)
|
|
282
|
+
const resolved = await clientHomeRoute.resolve(context)
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## Advanced Usage
|
|
286
|
+
|
|
287
|
+
### Custom Resolution Logic
|
|
288
|
+
|
|
289
|
+
```typescript
|
|
290
|
+
import { route as baseRoute } from '@owlmeans/route'
|
|
291
|
+
import { route as clientRoute } from '@owlmeans/client-route'
|
|
292
|
+
|
|
293
|
+
const baseRoute = baseRoute('api', '/api/:version')
|
|
294
|
+
const clientApiRoute = clientRoute(baseRoute)
|
|
295
|
+
|
|
296
|
+
// The client route preserves the original path pattern
|
|
297
|
+
const resolved = await clientApiRoute.resolve(context)
|
|
298
|
+
|
|
299
|
+
// Use partial path for client-side routing
|
|
300
|
+
const navigationPath = clientApiRoute.route.partialPath
|
|
301
|
+
const resolvedPath = resolved.path
|
|
302
|
+
|
|
303
|
+
console.log(navigationPath) // '/api/:version' (for client routing)
|
|
304
|
+
console.log(resolvedPath) // '/api/v1' (resolved for actual requests)
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Parameter-Based Navigation
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
import { extractParams } from '@owlmeans/client-route'
|
|
311
|
+
|
|
312
|
+
const buildNavigationUrl = (pathPattern: string, params: Record<string, string>) => {
|
|
313
|
+
const paramNames = extractParams(pathPattern)
|
|
314
|
+
let url = pathPattern
|
|
315
|
+
|
|
316
|
+
paramNames.forEach(param => {
|
|
317
|
+
url = url.replace(`:${param}`, params[param] || '')
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
return url
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Usage
|
|
324
|
+
const pattern = '/users/:userId/posts/:postId'
|
|
325
|
+
const url = buildNavigationUrl(pattern, { userId: '123', postId: '456' })
|
|
326
|
+
console.log(url) // '/users/123/posts/456'
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
## Error Handling
|
|
330
|
+
|
|
331
|
+
The package provides comprehensive error handling:
|
|
332
|
+
|
|
333
|
+
- **SyntaxError** - Thrown when attempting to resolve a route that's already resolved without proper promise handling
|
|
334
|
+
- **Type Guards** - Use `isClientRouteModel` to ensure type safety
|
|
335
|
+
- **Promise Management** - The `_resolved` promise prevents multiple resolution attempts
|
|
336
|
+
|
|
337
|
+
## Best Practices
|
|
338
|
+
|
|
339
|
+
1. **Use Type Guards** - Always use `isClientRouteModel` when working with mixed route types
|
|
340
|
+
2. **Handle Promises** - Properly handle the `_resolved` promise to avoid resolution conflicts
|
|
341
|
+
3. **Preserve Partial Paths** - Use the `partialPath` property for client-side routing logic
|
|
342
|
+
4. **Parameter Extraction** - Use `extractParams` for dynamic route handling
|
|
343
|
+
5. **Integration** - Combine with other OwlMeans Common modules for full functionality
|
|
344
|
+
|
|
345
|
+
## Related Modules
|
|
346
|
+
|
|
347
|
+
- **@owlmeans/route** - Base routing functionality (required dependency)
|
|
348
|
+
- **@owlmeans/client-context** - Client-side context management (required dependency)
|
|
349
|
+
- **@owlmeans/context** - Core context system for route resolution
|
|
350
|
+
- **@owlmeans/server-route** - Server-side route implementations
|
|
351
|
+
|
|
352
|
+
## Migration from @owlmeans/route
|
|
353
|
+
|
|
354
|
+
If you're upgrading from using `@owlmeans/route` directly in a client application:
|
|
355
|
+
|
|
356
|
+
```typescript
|
|
357
|
+
// Before
|
|
358
|
+
import { route } from '@owlmeans/route'
|
|
359
|
+
const userRoute = route('user', '/users/:id')
|
|
360
|
+
|
|
361
|
+
// After
|
|
362
|
+
import { route as baseRoute } from '@owlmeans/route'
|
|
363
|
+
import { route as clientRoute } from '@owlmeans/client-route'
|
|
364
|
+
const userRoute = clientRoute(baseRoute('user', '/users/:id'))
|
|
365
|
+
|
|
366
|
+
// Additional client functionality is now available
|
|
367
|
+
console.log(userRoute.route.partialPath) // '/users/:id'
|
|
368
|
+
```
|
package/build/.gitkeep
ADDED
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAE7C,eAAO,MAAM,kBAAkB,UAAW,MAAM,KAAG,KAAK,IAAI,gBACxC,CAAA;AAEpB,eAAO,MAAM,aAAa,SAAU,MAAM,KAAG,MAAM,EAIlD,CAAA"}
|
package/build/helper.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { PARAM, SEP, normalizePath } from '@owlmeans/route';
|
|
2
|
+
export const isClientRouteModel = (route) => '_client' in route;
|
|
3
|
+
export const extractParams = (path) => {
|
|
4
|
+
path = normalizePath(path);
|
|
5
|
+
return path.split(SEP).map(item => item.startsWith(PARAM) ? item.slice(1) : null)
|
|
6
|
+
.filter(param => param);
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=helper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helper.js","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAG3D,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,KAAa,EAA6B,EAAE,CAC7E,SAAS,IAAI,KAAK,CAAA;AAEpB,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,IAAY,EAAY,EAAE;IACtD,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,CAAA;IAC1B,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;SAC9E,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAa,CAAA;AACvC,CAAC,CAAA"}
|
package/build/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAA;AAC1B,mBAAmB,YAAY,CAAA;AAC/B,cAAc,aAAa,CAAA"}
|
package/build/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAA;AAE1B,cAAc,aAAa,CAAA"}
|
package/build/model.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAItE,eAAO,MAAM,KAAK,UAAW,gBAAgB,SAAS,kBAAkB,KAAG,gBAoC1E,CAAA"}
|
package/build/model.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { resolve, overrideParams } from '@owlmeans/route/utils';
|
|
2
|
+
export const route = (route, opts) => {
|
|
3
|
+
const unresolvedPath = route.route.path;
|
|
4
|
+
const model = {
|
|
5
|
+
...route,
|
|
6
|
+
_client: true,
|
|
7
|
+
resolve: async (context) => {
|
|
8
|
+
if (model.route.resolved) {
|
|
9
|
+
if (model._resolved == null) {
|
|
10
|
+
throw new SyntaxError('Cannot reach resolved state twice without resolving promise');
|
|
11
|
+
}
|
|
12
|
+
await model._resolved;
|
|
13
|
+
return model.route;
|
|
14
|
+
}
|
|
15
|
+
const resolver = {};
|
|
16
|
+
model._resolved = new Promise(resolve => resolver.resolve = resolve);
|
|
17
|
+
await resolve(model.route)(context);
|
|
18
|
+
model.route.partialPath = unresolvedPath;
|
|
19
|
+
resolver.resolve?.();
|
|
20
|
+
return model.route;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
overrideParams(model.route, opts?.overrides);
|
|
24
|
+
model.route.partialPath = unresolvedPath;
|
|
25
|
+
return model;
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAG/D,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,KAAuB,EAAE,IAAyB,EAAoB,EAAE;IAC5F,MAAM,cAAc,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAA;IAEvC,MAAM,KAAK,GAAqB;QAC9B,GAAI,KAA0B;QAE9B,OAAO,EAAE,IAAI;QAEb,OAAO,EAAE,KAAK,EAAK,OAAU,EAAE,EAAE;YAC/B,IAAI,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACzB,IAAI,KAAK,CAAC,SAAS,IAAI,IAAI,EAAE,CAAC;oBAC5B,MAAM,IAAI,WAAW,CAAC,6DAA6D,CAAC,CAAA;gBACtF,CAAC;gBACD,MAAM,KAAK,CAAC,SAAS,CAAA;gBAErB,OAAO,KAAK,CAAC,KAAK,CAAA;YACpB,CAAC;YAED,MAAM,QAAQ,GAA6B,EAAE,CAAA;YAC7C,KAAK,CAAC,SAAS,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,CAAC,OAAO,GAAG,OAAO,CAAC,CAAA;YAEpE,MAAM,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,OAAoC,CAAC,CAAA;YAEhE,KAAK,CAAC,KAAK,CAAC,WAAW,GAAG,cAAc,CAAA;YAExC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAA;YAEpB,OAAO,KAAK,CAAC,KAAK,CAAA;QACpB,CAAC;KACF,CAAA;IAED,cAAc,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,SAAS,CAAC,CAAA;IAE5C,KAAK,CAAC,KAAK,CAAC,WAAW,GAAG,cAAc,CAAA;IAExC,OAAO,KAAK,CAAA;AACd,CAAC,CAAA"}
|
package/build/types.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CommonRoute, CommonRouteModel } from '@owlmeans/route';
|
|
2
|
+
export interface ClientRoute extends CommonRoute {
|
|
3
|
+
partialPath: string;
|
|
4
|
+
}
|
|
5
|
+
export interface ClientRouteModel extends CommonRouteModel {
|
|
6
|
+
route: ClientRoute;
|
|
7
|
+
_resolved?: Promise<void>;
|
|
8
|
+
_client: true;
|
|
9
|
+
}
|
|
10
|
+
export interface ClientRouteOptions {
|
|
11
|
+
overrides?: Partial<ClientRoute>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAEpE,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC9C,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,gBAAiB,SAAQ,gBAAgB;IACxD,KAAK,EAAE,WAAW,CAAA;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;IACzB,OAAO,EAAE,IAAI,CAAA;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;CACjC"}
|
package/build/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@owlmeans/client-route",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "tsc -b",
|
|
7
|
+
"dev": "sleep 126 && nodemon -e ts,tsx,json --watch src --exec \"tsc -p ./tsconfig.json\"",
|
|
8
|
+
"watch": "tsc -b -w --preserveWatchOutput --pretty"
|
|
9
|
+
},
|
|
10
|
+
"main": "build/index.js",
|
|
11
|
+
"module": "build/index.js",
|
|
12
|
+
"types": "build/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"import": "./build/index.js",
|
|
16
|
+
"require": "./build/index.js",
|
|
17
|
+
"default": "./build/index.js",
|
|
18
|
+
"module": "./build/index.js",
|
|
19
|
+
"types": "./build/index.d.ts"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@owlmeans/client-context": "^0.1.0",
|
|
24
|
+
"@owlmeans/route": "^0.1.0"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"nodemon": "^3.1.7",
|
|
28
|
+
"typescript": "^5.6.3"
|
|
29
|
+
},
|
|
30
|
+
"private": false,
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
}
|
|
34
|
+
}
|
package/src/helper.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { PARAM, SEP, normalizePath } from '@owlmeans/route'
|
|
2
|
+
import { ClientRouteModel } from './types.js'
|
|
3
|
+
|
|
4
|
+
export const isClientRouteModel = (route: Object): route is ClientRouteModel =>
|
|
5
|
+
'_client' in route
|
|
6
|
+
|
|
7
|
+
export const extractParams = (path: string): string[] => {
|
|
8
|
+
path = normalizePath(path)
|
|
9
|
+
return path.split(SEP).map(item => item.startsWith(PARAM) ? item.slice(1) : null)
|
|
10
|
+
.filter(param => param) as string[]
|
|
11
|
+
}
|
package/src/index.ts
ADDED
package/src/model.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { CommonRouteModel } from '@owlmeans/route'
|
|
2
|
+
import type { ClientRouteModel, ClientRouteOptions } from './types.js'
|
|
3
|
+
import { resolve, overrideParams } from '@owlmeans/route/utils'
|
|
4
|
+
import type { BasicConfig, BasicContext } from '../../context/build/types.js'
|
|
5
|
+
|
|
6
|
+
export const route = (route: CommonRouteModel, opts?: ClientRouteOptions): ClientRouteModel => {
|
|
7
|
+
const unresolvedPath = route.route.path
|
|
8
|
+
|
|
9
|
+
const model: ClientRouteModel = {
|
|
10
|
+
...(route as ClientRouteModel),
|
|
11
|
+
|
|
12
|
+
_client: true,
|
|
13
|
+
|
|
14
|
+
resolve: async <C>(context: C) => {
|
|
15
|
+
if (model.route.resolved) {
|
|
16
|
+
if (model._resolved == null) {
|
|
17
|
+
throw new SyntaxError('Cannot reach resolved state twice without resolving promise')
|
|
18
|
+
}
|
|
19
|
+
await model._resolved
|
|
20
|
+
|
|
21
|
+
return model.route
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const resolver: { resolve?: () => void } = {}
|
|
25
|
+
model._resolved = new Promise(resolve => resolver.resolve = resolve)
|
|
26
|
+
|
|
27
|
+
await resolve(model.route)(context as BasicContext<BasicConfig>)
|
|
28
|
+
|
|
29
|
+
model.route.partialPath = unresolvedPath
|
|
30
|
+
|
|
31
|
+
resolver.resolve?.()
|
|
32
|
+
|
|
33
|
+
return model.route
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
overrideParams(model.route, opts?.overrides)
|
|
38
|
+
|
|
39
|
+
model.route.partialPath = unresolvedPath
|
|
40
|
+
|
|
41
|
+
return model
|
|
42
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { CommonRoute, CommonRouteModel } from '@owlmeans/route'
|
|
2
|
+
|
|
3
|
+
export interface ClientRoute extends CommonRoute {
|
|
4
|
+
partialPath: string
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface ClientRouteModel extends CommonRouteModel {
|
|
8
|
+
route: ClientRoute
|
|
9
|
+
_resolved?: Promise<void>
|
|
10
|
+
_client: true
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface ClientRouteOptions {
|
|
14
|
+
overrides?: Partial<ClientRoute>
|
|
15
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": [
|
|
3
|
+
"../tsconfig.default.json",
|
|
4
|
+
],
|
|
5
|
+
"compilerOptions": {
|
|
6
|
+
"rootDir": "./src/", /* Specify the root folder within your source files. */
|
|
7
|
+
"outDir": "./build/", /* Specify an output folder for all emitted files. */
|
|
8
|
+
"moduleResolution": "Bundler"
|
|
9
|
+
},
|
|
10
|
+
"exclude": [
|
|
11
|
+
"./dist/**/*",
|
|
12
|
+
"./build/**/*",
|
|
13
|
+
"./*.ts"
|
|
14
|
+
]
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"root":["./src/helper.ts","./src/index.ts","./src/model.ts","./src/types.ts"],"version":"5.6.3"}
|