@owlmeans/client-route 0.1.1 → 0.1.3

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 OwlMeans Common — Fullstack typescript framework
3
+ Copyright (c) 2026 OwlMeans Common — Fullstack typescript framework
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,368 +1,58 @@
1
1
  # @owlmeans/client-route
2
2
 
3
- Client-side routing library for OwlMeans applications that extends the base `@owlmeans/route` package with client-specific functionality.
3
+ Client-side route model extension marks routes as client-side and provides URL parameter utilities.
4
4
 
5
5
  ## Overview
6
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
7
+ - `route(routeModel, opts?)` wraps a `CommonRouteModel` into a `ClientRouteModel` (marks `_client: true`)
8
+ - `isClientRouteModel(route)` — type guard distinguishing client routes from server routes
9
+ - `extractParams(path)` extracts path parameter names (`:param` segments) from a URL pattern
10
+ - Used internally by `@owlmeans/client-module` when building client-side module URLs
18
11
 
19
12
  ## Installation
20
13
 
21
14
  ```bash
22
- npm install @owlmeans/client-route
15
+ bun add @owlmeans/client-route
23
16
  ```
24
17
 
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.
18
+ ## Usage
44
19
 
45
20
  ```typescript
46
- interface ClientRoute extends CommonRoute {
47
- partialPath: string // Original path pattern preserved for client use
48
- }
49
- ```
21
+ import { route, isClientRouteModel, extractParams } from '@owlmeans/client-route'
22
+ import type { ClientRouteModel } from '@owlmeans/client-route'
50
23
 
51
- **Properties:**
52
- - **partialPath**: `string` - The original path pattern before resolution, useful for client-side routing logic
24
+ // Wrap a route as a client route
25
+ const clientRoute = route(someRouteModel, { overrides: { partialPath: '/items' } })
53
26
 
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
27
+ // Type guard
28
+ if (isClientRouteModel(arg)) {
29
+ // arg is ClientRouteModel
62
30
  }
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
31
 
70
- #### ClientRouteOptions
71
- Options for configuring client routes.
72
-
73
- ```typescript
74
- interface ClientRouteOptions {
75
- overrides?: Partial<ClientRoute> // Route parameter overrides
76
- }
32
+ // Extract named params from a path pattern
33
+ const params = extractParams('/projects/:projectId/items/:itemId')
34
+ // => ['projectId', 'itemId']
77
35
  ```
78
36
 
79
- **Properties:**
80
- - **overrides**: `Partial<ClientRoute>` - Optional route parameter overrides
81
-
82
- ### Core Functions
37
+ ## API
83
38
 
84
- #### route(route, opts?)
85
- Wraps a base route model with client-specific functionality.
39
+ ### `route(route, opts?): ClientRouteModel`
86
40
 
87
- ```typescript
88
- const route: (route: CommonRouteModel, opts?: ClientRouteOptions) => ClientRouteModel
89
- ```
41
+ Converts a `CommonRouteModel` to a `ClientRouteModel`. Options: `overrides?: Partial<ClientRoute>`.
90
42
 
91
- **Parameters:**
92
- - `route: CommonRouteModel` - Base route model from `@owlmeans/route`
93
- - `opts?: ClientRouteOptions` - Optional configuration options
43
+ ### `isClientRouteModel(route): route is ClientRouteModel`
94
44
 
95
- **Returns:** `ClientRouteModel` - Client route model with enhanced functionality
45
+ Returns `true` if the route was created with `route()`.
96
46
 
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'
47
+ ### `extractParams(path): string[]`
107
48
 
108
- // Create a base route
109
- const userRoute = baseRoute('user', '/users/:id')
49
+ Returns the list of `:param` segment names in a URL pattern string.
110
50
 
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'
51
+ ### `ClientRouteModel`
197
52
 
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')
53
+ Extends `CommonRouteModel` with `_client: true` flag and `partialPath` for relative URL segments.
360
54
 
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'))
55
+ ## Related Packages
365
56
 
366
- // Additional client functionality is now available
367
- console.log(userRoute.route.partialPath) // '/users/:id'
368
- ```
57
+ - [`@owlmeans/route`](../route) `CommonRouteModel`, `CommonRoute` base types
58
+ - [`@owlmeans/client-module`](../client-module) — uses `route()` and `isClientRouteModel()` when constructing modules
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@owlmeans/client-route",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
+ "license": "MIT",
4
5
  "type": "module",
5
6
  "scripts": {
6
7
  "build": "tsc -b",
@@ -20,12 +21,13 @@
20
21
  }
21
22
  },
22
23
  "dependencies": {
23
- "@owlmeans/client-context": "^0.1.1",
24
- "@owlmeans/route": "^0.1.1"
24
+ "@owlmeans/client-context": "^0.1.3",
25
+ "@owlmeans/route": "^0.1.3"
25
26
  },
26
27
  "devDependencies": {
28
+ "@owlmeans/dep-config": "workspace:*",
27
29
  "nodemon": "^3.1.11",
28
- "typescript": "^5.8.3"
30
+ "typescript": "^6.0.2"
29
31
  },
30
32
  "publishConfig": {
31
33
  "access": "public"
package/tsconfig.json CHANGED
@@ -1,15 +1,10 @@
1
1
  {
2
2
  "extends": [
3
- "../tsconfig.default.json",
3
+ "@owlmeans/dep-config/tsconfig.base.json"
4
4
  ],
5
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"
6
+ "rootDir": "./src/",
7
+ "outDir": "./build/"
9
8
  },
10
- "exclude": [
11
- "./dist/**/*",
12
- "./build/**/*",
13
- "./*.ts"
14
- ]
15
- }
9
+ "exclude": ["./dist/**/*", "./build/**/*", "./*.ts"]
10
+ }