directus-extension-api-docs 1.4.1 → 1.4.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
@@ -1,134 +1,126 @@
1
- # directus-extension-api-docs
2
-
3
- Directus Extension to include a Swagger interface and custom endpoints definitions
4
-
5
- ![workspace](assets/swagger.png)
6
-
7
- All directus endpoints are autogenerated on runtime.
8
-
9
- **You can enable validations middleware based on your custom definitions. See below**
10
-
11
- ## Prerequisites
12
-
13
- Working in a Directus nodejs project
14
-
15
- Ref: https://github.com/directus/directus
16
-
17
- ## Installation
18
-
19
- npm install directus-extension-api-docs
20
-
21
- ## Configuration (optional)
22
-
23
- For include you custom endpoints.
24
-
25
- Create a `oasconfig.yaml` file under `/extensions/endpoints` folder.
26
-
27
- Options:
28
-
29
- - `docsPath` _optional_ path where the interface will be (default 'api-docs')
30
- - `tags` _optional_ openapi custom tags (will be merged with all standard and all customs tags)
31
- - `paths` _optional_ openapi custom paths (will be merged with all standard and all customs paths)
32
- - `components` _optional_ openapi custom components (will be merged with all standard and all customs tags)
33
-
34
- Example below:
35
-
36
- ```
37
- docsPath: 'api-docs'
38
- tags:
39
- - name: MyCustomTag
40
- description: MyCustomTag description
41
- components:
42
- schemas:
43
- UserId:
44
- type: object
45
- required:
46
- - user_id
47
- x-collection: directus_users
48
- properties:
49
- user_id:
50
- description: Unique identifier for the user.
51
- example: 63716273-0f29-4648-8a2a-2af2948f6f78
52
- type: string
53
-
54
- ```
55
-
56
- ## Definitions (optional)
57
-
58
- For each custom endpoints group, you can define api's including a file `oas.yaml` in root path of your group folder.
59
-
60
- Properties:
61
-
62
- - `tags` _optional_ openapi custom tags
63
- - `paths` _optional_ openapi custom paths
64
- - `components` _optional_ openapi custom components
65
-
66
- Exemple below (`./extensions/endpoints/my-custom-path/oas.yaml`) :
67
-
68
- ```
69
- tags:
70
- - name: MyCustomTag2
71
- description: MyCustomTag description2
72
- paths:
73
- "/my-custom-path/my-endpoint":
74
- post:
75
- summary: Validate email
76
- description: Validate email
77
- tags:
78
- - MyCustomTag2
79
- - MyCustomTag
80
- requestBody:
81
- content:
82
- application/json:
83
- schema:
84
- "$ref": "#/components/schemas/UserId"
85
- responses:
86
- '200':
87
- description: Successful request
88
- content:
89
- application/json:
90
- schema:
91
- "$ref": "#/components/schemas/Users"
92
- '401':
93
- description: Unauthorized
94
- content: {}
95
- '422':
96
- description: Unprocessable Entity
97
- content: {}
98
- '500':
99
- description: Server Error
100
- content: {}
101
- components:
102
- schemas:
103
- Users:
104
- type: object # you can ref to standard components declaring it empty
105
- ```
106
-
107
- ## Validations (optional)
108
-
109
- You can enable a request validations middleware based on your custom definitions.
110
-
111
- Call `validate` function inside your custom endpoint registration.
112
-
113
- Pass your `router`, `services`, `schema` and a list (_optional_) of endpoints you want to validate.
114
-
115
- Example below:
116
-
117
- ```
118
- const { validate } = require('directus-extension-api-docs');
119
-
120
- const id = 'my-custom-path';
121
-
122
- module.exports = {
123
- id,
124
- handler: async function registerEndpoint(router, { services, getSchema }) {
125
-
126
- const schema = await getSchema();
127
- await validate(router, services, schema); // Enable validator for custom endpoints
128
-
129
- router.post('/my-endpoint', async (req, res, next) => {
130
- ...
131
- });
132
- },
133
- };
134
- ```
1
+ # directus-extension-api-docs
2
+
3
+ Directus Extension to include a Swagger interface and custom endpoints definitions
4
+
5
+ ![workspace](assets/swagger.png)
6
+
7
+ All directus endpoints are autogenerated on runtime.
8
+
9
+ **You can enable validations middleware based on your custom definitions. See below**
10
+
11
+ ## Prerequisites
12
+
13
+ Working in a Directus nodejs project
14
+
15
+ Ref: https://github.com/directus/directus
16
+
17
+ ## Installation
18
+
19
+ npm install directus-extension-api-docs
20
+
21
+ ## Configuration (optional)
22
+
23
+ For include you custom endpoints.
24
+
25
+ Create a `oasconfig.yaml` file under `/extensions/endpoints` folder.
26
+
27
+ Options:
28
+
29
+ - `docsPath` _optional_ path where the interface will be (default 'api-docs')
30
+ - `tags` _optional_ openapi custom tags (will be merged with all standard and all customs tags)
31
+ - `paths` _optional_ openapi custom paths (will be merged with all standard and all customs paths)
32
+ - `components` _optional_ openapi custom components (will be merged with all standard and all customs tags)
33
+
34
+ Example below:
35
+
36
+ ```
37
+ docsPath: 'api-docs'
38
+ tags:
39
+ - name: MyCustomTag
40
+ description: MyCustomTag description
41
+ components:
42
+ schemas:
43
+ UserId:
44
+ type: object
45
+ required:
46
+ - user_id
47
+ x-collection: directus_users
48
+ properties:
49
+ user_id:
50
+ description: Unique identifier for the user.
51
+ example: 63716273-0f29-4648-8a2a-2af2948f6f78
52
+ type: string
53
+
54
+ ```
55
+
56
+ ## Definitions (optional)
57
+
58
+ For each custom endpoints group, you can define api's including a file `oas.yaml` in the root path of your group folder.
59
+
60
+ Properties:
61
+
62
+ - `tags` _optional_ openapi custom tags
63
+ - `paths` _optional_ openapi custom paths
64
+ - `components` _optional_ openapi custom components
65
+
66
+ Exemple below (`./extensions/endpoints/my-custom-path/oas.yaml`) :
67
+
68
+ ```
69
+ tags:
70
+ - name: MyCustomTag2
71
+ description: MyCustomTag description2
72
+ paths:
73
+ "/my-custom-path/my-endpoint":
74
+ post:
75
+ tags:
76
+ - MyCustomTag2
77
+ - MyCustomTag
78
+ requestBody:
79
+ content:
80
+ application/json:
81
+ schema:
82
+ "$ref": "#/components/schemas/UserId"
83
+ responses:
84
+ '200':
85
+ description: Successful request
86
+ content:
87
+ application/json:
88
+ schema:
89
+ "$ref": "#/components/schemas/Users"
90
+ '401':
91
+ description: Unauthorized
92
+ content: {}
93
+ components:
94
+ schemas:
95
+ Users:
96
+ type: object # ref to standard components declaring it empty
97
+ ```
98
+
99
+ ## Validations (optional)
100
+
101
+ You can enable a request validations middleware based on your custom definitions.
102
+
103
+ Call `validate` function inside your custom endpoint registration.
104
+
105
+ Pass your `router`, `services`, `schema` and a list (_optional_) of endpoints you want to validate.
106
+
107
+ Example below:
108
+
109
+ ```
110
+ const { validate } = require('directus-extension-api-docs');
111
+
112
+ const id = 'my-custom-path';
113
+
114
+ module.exports = {
115
+ id,
116
+ handler: async function registerEndpoint(router, { services, getSchema }) {
117
+
118
+ const schema = await getSchema();
119
+ await validate(router, services, schema); // Enable validator
120
+
121
+ router.post('/my-endpoint', async (req, res, next) => {
122
+ ...
123
+ });
124
+ },
125
+ };
126
+ ```
@@ -0,0 +1,9 @@
1
+ import { Router } from 'express';
2
+ declare function validate(router: Router, services: any, schema: any, paths: Array<string>): Promise<Router>;
3
+ declare const _default: {
4
+ id: string;
5
+ validate: typeof validate;
6
+ handler: any;
7
+ };
8
+ export default _default;
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAmC,MAAM,SAAS,CAAC;AAWlE,iBAAe,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAsCzG;;;;;;AAED,wBAiDE"}
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";const e=require("js-yaml"),s=require("path"),n=require("fs"),t=process.cwd();let o;async function i(e,s){if(o)return JSON.parse(o);const{SpecificationService:n}=e,t=new n({accountability:{admin:!0},schema:s});return o=JSON.stringify(await t.oas.generate()),JSON.parse(o)}function a(e,s){return Object.entries(s).reduce(((e,[s,n])=>(e[s]=n&&"object"==typeof n?a(e[s]=e[s]||(Array.isArray(n)?[]:{}),n):n,e)),e)}const r=require("swagger-ui-express"),c=require("express-openapi-validator"),{findWorkspaceDir:p}=require("@pnpm/find-workspace-dir"),u=function(){try{const o=s.join(t,"./extensions/endpoints/oasconfig.yaml"),i=e.load(n.readFileSync(o,{encoding:"utf-8"})),r=s.join(t,"./extensions/endpoints"),c=n.readdirSync(r,{withFileTypes:!0});for(const s of c){const t=`${r}/${s.name}/oas.yaml`;if(s.isDirectory()&&n.existsSync(t)){const s=e.load(n.readFileSync(t,{encoding:"utf-8"}));i.tags=[...i.tags,...s.tags],i.paths={...i.paths,...s.paths},i.components=a(i.components,s.components)}}return i}catch(e){return{}}}(),d=(null==u?void 0:u.docsPath)||"api-docs";var l={id:d,validate:async function(e,s,n,t){if(null==u?void 0:u.paths){const o=await i(s,n);if(t)for(const e of t)o.paths[e]=u.paths[e];else o.paths=u.paths;u.components?o.components=u.components:(delete o.components.definitions,delete o.components.schemas),e.use(c.middleware({apiSpec:o})),e.use(((e,s,n,t)=>{n.status(e.status||500).json({message:e.message,errors:e.errors})}))}return e},handler:(e,{services:s,exceptions:n,logger:t,getSchema:o})=>{const{ServiceUnavailableException:c}=n,l={swaggerOptions:{url:`/${d}/oas`}};e.use("/",r.serve),e.get("/",r.setup({},l)),e.get("/oas",(async(e,n,r)=>{try{const e=await o(),r=await i(s,e),c=require(`${await p(".")}/package.json`);r.info.title=c.name,r.info.version=c.version,r.info.description=c.description;try{if(null==u?void 0:u.paths)for(const e in u.paths)r.paths[e]=u.paths[e];if(null==u?void 0:u.tags)for(const e of u.tags)r.tags.push(e);(null==u?void 0:u.components)&&(r.components=a(u.components,r.components))}catch(e){t.info("No custom definitions")}n.json(r)}catch(e){return r(new c(e.message||e[0].message))}}))}};module.exports=l;
1
+ "use strict";const e=require("js-yaml"),s=require("path"),n=require("fs"),t=process.cwd();let o;async function i(e,s){if(o)return JSON.parse(o);const{SpecificationService:n}=e,t=new n({accountability:{admin:!0},schema:s});return o=JSON.stringify(await t.oas.generate()),JSON.parse(o)}function a(e,s){return Object.entries(s).reduce(((e,[s,n])=>(e[s]=n&&"object"==typeof n?a(e[s]=e[s]||(Array.isArray(n)?[]:{}),n):n,e)),e)}const r=require("swagger-ui-express"),c=require("express-openapi-validator"),{findWorkspaceDir:p}=require("@pnpm/find-workspace-dir"),u=function(){try{const o=s.join(t,"./extensions/endpoints/oasconfig.yaml"),i=e.load(n.readFileSync(o,{encoding:"utf-8"})),r=s.join(t,"./extensions/endpoints"),c=n.readdirSync(r,{withFileTypes:!0});for(const s of c){const t=`${r}/${s.name}/oas.yaml`;if(s.isDirectory()&&n.existsSync(t)){const s=e.load(n.readFileSync(t,{encoding:"utf-8"}));i.tags=[...i.tags,...s.tags],i.paths={...i.paths,...s.paths},i.components=a(i.components||{},s.components||{})}}return i}catch(e){return{}}}(),d=(null==u?void 0:u.docsPath)||"api-docs";var l={id:d,validate:async function(e,s,n,t){if(null==u?void 0:u.paths){const o=await i(s,n);if(t)for(const e of t)o.paths[e]=u.paths[e];else o.paths=u.paths;u.components?o.components=u.components:(delete o.components.definitions,delete o.components.schemas),e.use(c.middleware({apiSpec:o})),e.use(((e,s,n,t)=>{n.status(e.status||500).json({message:e.message,errors:e.errors})}))}return e},handler:(e,{services:s,exceptions:n,logger:t,getSchema:o})=>{const{ServiceUnavailableException:c}=n,l={swaggerOptions:{url:`/${d}/oas`}};e.use("/",r.serve),e.get("/",r.setup({},l)),e.get("/oas",(async(e,n,r)=>{try{const e=await o(),r=await i(s,e),c=require(`${await p(".")}/package.json`);r.info.title=c.name,r.info.version=c.version,r.info.description=c.description;try{if(null==u?void 0:u.paths)for(const e in u.paths)r.paths[e]=u.paths[e];if(null==u?void 0:u.tags)for(const e of u.tags)r.tags.push(e);(null==u?void 0:u.components)&&(r.components=a(u.components,r.components))}catch(e){t.info("No custom definitions")}n.json(r)}catch(e){return r(new c(e.message||e[0].message))}}))}};module.exports=l;
@@ -0,0 +1,22 @@
1
+ export interface oasconfig {
2
+ docsPath?: string;
3
+ tags?: Array<object>;
4
+ paths?: {
5
+ [key: string]: object;
6
+ };
7
+ components?: {
8
+ [key: string]: object;
9
+ };
10
+ }
11
+ export interface oas {
12
+ info: any;
13
+ docsPath: string;
14
+ tags: Array<any>;
15
+ paths: {
16
+ [key: string]: any;
17
+ };
18
+ components: {
19
+ [key: string]: any;
20
+ };
21
+ }
22
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACrB,KAAK,CAAC,EAAE;QACJ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;KACzB,CAAC;IACF,UAAU,CAAC,EAAE;QACT,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;KACzB,CAAC;CACL;AAED,MAAM,WAAW,GAAG;IAChB,IAAI,EAAE,GAAG,CAAC;IACV,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IACjB,KAAK,EAAE;QACH,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACtB,CAAC;IACF,UAAU,EAAE;QACR,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACtB,CAAC;CACL"}
@@ -0,0 +1,6 @@
1
+ import { SchemaOverview } from '@directus/shared/types';
2
+ import { oas, oasconfig } from './types';
3
+ export declare function getConfig(): oasconfig;
4
+ export declare function getOas(services: any, schema: SchemaOverview): Promise<oas>;
5
+ export declare function merge(a: any, b: any): any;
6
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAUzC,wBAAgB,SAAS,IAAI,SAAS,CAqBrC;AAED,wBAAsB,MAAM,CAAC,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,CAYhF;AAED,wBAAgB,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,OAKnC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "directus-extension-api-docs",
3
- "version": "1.4.1",
3
+ "version": "1.4.3",
4
4
  "description": "directus extension for swagger interface and custom endpoints definitions",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -40,14 +40,14 @@
40
40
  },
41
41
  "devDependencies": {
42
42
  "@babel/preset-env": "^7.20.2",
43
- "@directus/extensions-sdk": "^9.20.4",
43
+ "@directus/extensions-sdk": "^9.21.0",
44
44
  "@types/express": "^4.17.14",
45
45
  "@types/jest": "^29.2.3",
46
46
  "@types/node": "^18.11.9",
47
47
  "@typescript-eslint/eslint-plugin": "^5.43.0",
48
48
  "@typescript-eslint/parser": "^5.43.0",
49
49
  "babel-jest": "^29.3.1",
50
- "eslint": "^8.27.0",
50
+ "eslint": "^8.28.0",
51
51
  "eslint-config-prettier": "^8.5.0",
52
52
  "eslint-plugin-import": "^2.26.0",
53
53
  "eslint-plugin-prettier": "^4.2.1",