@necessarylion/adonis-autoswagger 0.0.1 → 0.0.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/README.md CHANGED
@@ -13,11 +13,13 @@ Adonis AutoSwagger <br />
13
13
  ## 💻️ Install
14
14
 
15
15
  ```bash
16
- pnpm i adonis-autoswagger #using pnpm
16
+ pnpm i @necessarylion/adonis-autoswagger #using pnpm
17
17
  ```
18
18
 
19
19
  ---
20
20
 
21
+ *This is a fork of [adonis-autoswagger](https://github.com/ad-on-is/adonis-autoswagger) with some additional features.*
22
+
21
23
  ## ⭐️ Features
22
24
 
23
25
  - Creates **paths** automatically based on `routes.ts`
@@ -76,7 +78,7 @@ In your `routes.ts`
76
78
  ## 6️⃣ for AdonisJS v6
77
79
 
78
80
  ```js
79
- import AutoSwagger from "adonis-autoswagger";
81
+ import AutoSwagger from "@necessarylion/adonis-autoswagger";
80
82
  import swagger from "#config/swagger";
81
83
  // returns swagger in YAML
82
84
  router.get("/swagger", async () => {
@@ -94,7 +96,7 @@ router.get("/docs", async () => {
94
96
  ## 5️⃣ for AdonisJS v5
95
97
 
96
98
  ```js
97
- import AutoSwagger from "adonis-autoswagger";
99
+ import AutoSwagger from "@necessarylion/adonis-autoswagger";
98
100
  import swagger from "Config/swagger";
99
101
  // returns swagger in YAML
100
102
  Route.get("/swagger", async () => {
@@ -456,6 +458,71 @@ Generates responses and requestBody based on your simple Controller-Annotation (
456
458
 
457
459
  ## Schemas
458
460
 
461
+ ### Validators
462
+
463
+ Automatically generates swagger schema-descriptions based on your validators.
464
+
465
+ #### Adding example values
466
+
467
+ ```ts
468
+ export const adminLogin = vine.compile(
469
+ vine.object({
470
+ email: vine.string().trim().example('admin@laconcept.de'),
471
+ password: vine.string().trim().example('password'),
472
+ })
473
+ )
474
+ ```
475
+
476
+ ##### Create custom validators with vine
477
+
478
+ ```ts
479
+ // start/validators/example.ts
480
+
481
+ import vine, { VineNumber, VineString, VineNativeEnum } from '@vinejs/vine'
482
+ import { EnumLike } from '@vinejs/vine/types'
483
+
484
+ type Options = {
485
+ example: any
486
+ }
487
+
488
+ declare module '@vinejs/vine' {
489
+ interface VineString {
490
+ example(example: string): this
491
+ }
492
+ interface VineNumber {
493
+ example(example: number): this
494
+ }
495
+ interface VineNativeEnum<Values extends EnumLike> {
496
+ example(example: string): this
497
+ }
498
+ }
499
+
500
+ export const exampleRule = vine.createRule((_: unknown, opt: Options) => {
501
+ return opt.example
502
+ })
503
+
504
+ VineString.macro('example', function (this: VineString, example: string) {
505
+ return this.use(exampleRule({ example }))
506
+ })
507
+ VineNumber.macro('example', function (this: VineNumber, example: number) {
508
+ return this.use(exampleRule({ example }))
509
+ })
510
+ VineNativeEnum.macro('example', function (this: VineNativeEnum<any>, example: string) {
511
+ return this.use(exampleRule({ example }))
512
+ })
513
+ ```
514
+
515
+ ##### Import in `adonisrc.ts` preloads
516
+
517
+ ```ts
518
+ preloads: [
519
+ () => import('#start/routes'),
520
+ () => import('#start/kernel'),
521
+ () => import('#start/sentry'),
522
+ () => import('#start/validators/example.ts'),
523
+ ],
524
+ ```
525
+
459
526
  ### Models
460
527
 
461
528
  Automatically generates swagger schema-descriptions based on your models
@@ -464,7 +531,16 @@ Automatically generates swagger schema-descriptions based on your models
464
531
 
465
532
  ### Interfaces
466
533
 
467
- Instead of using `param: any` you can now use custom interfaces `param: UserDetails`. The interfaces files need to be located at `app/Interfaces/`
534
+ Instead of using `param: any` you can now use custom interfaces `param: UserDetails`. The interfaces files need to be located at `app/Interfaces/` or `app/interfaces/`
535
+
536
+ ```ts
537
+ export interface UserDetails {
538
+ // @example(John Doe)
539
+ name: string;
540
+ // @example(johndoe@example.com)
541
+ email: string;
542
+ }
543
+ ```
468
544
 
469
545
  ### Enums
470
546
 
@@ -279,22 +279,23 @@ class AutoSwagger {
279
279
  description: "The resource has been created",
280
280
  },
281
281
  },
282
- securitySchemes: {
283
- BearerAuth: {
284
- type: "http",
285
- scheme: "bearer",
286
- },
287
- BasicAuth: {
288
- type: "http",
289
- scheme: "basic",
290
- },
291
- ApiKeyAuth: {
292
- type: "apiKey",
293
- in: "header",
294
- name: "X-API-Key",
282
+ securitySchemes: this.options.securitySchemes
283
+ ? this.options.securitySchemes
284
+ : {
285
+ BearerAuth: {
286
+ type: "http",
287
+ scheme: "bearer",
288
+ },
289
+ BasicAuth: {
290
+ type: "http",
291
+ scheme: "basic",
292
+ },
293
+ ApiKeyAuth: {
294
+ type: "apiKey",
295
+ in: "header",
296
+ name: "X-API-Key",
297
+ },
295
298
  },
296
- ...this.options.securitySchemes,
297
- },
298
299
  schemas: this.schemas,
299
300
  },
300
301
  paths: {},
@@ -675,10 +676,12 @@ class AutoSwagger {
675
676
  }
676
677
  let schema = {
677
678
  type: "object",
678
- required: parsed.required,
679
679
  properties: parsed.props,
680
680
  description: name + " (Model)",
681
681
  };
682
+ if (parsed.required.length > 0) {
683
+ schema['required'] = parsed.required;
684
+ }
682
685
  models[name] = schema;
683
686
  }
684
687
  return models;
package/dist/parsers.d.ts CHANGED
@@ -52,7 +52,17 @@ export declare class ValidatorParser {
52
52
  validatorToObject(validator: VineValidator<any, any>): Promise<any>;
53
53
  parsePropsAndMeta(obj: any, testObj: any, validator: VineValidator<any, any>): Promise<any>;
54
54
  objToTest(obj: any): {};
55
- parseSchema(json: any, refs: any): {};
55
+ parseSchema(json: any, refs: any): {
56
+ properties: {};
57
+ };
58
+ getType(type: string): string;
59
+ getMetaFromValidations(validations: any, refs: any): {
60
+ minimum?: number;
61
+ maximum?: number;
62
+ enum?: any;
63
+ pattern?: string;
64
+ example?: any;
65
+ };
56
66
  }
57
67
  export declare class InterfaceParser {
58
68
  exampleGenerator: ExampleGenerator;
package/dist/parsers.js CHANGED
@@ -110,7 +110,7 @@ class CommentParser {
110
110
  return h;
111
111
  }
112
112
  if (line.startsWith("@paramPath")) {
113
- required = false;
113
+ required = true;
114
114
  }
115
115
  if (line.startsWith("@paramQuery")) {
116
116
  required = false;
@@ -688,7 +688,7 @@ class ValidatorParser {
688
688
  // console.dir(json, { depth: null });
689
689
  const obj = {
690
690
  type: "object",
691
- properties: this.parseSchema(validator.toJSON()["schema"]["schema"], validator.toJSON()["refs"]),
691
+ ...this.parseSchema(validator.toJSON()["schema"]["schema"], validator.toJSON()["refs"]),
692
692
  };
693
693
  // console.dir(obj, { depth: null });
694
694
  const testObj = this.objToTest(obj["properties"]);
@@ -779,54 +779,84 @@ class ValidatorParser {
779
779
  }
780
780
  parseSchema(json, refs) {
781
781
  const obj = {};
782
+ const required = [];
782
783
  for (const p of json["properties"]) {
783
- let meta = {};
784
- for (const v of p["validations"]) {
785
- if (refs[v["ruleFnId"]].options?.example) {
786
- meta = { ...meta, example: refs[v["ruleFnId"]].options.example };
787
- }
788
- if (refs[v["ruleFnId"]].options?.min) {
789
- meta = { ...meta, minimum: refs[v["ruleFnId"]].options.min };
790
- }
791
- if (refs[v["ruleFnId"]].options?.max) {
792
- meta = { ...meta, maximum: refs[v["ruleFnId"]].options.max };
793
- }
794
- if (refs[v["ruleFnId"]].options?.choices) {
795
- meta = { ...meta, choices: refs[v["ruleFnId"]].options.choices };
796
- }
797
- if (refs[v["ruleFnId"]].options?.toString().includes("/")) {
798
- meta = { ...meta, pattern: refs[v["ruleFnId"]].options.toString() };
799
- }
800
- }
784
+ let meta = this.getMetaFromValidations(p["validations"], refs);
801
785
  // console.dir(p, { depth: null });
802
786
  // console.dir(validations, { depth: null });
803
787
  // console.log(min, max, choices, regex);
804
- obj[p["fieldName"]] =
805
- p["type"] === "object"
806
- ? { type: "object", properties: this.parseSchema(p, refs) }
807
- : p["type"] === "array"
808
- ? {
788
+ const type = p["type"];
789
+ const field = p["fieldName"];
790
+ if (type === "object") {
791
+ console.log(field, p);
792
+ obj[field] = { type: "object", ...this.parseSchema(p, refs) };
793
+ }
794
+ else {
795
+ // if array
796
+ if (type === "array") {
797
+ if (p["each"]["type"] === "object") {
798
+ obj[field] = {
809
799
  type: "array",
810
- items: p["each"]["type"] === "object"
811
- ? {
812
- type: "object",
813
- properties: this.parseSchema(p["each"], refs),
814
- }
815
- : {
816
- type: "number",
817
- example: meta.example ?? meta.minimum ?? this.exampleGenerator.exampleByType("number"),
818
- ...meta,
819
- },
820
- }
821
- : {
822
- type: "number",
823
- example: meta.example ?? meta.minimum ?? this.exampleGenerator.exampleByType("number"),
824
- ...meta,
800
+ items: {
801
+ type: "object",
802
+ ...this.parseSchema(p["each"], refs),
803
+ }
804
+ };
805
+ }
806
+ else {
807
+ const meta = this.getMetaFromValidations(p["each"]["validations"], refs);
808
+ obj[field] = {
809
+ type: "array",
810
+ items: {
811
+ type: this.getType(p["each"]["type"]),
812
+ ...meta,
813
+ example: meta.example ?? meta.minimum ?? this.exampleGenerator.exampleByType("number"),
814
+ },
825
815
  };
816
+ }
817
+ }
818
+ else {
819
+ obj[field] = {
820
+ type: this.getType(type),
821
+ example: meta.example ?? meta.minimum ?? this.exampleGenerator.exampleByType("number"),
822
+ ...meta,
823
+ };
824
+ }
825
+ }
826
826
  if (!p["isOptional"])
827
- obj[p["fieldName"]]["required"] = true;
827
+ required.push(p["fieldName"]);
828
828
  }
829
- return obj;
829
+ const res = { properties: obj };
830
+ if (required.length > 0)
831
+ res["required"] = required;
832
+ return res;
833
+ }
834
+ getType(type) {
835
+ if (type == 'literal') {
836
+ return 'string';
837
+ }
838
+ return type;
839
+ }
840
+ getMetaFromValidations(validations, refs) {
841
+ let meta = {};
842
+ for (const v of validations) {
843
+ if (refs[v["ruleFnId"]].options?.example) {
844
+ meta = { ...meta, example: refs[v["ruleFnId"]].options.example };
845
+ }
846
+ if (refs[v["ruleFnId"]].options?.min) {
847
+ meta = { ...meta, minimum: refs[v["ruleFnId"]].options.min };
848
+ }
849
+ if (refs[v["ruleFnId"]].options?.max) {
850
+ meta = { ...meta, maximum: refs[v["ruleFnId"]].options.max };
851
+ }
852
+ if (refs[v["ruleFnId"]].options?.choices) {
853
+ meta = { ...meta, enum: refs[v["ruleFnId"]].options.choices };
854
+ }
855
+ if (refs[v["ruleFnId"]].options?.toString().includes("/")) {
856
+ meta = { ...meta, pattern: refs[v["ruleFnId"]].options.toString() };
857
+ }
858
+ }
859
+ return meta;
830
860
  }
831
861
  }
832
862
  exports.ValidatorParser = ValidatorParser;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@necessarylion/adonis-autoswagger",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "Auto-Generate swagger docs for AdonisJS",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",