11import { IHttpServer } from '@objectstack/core' ;
22import { RouteManager } from './route-manager' ;
3- import { RestServerConfig } from '@objectstack/spec/api' ;
3+ import { RestServerConfig , CrudOperation , RestApiConfig , CrudEndpointsConfig , MetadataEndpointsConfig , BatchEndpointsConfig , RouteGenerationConfig } from '@objectstack/spec/api' ;
4+ import { ObjectStackProtocol } from '@objectstack/spec/api' ;
5+
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+ } ;
463
564/**
665 * RestServer
@@ -32,7 +91,7 @@ import { RestServerConfig } from '@objectstack/spec/api';
3291export class RestServer {
3392 private server : IHttpServer ;
3493 private protocol : ObjectStackProtocol ;
35- private config : RestServerConfig ;
94+ private config : NormalizedRestServerConfig ;
3695 private routeManager : RouteManager ;
3796
3897 constructor (
@@ -49,48 +108,64 @@ export class RestServer {
49108 /**
50109 * Normalize configuration with defaults
51110 */
52- private normalizeConfig ( config : RestServerConfig ) : Required < RestServerConfig > {
53- const api = config . api ;
54- const crud = config . crud ;
55- const metadata = config . metadata ;
56- const batch = config . batch ;
57- 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 > ;
58117
59118 return {
60119 api : {
61- version : api ? .version ?? 'v1' ,
62- basePath : api ? .basePath ?? '/api' ,
63- apiPath : api ? .apiPath ,
64- enableCrud : api ? .enableCrud ?? true ,
65- enableMetadata : api ? .enableMetadata ?? true ,
66- enableBatch : api ? .enableBatch ?? true ,
67- enableDiscovery : api ? .enableDiscovery ?? true ,
68- documentation : api ? .documentation ,
69- 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 ,
70129 } ,
71130 crud : {
72- operations : crud ?. operations ,
73- patterns : crud ?. patterns ,
74- dataPrefix : crud ?. dataPrefix ?? '/data' ,
75- 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' ,
76141 } ,
77142 metadata : {
78- prefix : metadata ?. prefix ?? '/meta' ,
79- enableCache : metadata ?. enableCache ?? true ,
80- cacheTtl : metadata ?. cacheTtl ?? 3600 ,
81- 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+ } ,
82152 } ,
83153 batch : {
84- maxBatchSize : batch ?. maxBatchSize ?? 200 ,
85- enableBatchEndpoint : batch ?. enableBatchEndpoint ?? true ,
86- operations : batch ?. operations ,
87- 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 ,
88163 } ,
89164 routes : {
90- includeObjects : routes ? .includeObjects ,
91- excludeObjects : routes ? .excludeObjects ,
92- nameTransform : routes ? .nameTransform ?? 'none' ,
93- overrides : routes ? .overrides ,
165+ includeObjects : routes . includeObjects ,
166+ excludeObjects : routes . excludeObjects ,
167+ nameTransform : routes . nameTransform ?? 'none' ,
168+ overrides : routes . overrides ,
94169 } ,
95170 } ;
96171 }
@@ -160,7 +235,7 @@ export class RestServer {
160235 const metaPath = `${ basePath } ${ metadata . prefix } ` ;
161236
162237 // GET /meta - List all metadata types
163- if ( metadata . endpoints ? .types !== false ) {
238+ if ( metadata . endpoints . types !== false ) {
164239 this . routeManager . register ( {
165240 method : 'GET' ,
166241 path : metaPath ,
@@ -180,7 +255,7 @@ export class RestServer {
180255 }
181256
182257 // GET /meta/:type - List items of a type
183- if ( metadata . endpoints ? .items !== false ) {
258+ if ( metadata . endpoints . items !== false ) {
184259 this . routeManager . register ( {
185260 method : 'GET' ,
186261 path : `${ metaPath } /:type` ,
@@ -200,7 +275,7 @@ export class RestServer {
200275 }
201276
202277 // GET /meta/:type/:name - Get specific item
203- if ( metadata . endpoints ? .item !== false ) {
278+ if ( metadata . endpoints . item !== false ) {
204279 this . routeManager . register ( {
205280 method : 'GET' ,
206281 path : `${ metaPath } /:type/:name` ,
@@ -267,13 +342,7 @@ export class RestServer {
267342 const { crud } = this . config ;
268343 const dataPath = `${ basePath } ${ crud . dataPrefix } ` ;
269344
270- const operations = crud . operations ?? {
271- create : true ,
272- read : true ,
273- update : true ,
274- delete : true ,
275- list : true ,
276- } ;
345+ const operations = crud . operations ;
277346
278347 // GET /data/:object - List/query records
279348 if ( operations . list ) {
@@ -399,12 +468,7 @@ export class RestServer {
399468 const { crud, batch } = this . config ;
400469 const dataPath = `${ basePath } ${ crud . dataPrefix } ` ;
401470
402- const operations = batch . operations ?? {
403- createMany : true ,
404- updateMany : true ,
405- deleteMany : true ,
406- upsertMany : true ,
407- } ;
471+ const operations = batch . operations ;
408472
409473 // POST /data/:object/batch - Generic batch endpoint
410474 if ( batch . enableBatchEndpoint && this . protocol . batchData ) {
0 commit comments