@tahminator/sapling 2.0.5-beta.23c37926 → 2.0.5-beta.279125eb

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/dist/index.d.mts CHANGED
@@ -437,100 +437,14 @@ declare class ResponseStatusError extends Error {
437
437
  }
438
438
  //#endregion
439
439
  //#region src/helper/error/parse.d.ts
440
- type ParserErrorLocation = "reqbody" | "reqparams" | "reqquery";
440
+ type ParserErrorLocation = "reqbody" | "reqparams" | "reqquery" | "resbody";
441
441
  /**
442
- * This error should be thrown when some data cannot be parsed by a given schema.
442
+ * This error should be thrown when some data cannot be parsed by a given Standard Schema compatible schema.
443
443
  */
444
444
  declare class ParserError extends ResponseStatusError {
445
- constructor(location: ParserErrorLocation, issues: readonly StandardSchemaV1.Issue[], vendor: string);
445
+ constructor(location: ParserErrorLocation, issues: readonly StandardSchemaV1.Issue[], vendor: string, functionName: string);
446
446
  private static formatMessage;
447
- }
448
- //#endregion
449
- //#region src/helper/sapling.d.ts
450
- type Settings = {
451
- serialize: (value: any) => string;
452
- deserialize: (value: string) => any;
453
- doc: {
454
- openApiPath: string;
455
- swaggerPath: string;
456
- };
457
- };
458
- declare const _settings: Settings;
459
- /**
460
- * Collection of utility functions which are essential for Sapling to function.
461
- */
462
- declare class Sapling {
463
- /**
464
- * If you would prefer to manually resolve your controllers instead, call resolve
465
- * on the controller class.
466
- *
467
- * @example```ts
468
- * import { Sapling } from "@tahminator/sapling";
469
- * import TestController from "./path/to/test.controller";
470
- *
471
- * const app = express();
472
- *
473
- * const router = Sapling.resolve(TestController);
474
- * app.use(router);
475
- * ```
476
- */
477
- static resolve<TClass>(this: void, clazz: Class<TClass>): Router | ErrorRequestHandler;
478
- /**
479
- * Register this function as a middleware in order to utilize Sapling's `deserialize` function.
480
- *
481
- * @example```ts
482
- * import { Sapling } from "@tahminator/sapling";
483
- * import express from "express";
484
- *
485
- * const app = express();
486
- *
487
- * app.use(Sapling.json());
488
- * ```
489
- */
490
- static json(this: void): ExpressMiddlewareFn;
491
- /**
492
- * Register your application with all the necessary middlewares and logics for Sapling to function.
493
- *
494
- * @example```ts
495
- * import { Sapling } from "@tahminator/sapling";
496
- * import express from "express";
497
- *
498
- * const app = express();
499
- *
500
- * app.registerApp(app);
501
- * ```
502
- */
503
- static registerApp(app: e.Express): void;
504
- /**
505
- * Serialize a value into a JSON string.
506
- *
507
- * This function is used in {@link ResponseEntity} to serialize the `body`.
508
- *
509
- * Use `setSerializeFn` to override underlying implementation.
510
- *
511
- * @defaultValue `JSON.stringify`
512
- */
513
- static serialize(this: void, value: any): string;
514
- /**
515
- * Replace the function used for `serialize`.
516
- */
517
- static setSerializeFn(this: void, fn: (value: any) => string): void;
518
- /**
519
- * De-serialize a JSON string back to a JavaScript object.
520
- *
521
- * This function is used to de-serialize a string into a `body`.
522
- *
523
- * Use `setDeserializeFn` to override underlying implementation.
524
- *
525
- * @defaultValue `JSON.parse`
526
- */
527
- static deserialize<T = any>(this: void, value: string): T;
528
- /**
529
- * Replace the function used for `deserialize`
530
- */
531
- static setDeserializeFn(this: void, fn: (value: string) => any): void;
532
- static setOpenApiPath(this: void, path: string): void;
533
- static setSwaggerPath(this: void, path: string): void;
447
+ static getPrettyLocationString(location: ParserErrorLocation): "request body" | "request params" | "request query" | "response body";
534
448
  }
535
449
  //#endregion
536
450
  //#region node_modules/.pnpm/openapi-types@12.1.3/node_modules/openapi-types/dist/index.d.ts
