11import { IHttpServer , RouteHandler } from '@objectstack/core' ;
22import { RouteManager } from './route-manager' ;
3- import { RestServerConfig , CrudOperation } from '@objectstack/spec/api' ;
3+ import { RestServerConfig , CrudOperation , RestApiConfig , CrudEndpointsConfig , MetadataEndpointsConfig , BatchEndpointsConfig , RouteGenerationConfig } from '@objectstack/spec/api' ;
44import { ObjectStackProtocol } from '@objectstack/spec/api' ;
55
6+ /**
7+ * Normalized REST Server Configuration
8+ * All nested properties are required after normalization
9+ */
10+ type NormalizedRestServerConfig = {
11+ api : {
12+ version : string ;
13+ basePath : string ;
14+ apiPath : string | undefined ;
15+ enableCrud : boolean ;
16+ enableMetadata : boolean ;
17+ enableBatch : boolean ;
18+ enableDiscovery : boolean ;
19+ documentation : RestApiConfig [ 'documentation' ] ;
20+ responseFormat : RestApiConfig [ 'responseFormat' ] ;
21+ } ;
22+ crud : {
23+ operations : {
24+ create : boolean ;
25+ read : boolean ;
26+ update : boolean ;
27+ delete : boolean ;
28+ list : boolean ;
29+ } ;
30+ patterns : CrudEndpointsConfig [ 'patterns' ] ;
31+ dataPrefix : string ;
32+ objectParamStyle : 'path' | 'query' ;
33+ } ;
34+ metadata : {
35+ prefix : string ;
36+ enableCache : boolean ;
37+ cacheTtl : number ;
38+ endpoints : {
39+ types : boolean ;
40+ items : boolean ;
41+ item : boolean ;
42+ schema : boolean ;
43+ } ;
44+ } ;
45+ batch : {
46+ maxBatchSize : number ;
47+ enableBatchEndpoint : boolean ;
48+ operations : {
49+ createMany : boolean ;
50+ updateMany : boolean ;
51+ deleteMany : boolean ;
52+ upsertMany : boolean ;
53+ } ;
54+ defaultAtomic : boolean ;
55+ } ;
56+ routes : {
57+ includeObjects : string [ ] | undefined ;
58+ excludeObjects : string [ ] | undefined ;
59+ nameTransform : 'none' | 'plural' | 'kebab-case' | 'camelCase' ;
60+ overrides : RouteGenerationConfig [ 'overrides' ] ;
61+ } ;
62+ } ;
63+
664/**
765 * RestServer
866 *
@@ -33,7 +91,7 @@ import { ObjectStackProtocol } from '@objectstack/spec/api';
3391export class RestServer {
3492 private server : IHttpServer ;
3593 private protocol : ObjectStackProtocol ;
36- private config : RestServerConfig ;
94+ private config : NormalizedRestServerConfig ;
3795 private routeManager : RouteManager ;
3896
3997 constructor (
@@ -50,48 +108,64 @@ export class RestServer {
50108 /**
51109 * Normalize configuration with defaults
52110 */
53- private normalizeConfig ( config : RestServerConfig ) : Required < RestServerConfig > {
54- const api = config . api ;
55- const crud = config . crud ;
56- const metadata = config . metadata ;
57- const batch = config . batch ;
58- const routes = config . routes ;
111+ private normalizeConfig ( config : RestServerConfig ) : NormalizedRestServerConfig {
112+ const api = config . api ?? { } as Partial < RestApiConfig > ;
113+ const crud = config . crud ?? { } as Partial < CrudEndpointsConfig > ;
114+ const metadata = config . metadata ?? { } as Partial < MetadataEndpointsConfig > ;
115+ const batch = config . batch ?? { } as Partial < BatchEndpointsConfig > ;
116+ const routes = config . routes ?? { } as Partial < RouteGenerationConfig > ;
59117
60118 return {
61119 api : {
62- version : api ? .version ?? 'v1' ,
63- basePath : api ? .basePath ?? '/api' ,
64- apiPath : api ? .apiPath ,
65- enableCrud : api ? .enableCrud ?? true ,
66- enableMetadata : api ? .enableMetadata ?? true ,
67- enableBatch : api ? .enableBatch ?? true ,
68- enableDiscovery : api ? .enableDiscovery ?? true ,
69- documentation : api ? .documentation ,
70- responseFormat : api ? .responseFormat ,
120+ version : api . version ?? 'v1' ,
121+ basePath : api . basePath ?? '/api' ,
122+ apiPath : api . apiPath ,
123+ enableCrud : api . enableCrud ?? true ,
124+ enableMetadata : api . enableMetadata ?? true ,
125+ enableBatch : api . enableBatch ?? true ,
126+ enableDiscovery : api . enableDiscovery ?? true ,
127+ documentation : api . documentation ,
128+ responseFormat : api . responseFormat ,
71129 } ,
72130 crud : {
73- operations : crud ?. operations ,
74- patterns : crud ?. patterns ,
75- dataPrefix : crud ?. dataPrefix ?? '/data' ,
76- objectParamStyle : crud ?. objectParamStyle ?? 'path' ,
131+ operations : crud . operations ?? {
132+ create : true ,
133+ read : true ,
134+ update : true ,
135+ delete : true ,
136+ list : true ,
137+ } ,
138+ patterns : crud . patterns ,
139+ dataPrefix : crud . dataPrefix ?? '/data' ,
140+ objectParamStyle : crud . objectParamStyle ?? 'path' ,
77141 } ,
78142 metadata : {
79- prefix : metadata ?. prefix ?? '/meta' ,
80- enableCache : metadata ?. enableCache ?? true ,
81- cacheTtl : metadata ?. cacheTtl ?? 3600 ,
82- endpoints : metadata ?. endpoints ,
143+ prefix : metadata . prefix ?? '/meta' ,
144+ enableCache : metadata . enableCache ?? true ,
145+ cacheTtl : metadata . cacheTtl ?? 3600 ,
146+ endpoints : metadata . endpoints ?? {
147+ types : true ,
148+ items : true ,
149+ item : true ,
150+ schema : true ,
151+ } ,
83152 } ,
84153 batch : {
85- maxBatchSize : batch ?. maxBatchSize ?? 200 ,
86- enableBatchEndpoint : batch ?. enableBatchEndpoint ?? true ,
87- operations : batch ?. operations ,
88- defaultAtomic : batch ?. defaultAtomic ?? true ,
154+ maxBatchSize : batch . maxBatchSize ?? 200 ,
155+ enableBatchEndpoint : batch . enableBatchEndpoint ?? true ,
156+ operations : batch . operations ?? {
157+ createMany : true ,
158+ updateMany : true ,
159+ deleteMany : true ,
160+ upsertMany : true ,
161+ } ,
162+ defaultAtomic : batch . defaultAtomic ?? true ,
89163 } ,
90164 routes : {
91- includeObjects : routes ? .includeObjects ,
92- excludeObjects : routes ? .excludeObjects ,
93- nameTransform : routes ? .nameTransform ?? 'none' ,
94- overrides : routes ? .overrides ,
165+ includeObjects : routes . includeObjects ,
166+ excludeObjects : routes . excludeObjects ,
167+ nameTransform : routes . nameTransform ?? 'none' ,
168+ overrides : routes . overrides ,
95169 } ,
96170 } ;
97171 }
@@ -161,7 +235,7 @@ export class RestServer {
161235 const metaPath = `${ basePath } ${ metadata . prefix } ` ;
162236
163237 // GET /meta - List all metadata types
164- if ( metadata . endpoints ? .types !== false ) {
238+ if ( metadata . endpoints . types !== false ) {
165239 this . routeManager . register ( {
166240 method : 'GET' ,
167241 path : metaPath ,
@@ -181,7 +255,7 @@ export class RestServer {
181255 }
182256
183257 // GET /meta/:type - List items of a type
184- if ( metadata . endpoints ? .items !== false ) {
258+ if ( metadata . endpoints . items !== false ) {
185259 this . routeManager . register ( {
186260 method : 'GET' ,
187261 path : `${ metaPath } /:type` ,
@@ -201,7 +275,7 @@ export class RestServer {
201275 }
202276
203277 // GET /meta/:type/:name - Get specific item
204- if ( metadata . endpoints ? .item !== false ) {
278+ if ( metadata . endpoints . item !== false ) {
205279 this . routeManager . register ( {
206280 method : 'GET' ,
207281 path : `${ metaPath } /:type/:name` ,
@@ -268,13 +342,7 @@ export class RestServer {
268342 const { crud } = this . config ;
269343 const dataPath = `${ basePath } ${ crud . dataPrefix } ` ;
270344
271- const operations = crud . operations ?? {
272- create : true ,
273- read : true ,
274- update : true ,
275- delete : true ,
276- list : true ,
277- } ;
345+ const operations = crud . operations ;
278346
279347 // GET /data/:object - List/query records
280348 if ( operations . list ) {
@@ -400,12 +468,7 @@ export class RestServer {
400468 const { crud, batch } = this . config ;
401469 const dataPath = `${ basePath } ${ crud . dataPrefix } ` ;
402470
403- const operations = batch . operations ?? {
404- createMany : true ,
405- updateMany : true ,
406- deleteMany : true ,
407- upsertMany : true ,
408- } ;
471+ const operations = batch . operations ;
409472
410473 // POST /data/:object/batch - Generic batch endpoint
411474 if ( batch . enableBatchEndpoint && this . protocol . batchData ) {
0 commit comments