@skmtc/core 0.0.793 → 0.0.795
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/esm/context/StackTrail.d.ts +293 -0
- package/esm/context/StackTrail.d.ts.map +1 -1
- package/esm/context/StackTrail.js +294 -0
- package/esm/helpers/ResultsLog.d.ts +193 -0
- package/esm/helpers/ResultsLog.d.ts.map +1 -1
- package/esm/helpers/ResultsLog.js +213 -0
- package/esm/helpers/tracer.d.ts +124 -0
- package/esm/helpers/tracer.d.ts.map +1 -1
- package/esm/helpers/tracer.js +124 -0
- package/esm/types/Modifiers.d.ts +68 -0
- package/esm/types/Modifiers.d.ts.map +1 -1
- package/esm/types/TypeSystem.d.ts +419 -0
- package/esm/types/TypeSystem.d.ts.map +1 -1
- package/esm/typescript/FunctionParameter.d.ts +313 -0
- package/esm/typescript/FunctionParameter.d.ts.map +1 -1
- package/esm/typescript/FunctionParameter.js +328 -0
- package/esm/typescript/PathParams.d.ts +198 -0
- package/esm/typescript/PathParams.d.ts.map +1 -1
- package/esm/typescript/PathParams.js +190 -0
- package/esm/typescript/ReactRouterPathParams.d.ts +190 -0
- package/esm/typescript/ReactRouterPathParams.d.ts.map +1 -1
- package/esm/typescript/ReactRouterPathParams.js +183 -0
- package/esm/typescript/keyValues.d.ts +125 -0
- package/esm/typescript/keyValues.d.ts.map +1 -1
- package/esm/typescript/keyValues.js +125 -1
- package/esm/typescript/toPathParams.d.ts +179 -0
- package/esm/typescript/toPathParams.d.ts.map +1 -1
- package/esm/typescript/toPathParams.js +179 -0
- package/esm/typescript/toPathTemplate.d.ts +114 -0
- package/esm/typescript/toPathTemplate.d.ts.map +1 -1
- package/esm/typescript/toPathTemplate.js +114 -0
- package/package.json +1 -1
- package/script/context/StackTrail.d.ts +293 -0
- package/script/context/StackTrail.d.ts.map +1 -1
- package/script/context/StackTrail.js +294 -0
- package/script/helpers/ResultsLog.d.ts +193 -0
- package/script/helpers/ResultsLog.d.ts.map +1 -1
- package/script/helpers/ResultsLog.js +213 -0
- package/script/helpers/tracer.d.ts +124 -0
- package/script/helpers/tracer.d.ts.map +1 -1
- package/script/helpers/tracer.js +124 -0
- package/script/types/Modifiers.d.ts +68 -0
- package/script/types/Modifiers.d.ts.map +1 -1
- package/script/types/TypeSystem.d.ts +419 -0
- package/script/types/TypeSystem.d.ts.map +1 -1
- package/script/typescript/FunctionParameter.d.ts +313 -0
- package/script/typescript/FunctionParameter.d.ts.map +1 -1
- package/script/typescript/FunctionParameter.js +328 -0
- package/script/typescript/PathParams.d.ts +198 -0
- package/script/typescript/PathParams.d.ts.map +1 -1
- package/script/typescript/PathParams.js +190 -0
- package/script/typescript/ReactRouterPathParams.d.ts +190 -0
- package/script/typescript/ReactRouterPathParams.d.ts.map +1 -1
- package/script/typescript/ReactRouterPathParams.js +183 -0
- package/script/typescript/keyValues.d.ts +125 -0
- package/script/typescript/keyValues.d.ts.map +1 -1
- package/script/typescript/keyValues.js +125 -1
- package/script/typescript/toPathParams.d.ts +179 -0
- package/script/typescript/toPathParams.d.ts.map +1 -1
- package/script/typescript/toPathParams.js +179 -0
- package/script/typescript/toPathTemplate.d.ts +114 -0
- package/script/typescript/toPathTemplate.d.ts.map +1 -1
- package/script/typescript/toPathTemplate.js +114 -0
|
@@ -1,3 +1,128 @@
|
|
|
1
1
|
import type { Stringable } from '../dsl/Stringable.js';
|
|
2
|
+
/**
|
|
3
|
+
* Converts a properties object into a formatted TypeScript object literal string.
|
|
4
|
+
*
|
|
5
|
+
* This utility function takes a record of key-value pairs and generates a properly
|
|
6
|
+
* formatted TypeScript object literal. It automatically filters out empty values
|
|
7
|
+
* and handles proper spacing and comma placement. If all properties are empty,
|
|
8
|
+
* it returns the EMPTY constant instead of an empty object.
|
|
9
|
+
*
|
|
10
|
+
* The function is particularly useful for generating TypeScript interface properties,
|
|
11
|
+
* object type definitions, and literal object expressions in code generation scenarios.
|
|
12
|
+
*
|
|
13
|
+
* @param properties - Record of property names to their stringable values
|
|
14
|
+
* @returns Formatted object literal string or EMPTY if no valid properties
|
|
15
|
+
*
|
|
16
|
+
* @example Basic object generation
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { keyValues } from '@skmtc/core';
|
|
19
|
+
*
|
|
20
|
+
* const props = {
|
|
21
|
+
* name: { toString: () => 'string' },
|
|
22
|
+
* age: { toString: () => 'number' },
|
|
23
|
+
* email: { toString: () => 'string' }
|
|
24
|
+
* };
|
|
25
|
+
*
|
|
26
|
+
* const result = keyValues(props);
|
|
27
|
+
* console.log(result);
|
|
28
|
+
* // {name: string,
|
|
29
|
+
* // age: number,
|
|
30
|
+
* // email: string}
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @example With empty values filtered
|
|
34
|
+
* ```typescript
|
|
35
|
+
* const propsWithEmpty = {
|
|
36
|
+
* name: { toString: () => 'string' },
|
|
37
|
+
* description: { toString: () => '' }, // Empty, will be filtered
|
|
38
|
+
* age: { toString: () => 'number' },
|
|
39
|
+
* notes: { toString: () => 'EMPTY' } // EMPTY constant, will be filtered
|
|
40
|
+
* };
|
|
41
|
+
*
|
|
42
|
+
* const result = keyValues(propsWithEmpty);
|
|
43
|
+
* console.log(result);
|
|
44
|
+
* // {name: string,
|
|
45
|
+
* // age: number}
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @example All empty properties
|
|
49
|
+
* ```typescript
|
|
50
|
+
* const emptyProps = {
|
|
51
|
+
* description: { toString: () => '' },
|
|
52
|
+
* notes: { toString: () => 'EMPTY' }
|
|
53
|
+
* };
|
|
54
|
+
*
|
|
55
|
+
* const result = keyValues(emptyProps);
|
|
56
|
+
* console.log(result === EMPTY); // true
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* @example TypeScript interface generation
|
|
60
|
+
* ```typescript
|
|
61
|
+
* class InterfaceGenerator {
|
|
62
|
+
* generateInterface(name: string, properties: Record<string, Stringable>) {
|
|
63
|
+
* const propsString = keyValues(properties);
|
|
64
|
+
*
|
|
65
|
+
* if (propsString === EMPTY) {
|
|
66
|
+
* return `interface ${name} {}`;
|
|
67
|
+
* }
|
|
68
|
+
*
|
|
69
|
+
* return `interface ${name} ${propsString}`;
|
|
70
|
+
* }
|
|
71
|
+
* }
|
|
72
|
+
*
|
|
73
|
+
* const generator = new InterfaceGenerator();
|
|
74
|
+
* const userInterface = generator.generateInterface('User', {
|
|
75
|
+
* id: { toString: () => 'string' },
|
|
76
|
+
* name: { toString: () => 'string' },
|
|
77
|
+
* age: { toString: () => 'number' }
|
|
78
|
+
* });
|
|
79
|
+
*
|
|
80
|
+
* console.log(userInterface);
|
|
81
|
+
* // interface User {id: string,
|
|
82
|
+
* // name: string,
|
|
83
|
+
* // age: number}
|
|
84
|
+
* ```
|
|
85
|
+
*
|
|
86
|
+
* @example Object literal generation
|
|
87
|
+
* ```typescript
|
|
88
|
+
* function generateObjectLiteral(values: Record<string, string>) {
|
|
89
|
+
* const stringableValues = Object.fromEntries(
|
|
90
|
+
* Object.entries(values).map(([k, v]) => [k, { toString: () => `'${v}'` }])
|
|
91
|
+
* );
|
|
92
|
+
*
|
|
93
|
+
* const result = keyValues(stringableValues);
|
|
94
|
+
* return result === EMPTY ? '{}' : result;
|
|
95
|
+
* }
|
|
96
|
+
*
|
|
97
|
+
* const config = generateObjectLiteral({
|
|
98
|
+
* apiUrl: 'https://api.example.com',
|
|
99
|
+
* timeout: '5000'
|
|
100
|
+
* });
|
|
101
|
+
*
|
|
102
|
+
* console.log(config);
|
|
103
|
+
* // {apiUrl: 'https://api.example.com',
|
|
104
|
+
* // timeout: '5000'}
|
|
105
|
+
* ```
|
|
106
|
+
*
|
|
107
|
+
* @example Conditional property inclusion
|
|
108
|
+
* ```typescript
|
|
109
|
+
* class ConditionalGenerator {
|
|
110
|
+
* generateObjectType(fields: Array<{name: string, type: string, optional?: boolean}>) {
|
|
111
|
+
* const properties: Record<string, Stringable> = {};
|
|
112
|
+
*
|
|
113
|
+
* fields.forEach(field => {
|
|
114
|
+
* if (field.type) { // Only include fields with types
|
|
115
|
+
* const optionalMarker = field.optional ? '?' : '';
|
|
116
|
+
* properties[field.name] = {
|
|
117
|
+
* toString: () => `${optionalMarker}: ${field.type}`
|
|
118
|
+
* };
|
|
119
|
+
* }
|
|
120
|
+
* });
|
|
121
|
+
*
|
|
122
|
+
* return keyValues(properties);
|
|
123
|
+
* }
|
|
124
|
+
* }
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
2
127
|
export declare const keyValues: (properties: Record<string, Stringable>) => string;
|
|
3
128
|
//# sourceMappingURL=keyValues.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyValues.d.ts","sourceRoot":"","sources":["../../src/typescript/keyValues.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"keyValues.d.ts","sourceRoot":"","sources":["../../src/typescript/keyValues.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4HG;AACH,eAAO,MAAM,SAAS,GAAI,YAAY,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,KAAG,MAUlE,CAAA"}
|
|
@@ -1,5 +1,129 @@
|
|
|
1
1
|
import { EMPTY } from '../dsl/constants.js';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Converts a properties object into a formatted TypeScript object literal string.
|
|
4
|
+
*
|
|
5
|
+
* This utility function takes a record of key-value pairs and generates a properly
|
|
6
|
+
* formatted TypeScript object literal. It automatically filters out empty values
|
|
7
|
+
* and handles proper spacing and comma placement. If all properties are empty,
|
|
8
|
+
* it returns the EMPTY constant instead of an empty object.
|
|
9
|
+
*
|
|
10
|
+
* The function is particularly useful for generating TypeScript interface properties,
|
|
11
|
+
* object type definitions, and literal object expressions in code generation scenarios.
|
|
12
|
+
*
|
|
13
|
+
* @param properties - Record of property names to their stringable values
|
|
14
|
+
* @returns Formatted object literal string or EMPTY if no valid properties
|
|
15
|
+
*
|
|
16
|
+
* @example Basic object generation
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { keyValues } from '@skmtc/core';
|
|
19
|
+
*
|
|
20
|
+
* const props = {
|
|
21
|
+
* name: { toString: () => 'string' },
|
|
22
|
+
* age: { toString: () => 'number' },
|
|
23
|
+
* email: { toString: () => 'string' }
|
|
24
|
+
* };
|
|
25
|
+
*
|
|
26
|
+
* const result = keyValues(props);
|
|
27
|
+
* console.log(result);
|
|
28
|
+
* // {name: string,
|
|
29
|
+
* // age: number,
|
|
30
|
+
* // email: string}
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @example With empty values filtered
|
|
34
|
+
* ```typescript
|
|
35
|
+
* const propsWithEmpty = {
|
|
36
|
+
* name: { toString: () => 'string' },
|
|
37
|
+
* description: { toString: () => '' }, // Empty, will be filtered
|
|
38
|
+
* age: { toString: () => 'number' },
|
|
39
|
+
* notes: { toString: () => 'EMPTY' } // EMPTY constant, will be filtered
|
|
40
|
+
* };
|
|
41
|
+
*
|
|
42
|
+
* const result = keyValues(propsWithEmpty);
|
|
43
|
+
* console.log(result);
|
|
44
|
+
* // {name: string,
|
|
45
|
+
* // age: number}
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @example All empty properties
|
|
49
|
+
* ```typescript
|
|
50
|
+
* const emptyProps = {
|
|
51
|
+
* description: { toString: () => '' },
|
|
52
|
+
* notes: { toString: () => 'EMPTY' }
|
|
53
|
+
* };
|
|
54
|
+
*
|
|
55
|
+
* const result = keyValues(emptyProps);
|
|
56
|
+
* console.log(result === EMPTY); // true
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* @example TypeScript interface generation
|
|
60
|
+
* ```typescript
|
|
61
|
+
* class InterfaceGenerator {
|
|
62
|
+
* generateInterface(name: string, properties: Record<string, Stringable>) {
|
|
63
|
+
* const propsString = keyValues(properties);
|
|
64
|
+
*
|
|
65
|
+
* if (propsString === EMPTY) {
|
|
66
|
+
* return `interface ${name} {}`;
|
|
67
|
+
* }
|
|
68
|
+
*
|
|
69
|
+
* return `interface ${name} ${propsString}`;
|
|
70
|
+
* }
|
|
71
|
+
* }
|
|
72
|
+
*
|
|
73
|
+
* const generator = new InterfaceGenerator();
|
|
74
|
+
* const userInterface = generator.generateInterface('User', {
|
|
75
|
+
* id: { toString: () => 'string' },
|
|
76
|
+
* name: { toString: () => 'string' },
|
|
77
|
+
* age: { toString: () => 'number' }
|
|
78
|
+
* });
|
|
79
|
+
*
|
|
80
|
+
* console.log(userInterface);
|
|
81
|
+
* // interface User {id: string,
|
|
82
|
+
* // name: string,
|
|
83
|
+
* // age: number}
|
|
84
|
+
* ```
|
|
85
|
+
*
|
|
86
|
+
* @example Object literal generation
|
|
87
|
+
* ```typescript
|
|
88
|
+
* function generateObjectLiteral(values: Record<string, string>) {
|
|
89
|
+
* const stringableValues = Object.fromEntries(
|
|
90
|
+
* Object.entries(values).map(([k, v]) => [k, { toString: () => `'${v}'` }])
|
|
91
|
+
* );
|
|
92
|
+
*
|
|
93
|
+
* const result = keyValues(stringableValues);
|
|
94
|
+
* return result === EMPTY ? '{}' : result;
|
|
95
|
+
* }
|
|
96
|
+
*
|
|
97
|
+
* const config = generateObjectLiteral({
|
|
98
|
+
* apiUrl: 'https://api.example.com',
|
|
99
|
+
* timeout: '5000'
|
|
100
|
+
* });
|
|
101
|
+
*
|
|
102
|
+
* console.log(config);
|
|
103
|
+
* // {apiUrl: 'https://api.example.com',
|
|
104
|
+
* // timeout: '5000'}
|
|
105
|
+
* ```
|
|
106
|
+
*
|
|
107
|
+
* @example Conditional property inclusion
|
|
108
|
+
* ```typescript
|
|
109
|
+
* class ConditionalGenerator {
|
|
110
|
+
* generateObjectType(fields: Array<{name: string, type: string, optional?: boolean}>) {
|
|
111
|
+
* const properties: Record<string, Stringable> = {};
|
|
112
|
+
*
|
|
113
|
+
* fields.forEach(field => {
|
|
114
|
+
* if (field.type) { // Only include fields with types
|
|
115
|
+
* const optionalMarker = field.optional ? '?' : '';
|
|
116
|
+
* properties[field.name] = {
|
|
117
|
+
* toString: () => `${optionalMarker}: ${field.type}`
|
|
118
|
+
* };
|
|
119
|
+
* }
|
|
120
|
+
* });
|
|
121
|
+
*
|
|
122
|
+
* return keyValues(properties);
|
|
123
|
+
* }
|
|
124
|
+
* }
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
3
127
|
export const keyValues = (properties) => {
|
|
4
128
|
const filteredEntries = Object.entries(properties)
|
|
5
129
|
.map(([key, value]) => {
|
|
@@ -1,2 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts OpenAPI path parameters to React Router path parameter syntax.
|
|
3
|
+
*
|
|
4
|
+
* This utility function transforms OpenAPI path syntax (using curly braces) into
|
|
5
|
+
* React Router path parameter syntax (using colon prefix). It's essential for
|
|
6
|
+
* generating React Router route definitions and other routing configurations
|
|
7
|
+
* that need to match URL parameters.
|
|
8
|
+
*
|
|
9
|
+
* The function performs a simple but crucial transformation that enables
|
|
10
|
+
* OpenAPI-defined paths to be used directly in React Router route definitions,
|
|
11
|
+
* maintaining the same parameter names while adapting the syntax.
|
|
12
|
+
*
|
|
13
|
+
* @param path - OpenAPI path string with {parameter} syntax
|
|
14
|
+
* @returns React Router path string with :parameter syntax
|
|
15
|
+
*
|
|
16
|
+
* @example Basic path parameter conversion
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { toPathParams } from '@skmtc/core';
|
|
19
|
+
*
|
|
20
|
+
* const routePath = toPathParams('/users/{id}/posts/{postId}');
|
|
21
|
+
* console.log(routePath); // '/users/:id/posts/:postId'
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @example React Router route generation
|
|
25
|
+
* ```typescript
|
|
26
|
+
* import { Routes, Route } from 'react-router-dom';
|
|
27
|
+
*
|
|
28
|
+
* const apiPaths = [
|
|
29
|
+
* '/users/{id}',
|
|
30
|
+
* '/users/{id}/posts/{postId}',
|
|
31
|
+
* '/organizations/{orgId}/members/{userId}'
|
|
32
|
+
* ];
|
|
33
|
+
*
|
|
34
|
+
* const routePaths = apiPaths.map(toPathParams);
|
|
35
|
+
* // [
|
|
36
|
+
* // '/users/:id',
|
|
37
|
+
* // '/users/:id/posts/:postId',
|
|
38
|
+
* // '/organizations/:orgId/members/:userId'
|
|
39
|
+
* // ]
|
|
40
|
+
*
|
|
41
|
+
* function App() {
|
|
42
|
+
* return (
|
|
43
|
+
* <Routes>
|
|
44
|
+
* {routePaths.map(path => (
|
|
45
|
+
* <Route key={path} path={path} element={<DetailView />} />
|
|
46
|
+
* ))}
|
|
47
|
+
* </Routes>
|
|
48
|
+
* );
|
|
49
|
+
* }
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* @example Express.js route generation
|
|
53
|
+
* ```typescript
|
|
54
|
+
* import express from 'express';
|
|
55
|
+
*
|
|
56
|
+
* class RouteGenerator {
|
|
57
|
+
* generateExpressRoutes(openApiPaths: string[]) {
|
|
58
|
+
* const router = express.Router();
|
|
59
|
+
*
|
|
60
|
+
* openApiPaths.forEach(path => {
|
|
61
|
+
* const expressPath = toPathParams(path);
|
|
62
|
+
*
|
|
63
|
+
* router.get(expressPath, (req, res) => {
|
|
64
|
+
* // Handler logic using req.params
|
|
65
|
+
* res.json({ path: expressPath, params: req.params });
|
|
66
|
+
* });
|
|
67
|
+
* });
|
|
68
|
+
*
|
|
69
|
+
* return router;
|
|
70
|
+
* }
|
|
71
|
+
* }
|
|
72
|
+
*
|
|
73
|
+
* const generator = new RouteGenerator();
|
|
74
|
+
* const router = generator.generateExpressRoutes([
|
|
75
|
+
* '/api/users/{userId}',
|
|
76
|
+
* '/api/users/{userId}/orders/{orderId}'
|
|
77
|
+
* ]);
|
|
78
|
+
* // Generates routes for:
|
|
79
|
+
* // '/api/users/:userId'
|
|
80
|
+
* // '/api/users/:userId/orders/:orderId'
|
|
81
|
+
* ```
|
|
82
|
+
*
|
|
83
|
+
* @example Route configuration generation
|
|
84
|
+
* ```typescript
|
|
85
|
+
* interface RouteConfig {
|
|
86
|
+
* path: string;
|
|
87
|
+
* component: string;
|
|
88
|
+
* exact?: boolean;
|
|
89
|
+
* }
|
|
90
|
+
*
|
|
91
|
+
* function generateRouteConfigs(apiEndpoints: Array<{path: string, component: string}>): RouteConfig[] {
|
|
92
|
+
* return apiEndpoints.map(endpoint => ({
|
|
93
|
+
* path: toPathParams(endpoint.path),
|
|
94
|
+
* component: endpoint.component,
|
|
95
|
+
* exact: true
|
|
96
|
+
* }));
|
|
97
|
+
* }
|
|
98
|
+
*
|
|
99
|
+
* const routeConfigs = generateRouteConfigs([
|
|
100
|
+
* { path: '/users/{id}', component: 'UserDetail' },
|
|
101
|
+
* { path: '/users/{id}/settings', component: 'UserSettings' },
|
|
102
|
+
* { path: '/projects/{projectId}/tasks/{taskId}', component: 'TaskDetail' }
|
|
103
|
+
* ]);
|
|
104
|
+
*
|
|
105
|
+
* console.log(routeConfigs);
|
|
106
|
+
* // [
|
|
107
|
+
* // { path: '/users/:id', component: 'UserDetail', exact: true },
|
|
108
|
+
* // { path: '/users/:id/settings', component: 'UserSettings', exact: true },
|
|
109
|
+
* // { path: '/projects/:projectId/tasks/:taskId', component: 'TaskDetail', exact: true }
|
|
110
|
+
* // ]
|
|
111
|
+
* ```
|
|
112
|
+
*
|
|
113
|
+
* @example Next.js dynamic route generation
|
|
114
|
+
* ```typescript
|
|
115
|
+
* class NextJsRouteGenerator {
|
|
116
|
+
* generateFileStructure(openApiPaths: string[]) {
|
|
117
|
+
* return openApiPaths.map(path => {
|
|
118
|
+
* // Convert to Next.js file-based routing syntax
|
|
119
|
+
* const routerPath = toPathParams(path);
|
|
120
|
+
* const fileName = routerPath
|
|
121
|
+
* .replace(/:/g, '[') // :id becomes [id
|
|
122
|
+
* .replace(/\/\[([^\]]+)/g, '/[$1]') // [id becomes [id]
|
|
123
|
+
* .replace(/^\//,'') // Remove leading slash
|
|
124
|
+
* + '.tsx';
|
|
125
|
+
*
|
|
126
|
+
* return {
|
|
127
|
+
* originalPath: path,
|
|
128
|
+
* routerPath,
|
|
129
|
+
* fileName
|
|
130
|
+
* };
|
|
131
|
+
* });
|
|
132
|
+
* }
|
|
133
|
+
* }
|
|
134
|
+
*
|
|
135
|
+
* const generator = new NextJsRouteGenerator();
|
|
136
|
+
* const structure = generator.generateFileStructure([
|
|
137
|
+
* '/users/{id}',
|
|
138
|
+
* '/posts/{slug}/comments/{commentId}'
|
|
139
|
+
* ]);
|
|
140
|
+
*
|
|
141
|
+
* console.log(structure);
|
|
142
|
+
* // [
|
|
143
|
+
* // {
|
|
144
|
+
* // originalPath: '/users/{id}',
|
|
145
|
+
* // routerPath: '/users/:id',
|
|
146
|
+
* // fileName: 'users/[id].tsx'
|
|
147
|
+
* // },
|
|
148
|
+
* // {
|
|
149
|
+
* // originalPath: '/posts/{slug}/comments/{commentId}',
|
|
150
|
+
* // routerPath: '/posts/:slug/comments/:commentId',
|
|
151
|
+
* // fileName: 'posts/[slug]/comments/[commentId].tsx'
|
|
152
|
+
* // }
|
|
153
|
+
* // ]
|
|
154
|
+
* ```
|
|
155
|
+
*
|
|
156
|
+
* @example Integration with path matching
|
|
157
|
+
* ```typescript
|
|
158
|
+
* import { matchPath } from 'react-router-dom';
|
|
159
|
+
*
|
|
160
|
+
* class PathMatcher {
|
|
161
|
+
* createMatcher(openApiPath: string) {
|
|
162
|
+
* const routerPath = toPathParams(openApiPath);
|
|
163
|
+
*
|
|
164
|
+
* return (pathname: string) => {
|
|
165
|
+
* return matchPath(
|
|
166
|
+
* { path: routerPath, exact: true },
|
|
167
|
+
* pathname
|
|
168
|
+
* );
|
|
169
|
+
* };
|
|
170
|
+
* }
|
|
171
|
+
* }
|
|
172
|
+
*
|
|
173
|
+
* const matcher = new PathMatcher();
|
|
174
|
+
* const userMatcher = matcher.createMatcher('/users/{id}');
|
|
175
|
+
*
|
|
176
|
+
* const match = userMatcher('/users/123');
|
|
177
|
+
* console.log(match?.params); // { id: '123' }
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
1
180
|
export declare const toPathParams: (path: string) => string;
|
|
2
181
|
//# sourceMappingURL=toPathParams.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toPathParams.d.ts","sourceRoot":"","sources":["../../src/typescript/toPathParams.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,KAAG,MAE3C,CAAA"}
|
|
1
|
+
{"version":3,"file":"toPathParams.d.ts","sourceRoot":"","sources":["../../src/typescript/toPathParams.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkLG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,KAAG,MAE3C,CAAA"}
|
|
@@ -1,3 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts OpenAPI path parameters to React Router path parameter syntax.
|
|
3
|
+
*
|
|
4
|
+
* This utility function transforms OpenAPI path syntax (using curly braces) into
|
|
5
|
+
* React Router path parameter syntax (using colon prefix). It's essential for
|
|
6
|
+
* generating React Router route definitions and other routing configurations
|
|
7
|
+
* that need to match URL parameters.
|
|
8
|
+
*
|
|
9
|
+
* The function performs a simple but crucial transformation that enables
|
|
10
|
+
* OpenAPI-defined paths to be used directly in React Router route definitions,
|
|
11
|
+
* maintaining the same parameter names while adapting the syntax.
|
|
12
|
+
*
|
|
13
|
+
* @param path - OpenAPI path string with {parameter} syntax
|
|
14
|
+
* @returns React Router path string with :parameter syntax
|
|
15
|
+
*
|
|
16
|
+
* @example Basic path parameter conversion
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { toPathParams } from '@skmtc/core';
|
|
19
|
+
*
|
|
20
|
+
* const routePath = toPathParams('/users/{id}/posts/{postId}');
|
|
21
|
+
* console.log(routePath); // '/users/:id/posts/:postId'
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @example React Router route generation
|
|
25
|
+
* ```typescript
|
|
26
|
+
* import { Routes, Route } from 'react-router-dom';
|
|
27
|
+
*
|
|
28
|
+
* const apiPaths = [
|
|
29
|
+
* '/users/{id}',
|
|
30
|
+
* '/users/{id}/posts/{postId}',
|
|
31
|
+
* '/organizations/{orgId}/members/{userId}'
|
|
32
|
+
* ];
|
|
33
|
+
*
|
|
34
|
+
* const routePaths = apiPaths.map(toPathParams);
|
|
35
|
+
* // [
|
|
36
|
+
* // '/users/:id',
|
|
37
|
+
* // '/users/:id/posts/:postId',
|
|
38
|
+
* // '/organizations/:orgId/members/:userId'
|
|
39
|
+
* // ]
|
|
40
|
+
*
|
|
41
|
+
* function App() {
|
|
42
|
+
* return (
|
|
43
|
+
* <Routes>
|
|
44
|
+
* {routePaths.map(path => (
|
|
45
|
+
* <Route key={path} path={path} element={<DetailView />} />
|
|
46
|
+
* ))}
|
|
47
|
+
* </Routes>
|
|
48
|
+
* );
|
|
49
|
+
* }
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* @example Express.js route generation
|
|
53
|
+
* ```typescript
|
|
54
|
+
* import express from 'express';
|
|
55
|
+
*
|
|
56
|
+
* class RouteGenerator {
|
|
57
|
+
* generateExpressRoutes(openApiPaths: string[]) {
|
|
58
|
+
* const router = express.Router();
|
|
59
|
+
*
|
|
60
|
+
* openApiPaths.forEach(path => {
|
|
61
|
+
* const expressPath = toPathParams(path);
|
|
62
|
+
*
|
|
63
|
+
* router.get(expressPath, (req, res) => {
|
|
64
|
+
* // Handler logic using req.params
|
|
65
|
+
* res.json({ path: expressPath, params: req.params });
|
|
66
|
+
* });
|
|
67
|
+
* });
|
|
68
|
+
*
|
|
69
|
+
* return router;
|
|
70
|
+
* }
|
|
71
|
+
* }
|
|
72
|
+
*
|
|
73
|
+
* const generator = new RouteGenerator();
|
|
74
|
+
* const router = generator.generateExpressRoutes([
|
|
75
|
+
* '/api/users/{userId}',
|
|
76
|
+
* '/api/users/{userId}/orders/{orderId}'
|
|
77
|
+
* ]);
|
|
78
|
+
* // Generates routes for:
|
|
79
|
+
* // '/api/users/:userId'
|
|
80
|
+
* // '/api/users/:userId/orders/:orderId'
|
|
81
|
+
* ```
|
|
82
|
+
*
|
|
83
|
+
* @example Route configuration generation
|
|
84
|
+
* ```typescript
|
|
85
|
+
* interface RouteConfig {
|
|
86
|
+
* path: string;
|
|
87
|
+
* component: string;
|
|
88
|
+
* exact?: boolean;
|
|
89
|
+
* }
|
|
90
|
+
*
|
|
91
|
+
* function generateRouteConfigs(apiEndpoints: Array<{path: string, component: string}>): RouteConfig[] {
|
|
92
|
+
* return apiEndpoints.map(endpoint => ({
|
|
93
|
+
* path: toPathParams(endpoint.path),
|
|
94
|
+
* component: endpoint.component,
|
|
95
|
+
* exact: true
|
|
96
|
+
* }));
|
|
97
|
+
* }
|
|
98
|
+
*
|
|
99
|
+
* const routeConfigs = generateRouteConfigs([
|
|
100
|
+
* { path: '/users/{id}', component: 'UserDetail' },
|
|
101
|
+
* { path: '/users/{id}/settings', component: 'UserSettings' },
|
|
102
|
+
* { path: '/projects/{projectId}/tasks/{taskId}', component: 'TaskDetail' }
|
|
103
|
+
* ]);
|
|
104
|
+
*
|
|
105
|
+
* console.log(routeConfigs);
|
|
106
|
+
* // [
|
|
107
|
+
* // { path: '/users/:id', component: 'UserDetail', exact: true },
|
|
108
|
+
* // { path: '/users/:id/settings', component: 'UserSettings', exact: true },
|
|
109
|
+
* // { path: '/projects/:projectId/tasks/:taskId', component: 'TaskDetail', exact: true }
|
|
110
|
+
* // ]
|
|
111
|
+
* ```
|
|
112
|
+
*
|
|
113
|
+
* @example Next.js dynamic route generation
|
|
114
|
+
* ```typescript
|
|
115
|
+
* class NextJsRouteGenerator {
|
|
116
|
+
* generateFileStructure(openApiPaths: string[]) {
|
|
117
|
+
* return openApiPaths.map(path => {
|
|
118
|
+
* // Convert to Next.js file-based routing syntax
|
|
119
|
+
* const routerPath = toPathParams(path);
|
|
120
|
+
* const fileName = routerPath
|
|
121
|
+
* .replace(/:/g, '[') // :id becomes [id
|
|
122
|
+
* .replace(/\/\[([^\]]+)/g, '/[$1]') // [id becomes [id]
|
|
123
|
+
* .replace(/^\//,'') // Remove leading slash
|
|
124
|
+
* + '.tsx';
|
|
125
|
+
*
|
|
126
|
+
* return {
|
|
127
|
+
* originalPath: path,
|
|
128
|
+
* routerPath,
|
|
129
|
+
* fileName
|
|
130
|
+
* };
|
|
131
|
+
* });
|
|
132
|
+
* }
|
|
133
|
+
* }
|
|
134
|
+
*
|
|
135
|
+
* const generator = new NextJsRouteGenerator();
|
|
136
|
+
* const structure = generator.generateFileStructure([
|
|
137
|
+
* '/users/{id}',
|
|
138
|
+
* '/posts/{slug}/comments/{commentId}'
|
|
139
|
+
* ]);
|
|
140
|
+
*
|
|
141
|
+
* console.log(structure);
|
|
142
|
+
* // [
|
|
143
|
+
* // {
|
|
144
|
+
* // originalPath: '/users/{id}',
|
|
145
|
+
* // routerPath: '/users/:id',
|
|
146
|
+
* // fileName: 'users/[id].tsx'
|
|
147
|
+
* // },
|
|
148
|
+
* // {
|
|
149
|
+
* // originalPath: '/posts/{slug}/comments/{commentId}',
|
|
150
|
+
* // routerPath: '/posts/:slug/comments/:commentId',
|
|
151
|
+
* // fileName: 'posts/[slug]/comments/[commentId].tsx'
|
|
152
|
+
* // }
|
|
153
|
+
* // ]
|
|
154
|
+
* ```
|
|
155
|
+
*
|
|
156
|
+
* @example Integration with path matching
|
|
157
|
+
* ```typescript
|
|
158
|
+
* import { matchPath } from 'react-router-dom';
|
|
159
|
+
*
|
|
160
|
+
* class PathMatcher {
|
|
161
|
+
* createMatcher(openApiPath: string) {
|
|
162
|
+
* const routerPath = toPathParams(openApiPath);
|
|
163
|
+
*
|
|
164
|
+
* return (pathname: string) => {
|
|
165
|
+
* return matchPath(
|
|
166
|
+
* { path: routerPath, exact: true },
|
|
167
|
+
* pathname
|
|
168
|
+
* );
|
|
169
|
+
* };
|
|
170
|
+
* }
|
|
171
|
+
* }
|
|
172
|
+
*
|
|
173
|
+
* const matcher = new PathMatcher();
|
|
174
|
+
* const userMatcher = matcher.createMatcher('/users/{id}');
|
|
175
|
+
*
|
|
176
|
+
* const match = userMatcher('/users/123');
|
|
177
|
+
* console.log(match?.params); // { id: '123' }
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
1
180
|
export const toPathParams = (path) => {
|
|
2
181
|
return `${path.replaceAll(/{([^}]*)}/g, ':$1')}`;
|
|
3
182
|
};
|