@@ -854,115 +768,208 @@ declare namespace OpenAPIV3 {
854
768
  }
855
769
  //#endregion
856
770
  //#region src/helper/openapi.d.ts
857
- type OpenAPIConfig = {
771
+ type OpenAPIMetadata = {
858
772
  title: string;
859
773
  version: string;
860
774
  description?: string;
861
775
  };
862
776
  declare class OpenAPIGenerator {
863
777
  private controllers;
864
- private config;
865
- setConfig(config: OpenAPIConfig): void;
866
778
  registerController(controllerClass: Function, prefix: string): void;
779
+ private get metadata();
867
780
  generateSpec(): OpenAPIV3.Document;
868
781
  private toJsonSchema;
869
782
  }
870
783
  declare const openApiGenerator: OpenAPIGenerator;
871
- declare function _registerControllerClass(controllerClass: Function, prefix: string): void;
872
- declare function _setOpenApiConfig(config: OpenAPIConfig): void;
873
- declare function _generateOpenApiSpec(): OpenAPIV3.Document;
784
+ declare function _registerController(controllerClass: Function, prefix: string): void;
785
+ declare function generateOpenApiSpec(): OpenAPIV3.Document;
874
786
  //#endregion
875
- //#region src/annotation/request.d.ts
876
- type RequestSchemaDefinition = {
877
- body?: StandardSchemaV1 & StandardJSONSchemaV1;
878
- param?: StandardSchemaV1 & StandardJSONSchemaV1;
879
- query?: StandardSchemaV1 & StandardJSONSchemaV1;
787
+ //#region src/helper/sapling.d.ts
788
+ type Settings = {
789
+ serialize: (value: any) => string;
790
+ deserialize: (value: string) => any;
791
+ doc: {
792
+ openApiPath: string;
793
+ swaggerPath: string;
794
+ metadata: OpenAPIMetadata;
795
+ };
880
796
  };
797
+ declare const _settings: Settings;
881
798
  /**
882
- * Apply to a route method to have `request.body` be parsed by `schema`.
883
- *
884
- * This annotation will parse `request.body` & then override `request.body`.
885
- * You can then just simply cast `request.body` for your use
886
- *
887
- * @example
888
- * ```ts
889
- * const CREATE_BOOK_REQUEST_BODY_SCHEMA = z.object({
890
- * name: z.string(),
891
- * description: z.string().optional(),
892
- * });
893
- *
894
- * ⠀@Controller({ prefix: "/api/book" })
895
- * class BookController {
896
- * ⠀@RequestBody(CREATE_BOOK_REQUEST_BODY_SCHEMA)
897
- * ⠀@POST()
898
- * public createBook(request: e.Request) {
899
- * const { name, description } = request.body as unknown as z.infer<
900
- * typeof CREATE_BOOK_REQUEST_BODY_SCHEMA
901
- * >;
902
- * }
903
- * }
904
- * ```
799
+ * Collection of utility functions which are essential for Sapling to function.
905
800
  */
801
+ declare class Sapling {
802
+ /**
803
+ * If you would prefer to manually resolve your controllers instead, call resolve
804
+ * on the controller class.
805
+ *
806
+ * @example```ts
807
+ * import { Sapling } from "@tahminator/sapling";
808
+ * import TestController from "./path/to/test.controller";
809
+ *
810
+ * const app = express();
811
+ *
812
+ * const router = Sapling.resolve(TestController);
813
+ * app.use(router);
814
+ * ```
815
+ */
816
+ static resolve<TClass>(this: void, clazz: Class<TClass>): Router | ErrorRequestHandler;
817
+ /**
818
+ * Register this function as a middleware in order to utilize Sapling's `deserialize` function.
819
+ *
820
+ * @example```ts
821
+ * import { Sapling } from "@tahminator/sapling";
822
+ * import express from "express";
823
+ *
824
+ * const app = express();
825
+ *
826
+ * app.use(Sapling.json());
827
+ * ```
828
+ */
829
+ static json(this: void): ExpressMiddlewareFn;
830
+ /**
831
+ * Register your application with all the necessary middlewares and logics for Sapling to function.
832
+ *
833
+ * @example```ts
834
+ * import { Sapling } from "@tahminator/sapling";
835
+ * import express from "express";
836
+ *
837
+ * const app = express();
838
+ *
839
+ * app.registerApp(app);
840
+ * ```
841
+ */
842
+ static registerApp(app: e.Express): void;
843
+ /**
844
+ * Serialize a value into a JSON string.
845
+ *
846
+ * This function is used in {@link ResponseEntity} to serialize the `body`.
847
+ *
848
+ * Use `setSerializeFn` to override underlying implementation.
849
+ *
850
+ * @defaultValue `JSON.stringify`
851
+ */
852
+ static serialize(this: void, value: any): string;
853
+ /**
854
+ * Replace the function used for `serialize`.
855
+ */
856
+ static setSerializeFn(this: void, fn: (value: any) => string): void;
857
+ /**
858
+ * De-serialize a JSON string back to a JavaScript object.
859
+ *
860
+ * This function is used to de-serialize a string into a `body`.
861
+ *
862
+ * Use `setDeserializeFn` to override underlying implementation.
863
+ *
864
+ * @defaultValue `JSON.parse`
865
+ */
866
+ static deserialize<T = any>(this: void, value: string): T;
867
+ /**
868
+ * Replace the function used for `deserialize`
869
+ */
870
+ static setDeserializeFn(this: void, fn: (value: string) => any): void;
871
+ /**
872
+ * Modify extra settings
873
+ */
874
+ static Extras: {
875
+ /**
876
+ * Modify default settings applied to OpenAPI & Swagger
877
+ */
878
+ swaggerAndOpenApi: {
879
+ /**
880
+ * Set base OpenAPI metadata values.
881
+ *
882
+ * @default { title: "API", version: "1.0.0" }
883
+ */
884
+ setMetadata(metadata: OpenAPIMetadata): void;
885
+ /**
886
+ * change default endpoint that will serve OpenAPI spec.
887
+ * Swagger will also load this endpoint on load.
888
+ *
889
+ * @default `/openapi.json`
890
+ */
891
+ setOpenApiPath(this: void, path: string): void;
892
+ /**
893
+ * change Swagger endpoint.
894
+ *
895
+ * @default `/swagger.html`
896
+ */
897
+ setSwaggerPath(this: void, path: string): void;
898
+ };
899
+ };
900
+ /**
901
+ * This method can be used in a `@MiddlewareClass` to register any libraries
902
+ * that expect you to register multiple registers at once. An example is `swagger-ui-express`
903
+ *
904
+ * @example
905
+ * ```ts
906
+ * ⠀@MiddlewareClass()
907
+ * class Serve {
908
+ * // `swagger.serve` returns multiple Express handlers for all the assets and routes
909
+ * // that will be served
910
+ * private readonly handlers: RequestHandler[] = swagger.serve;
911
+ *
912
+ * ⠀@Middleware(_settings.doc.swaggerPath)
913
+ * handle(request: Request, response: Response, next: NextFunction) {
914
+ * return Sapling.chainHandlers(this.handlers, request, response, next);
915
+ * }
916
+ * }
917
+ * ```
918
+ */
919
+ static chainHandlers(this: void, handlers: RequestHandler[], request: Request, response: Response$1, next: NextFunction, index?: number): void;
920
+ }
921
+ //#endregion
922
+ //#region src/annotation/validator.d.ts
923
+ type ValidatorSchema = {
924
+ requestBody?: StandardSchemaV1 & StandardJSONSchemaV1;
925
+ requestParam?: StandardSchemaV1 & StandardJSONSchemaV1;
926
+ requestQuery?: StandardSchemaV1 & StandardJSONSchemaV1;
927
+ responseBody?: StandardSchemaV1 & StandardJSONSchemaV1;
928
+ };
929
+ declare function ResponseBody(schema: StandardSchemaV1 & StandardJSONSchemaV1): MethodDecorator;
906
930
  declare function RequestBody(schema: StandardSchemaV1 & StandardJSONSchemaV1): MethodDecorator;
907
- /**
908
- * Apply to a route method to have `request.param` be parsed by `schema`.
909
- *
910
- * This annotation will parse `request.param` & then override `request.param`.
911
- * You can then just simply cast `request.param` for your use
912
- *
913
- * @example
914
- * ```ts
915
- * const GET_BOOK_REQUEST_PARAM_SCHEMA = z.object({
916
- * bookId: z.string(),
917
- * });
918
- *
919
- * ⠀@Controller({ prefix: "/api/book" })
920
- * class BookController {
921
- * ⠀@RequestParam(GET_BOOK_REQUEST_PARAM_SCHEMA)
922
- * ⠀@GET("/:bookId")
923
- * public getBook(request: e.Request) {
924
- * const { bookId } = request.param as unknown as z.infer<
925
- * typeof GET_BOOK_REQUEST_PARAM_SCHEMA
926
- * >;
927
- * }
928
- * }
929
- * ```
930
- */
931
931
  declare function RequestParam(schema: StandardSchemaV1 & StandardJSONSchemaV1): MethodDecorator;
932
- /**
933
- * Apply to a route method to have `request.query` be parsed by `schema`.
934
- *
935
- * This annotation will parse `request.query` & then override `request.query`.
936
- * You can then just simply cast `request.query` for your use
937
- *
938
- * @example
939
- * ```ts
940
- * const LIST_BOOKS_REQUEST_QUERY_SCHEMA = z.object({
941
- * sort: z.enum(["name", "createdAt"]).optional(),
942
- * q: z.string().optional(),
943
- * });
944
- *
945
- * ⠀@Controller({ prefix: "/api/book" })
946
- * class BookController {
947
- * ⠀@RequestQuery(LIST_BOOKS_REQUEST_QUERY_SCHEMA)
948
- * ⠀@GET()
949
- * public listBooks(request: e.Request) {
950
- * const { sort, q } = request.query as unknown as z.infer<
951
- * typeof LIST_BOOKS_REQUEST_QUERY_SCHEMA
952
- * >;
953
- * }
954
- * }
955
- * ```
956
- */
957
932
  declare function RequestQuery(schema: StandardSchemaV1 & StandardJSONSchemaV1): MethodDecorator;
958
- declare function _getRequestSchemas(ctor: Function, fnName: string): RequestSchemaDefinition | undefined;
959
- declare function _parseOrThrow<TSchema extends StandardSchemaV1>(schema: TSchema, input: unknown, kind: ParserErrorLocation): Promise<StandardSchemaV1.InferOutput<TSchema>>;
933
+ declare function _getOrCreateSchemaDefinition(ctor: Function, fnName: string): ValidatorSchema;
934
+ declare function _parseOrThrow<TSchema extends StandardSchemaV1>(schema: TSchema, input: unknown, location: ParserErrorLocation, fnName: string): Promise<StandardSchemaV1.InferOutput<TSchema>>;
935
+ declare function _saveValidatorSchema(def: ValidatorSchema, key: keyof ValidatorSchema, schema: StandardSchemaV1 & StandardJSONSchemaV1, fnName: string): void;
936
+ declare function _getValidatorSchema(ctor: Function, fnName: string): ValidatorSchema | undefined;
937
+ //#endregion
938
+ //#region src/annotation/schema.d.ts
939
+ type ResponseSchema = {
940
+ statusCode: HttpStatus;
941
+ description?: string;
942
+ schema?: StandardSchemaV1 & StandardJSONSchemaV1;
943
+ };
944
+ type RouteSchemaDefinition = {
945
+ summary?: string;
946
+ description?: string;
947
+ responses?: ResponseSchema[];
948
+ };
949
+ type ControllerSchemaDefinition = {
950
+ title?: string;
951
+ description?: string;
952
+ };
953
+ declare function ControllerSchema(options: {
954
+ title?: string;
955
+ description?: string;
956
+ }): ClassDecorator;
957
+ declare function RouteSchema(options: {
958
+ summary?: string;
959
+ description?: string;
960
+ responses?: ResponseSchema[];
961
+ }): MethodDecorator;
962
+ declare function _setRouteSchema(ctor: Function, fnName: string, options: RouteSchemaDefinition): void;
963
+ declare function _setControllerSchema(ctor: Function, options: ControllerSchemaDefinition): void;
964
+ declare function _getRouteSchema(ctor: Function, fnName: string): RouteSchemaDefinition | undefined;
965
+ declare function _getControllerSchema(ctor: Function): ControllerSchemaDefinition | undefined;
960
966
  //#endregion
961
967
  //#region src/middleware/default/error/base.d.ts
962
968
  /**
963
969
  * This should be registered last in the middleware chain.
964
970
  *
965
971
  * All exception messages are hidden from the request by default.
972
+ * If the default is not suitable, you may also easily write your own.
966
973
  */
967
974
  declare class DefaultBaseErrorMiddleware {
968
975
  handle(err: unknown, _request: Request, _response: Response$1, _next: NextFunction): ResponseEntity<{
@@ -971,6 +978,10 @@ declare class DefaultBaseErrorMiddleware {
971
978
  }
972
979
  //#endregion
973
980
  //#region src/middleware/default/error/parse.d.ts
981
+ /**
982
+ * Default error middleware that handles `ParserError`.
983
+ * If the default is not suitable, you may also easily write your own.
984
+ */
974
985
  declare class DefaultParserErrorMiddleware {
975
986
  handle(err: unknown, _request: Request, _response: Response$1, next: NextFunction): ResponseEntity<{
976
987
  message: string;
@@ -978,6 +989,10 @@ declare class DefaultParserErrorMiddleware {
978
989
  }
979
990
  //#endregion
980
991
  //#region src/middleware/default/error/responsestatus.d.ts
992
+ /**
993
+ * Default error middleware that handles `ResponseStatusError`.
994
+ * If the default is not suitable, you may also easily write your own.
995
+ */
981
996
  declare class DefaultResponseStatusErrorMiddleware {
982
997
  handle(err: unknown, _request: Request, _response: Response$1, next: NextFunction): ResponseEntity<{
983
998
  message: string;
@@ -985,23 +1000,87 @@ declare class DefaultResponseStatusErrorMiddleware {
985
1000
  }
986
1001
  //#endregion
987
1002
  //#region src/middleware/default/openapi/index.d.ts
1003
+ /**
1004
+ * Enable the serving of the OpenAPI spec autogenerated by Sapling.
1005
+ *
1006
+ * Configure any middleware-specific settings with `Sapling.Extras.swaggerAndOpenApi`
1007
+ *
1008
+ * You must register `DefaultSwaggerMiddleware.Serve` & `DefaultSwaggerMiddleware.Setup` after `DefaultOpenApiMiddleware`
1009
+ *
1010
+ * ```ts
1011
+ * const middlewares = [
1012
+ * DefaultOpenApiMiddleware,
1013
+ * DefaultSwaggerMiddleware.Serve,
1014
+ * DefaultSwaggerMiddleware.Setup,
1015
+ * ];
1016
+ * middlewares.map(Sapling.resolve).forEach((r) => app.use(r));
1017
+ * ```
1018
+ */
988
1019
  declare class DefaultOpenApiMiddleware {
989
1020
  handle(_request: Request, _response: Response$1, _next: NextFunction): ResponseEntity<OpenAPIV3.Document<{}>>;
990
1021
  }
991
1022
  //#endregion
992
1023
  //#region src/middleware/default/swagger/index.d.ts
1024
+ /**
1025
+ * Enable the serving of the Swagger endpoint used to serve the OpenAPI spec generated by Sapling.
1026
+ *
1027
+ * Configure any middleware-specific settings with `Sapling.Extras.swaggerAndOpenApi`
1028
+ *
1029
+ * You must register `DefaultSwaggerMiddleware.Serve` & `DefaultSwaggerMiddleware.Setup` after `DefaultOpenApiMiddleware`
1030
+ *
1031
+ * ```ts
1032
+ * const middlewares = [
1033
+ * DefaultOpenApiMiddleware,
1034
+ * DefaultSwaggerMiddleware.Serve,
1035
+ * DefaultSwaggerMiddleware.Setup,
1036
+ * ];
1037
+ * middlewares.map(Sapling.resolve).forEach((r) => app.use(r));
1038
+ * ```
1039
+ */
993
1040
  declare class Serve {
994
1041
  private readonly handlers;
995
- handle(_request: Request, _response: Response$1, _next: NextFunction): RequestHandler[];
1042
+ handle(request: Request, response: Response$1, next: NextFunction): void;
996
1043
  }
1044
+ /**
1045
+ * Enable the serving of the Swagger endpoint used to serve the OpenAPI spec generated by Sapling.
1046
+ *
1047
+ * Configure any middleware-specific settings with `Sapling.Extras.swaggerAndOpenApi`
1048
+ *
1049
+ * You must register `DefaultSwaggerMiddleware.Serve` & `DefaultSwaggerMiddleware.Setup` after `DefaultOpenApiMiddleware`
1050
+ *
1051
+ * ```ts
1052
+ * const middlewares = [
1053
+ * DefaultOpenApiMiddleware,
1054
+ * DefaultSwaggerMiddleware.Serve,
1055
+ * DefaultSwaggerMiddleware.Setup,
1056
+ * ];
1057
+ * middlewares.map(Sapling.resolve).forEach((r) => app.use(r));
1058
+ * ```
1059
+ */
997
1060
  declare class Setup {
998
1061
  private readonly handler;
999
1062
  constructor();
1000
1063
  handle(request: Request, response: Response$1, next: NextFunction): unknown;
1001
1064
  }
1065
+ /**
1066
+ * Enable the serving of the Swagger endpoint used to serve the OpenAPI spec generated by Sapling.
1067
+ *
1068
+ * Configure any middleware-specific settings with `Sapling.Extras.swaggerAndOpenApi`
1069
+ *
1070
+ * You must register `DefaultSwaggerMiddleware.Serve` & `DefaultSwaggerMiddleware.Setup` after `DefaultOpenApiMiddleware`
1071
+ *
1072
+ * ```ts
1073
+ * const middlewares = [
1074
+ * DefaultOpenApiMiddleware,
1075
+ * DefaultSwaggerMiddleware.Serve,
1076
+ * DefaultSwaggerMiddleware.Setup,
1077
+ * ];
1078
+ * middlewares.map(Sapling.resolve).forEach((r) => app.use(r));
1079
+ * ```
1080
+ */
1002
1081
  declare const DefaultSwaggerMiddleware: {
1003
1082
  Serve: typeof Serve;
1004
1083
  Setup: typeof Setup;
1005
1084
  };
1006
1085
  //#endregion
1007
- export { Class, Controller, DELETE, DefaultBaseErrorMiddleware, DefaultOpenApiMiddleware, DefaultParserErrorMiddleware, DefaultResponseStatusErrorMiddleware, DefaultSwaggerMiddleware, ExpressMiddlewareFn, ExpressRouterMethodKey, ExpressRouterMethods, GET, HEAD, Html404ErrorPage, HttpHeaders, HttpStatus, Injectable, Middleware, MiddlewareClass, OPTIONS, PATCH, POST, PUT, ParserError, ParserErrorLocation, RedirectView, RequestBody, RequestParam, RequestQuery, ResponseEntity, ResponseEntityBuilder, ResponseStatusError, RouteDefinition, Sapling, _ControllerRegistry, _InjectableDeps, _InjectableRegistry, _Route, _generateOpenApiSpec, _getRequestSchemas, _getRoutes, _parseOrThrow, _registerControllerClass, _resolve, _setOpenApiConfig, _settings, methodResolve, openApiGenerator };
1086
+ export { Class, Controller, ControllerSchema, ControllerSchemaDefinition, DELETE, DefaultBaseErrorMiddleware, DefaultOpenApiMiddleware, DefaultParserErrorMiddleware, DefaultResponseStatusErrorMiddleware, DefaultSwaggerMiddleware, ExpressMiddlewareFn, ExpressRouterMethodKey, ExpressRouterMethods, GET, HEAD, Html404ErrorPage, HttpHeaders, HttpStatus, Injectable, Middleware, MiddlewareClass, OPTIONS, OpenAPIMetadata, PATCH, POST, PUT, ParserError, ParserErrorLocation, RedirectView, RequestBody, RequestParam, RequestQuery, ResponseBody, ResponseEntity, ResponseEntityBuilder, ResponseSchema, ResponseStatusError, RouteDefinition, RouteSchema, RouteSchemaDefinition, Sapling, ValidatorSchema, _ControllerRegistry, _InjectableDeps, _InjectableRegistry, _Route, _getControllerSchema, _getOrCreateSchemaDefinition, _getRouteSchema, _getRoutes, _getValidatorSchema, _parseOrThrow, _registerController, _resolve, _saveValidatorSchema, _setControllerSchema, _setRouteSchema, _settings, generateOpenApiSpec, methodResolve, openApiGenerator };