@kravc/dos 2.0.0-alpha.21 → 2.0.0-alpha.23

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.
Files changed (32) hide show
  1. package/.claude/settings.local.json +18 -1
  2. package/.composer/documents/ExampleDocument.yaml +9 -0
  3. package/.composer/enums/ExampleEnum.yaml +5 -0
  4. package/.composer/operations/ExampleDocument/ExampleOperation.yaml +9 -0
  5. package/.composer/parameters/ExampleOperation.yaml +9 -0
  6. package/.composer/scenarios/ExampleScenario.yaml +17 -0
  7. package/.composer/schemas/ExampleSchema.yaml +9 -0
  8. package/dist/Service/test/ensureItem.d.ts.map +1 -1
  9. package/dist/Service/test/ensureItem.js +1 -0
  10. package/dist/Service/test/ensureItem.js.map +1 -1
  11. package/dist/Service/test/ensureNoItem.d.ts.map +1 -1
  12. package/dist/Service/test/ensureNoItem.js +1 -0
  13. package/dist/Service/test/ensureNoItem.js.map +1 -1
  14. package/dist/Service/test/firstItemGet.d.ts.map +1 -1
  15. package/dist/Service/test/firstItemGet.js +1 -0
  16. package/dist/Service/test/firstItemGet.js.map +1 -1
  17. package/dist/Service/useComposerMiddleware.d.ts.map +1 -1
  18. package/dist/Service/useComposerMiddleware.js +27 -20
  19. package/dist/Service/useComposerMiddleware.js.map +1 -1
  20. package/jest.config.mjs +5 -1
  21. package/package.json +5 -4
  22. package/src/Service/__tests__/Service.test.ts +20 -0
  23. package/src/Service/test/ensureItem.ts +1 -0
  24. package/src/Service/test/ensureNoItem.ts +1 -0
  25. package/src/Service/test/firstItemGet.ts +1 -0
  26. package/src/Service/useComposerMiddleware.ts +31 -25
  27. package/.composer/Documents.yaml +0 -1
  28. package/.composer/Enums.yaml +0 -1
  29. package/.composer/Operations.yaml +0 -1
  30. package/.composer/Parameters.yaml +0 -1
  31. package/.composer/Scenarios.yaml +0 -1
  32. package/.composer/Schemas.yaml +0 -1
@@ -1,7 +1,24 @@
1
1
  {
2
2
  "permissions": {
3
3
  "allow": [
4
- "Bash(npx ts-node:*)"
4
+ "Bash(npm outdated:*)",
5
+ "Bash(npm info:*)",
6
+ "Bash(npm pack:*)",
7
+ "Bash(node -e \"const m = require\\(''''/Users/ok/dev/dos/dos/node_modules/read-yaml-file''''\\); console.log\\(Object.keys\\(m\\)\\)\")",
8
+ "Bash(tar -tf read-yaml-file-3.0.0.tgz)",
9
+ "Bash(tar -xOf read-yaml-file-3.0.0.tgz package/index.js)",
10
+ "Bash(rm -f read-yaml-file-3.0.0.tgz)",
11
+ "Bash(tar -xOf z-schema-12.1.1.tgz package/package.json)",
12
+ "Bash(node -e \"const d=JSON.parse\\(require\\(''''fs''''\\).readFileSync\\(''''/dev/stdin'''',''''utf8''''\\)\\); console.log\\(''''type:'''', d.type, ''''main:'''', d.main, ''''exports:'''', JSON.stringify\\(d.exports, null, 2\\)\\)\")",
13
+ "Bash(rm -f z-schema-12.1.1.tgz)",
14
+ "Bash(npm install:*)",
15
+ "Bash(npx tsc:*)",
16
+ "Bash(node -e \"const ZSchema = require\\(''''/Users/ok/dev/dos/dos/node_modules/z-schema''''\\); console.log\\(Object.getOwnPropertyNames\\(ZSchema.prototype\\).join\\(''''\\\\n''''\\)\\)\")",
17
+ "Bash(node:*)",
18
+ "Bash(npx tsc@5.9.3 --noEmit)",
19
+ "Bash(npm test:*)",
20
+ "Bash(npx jest:*)",
21
+ "Bash(npm run:*)"
5
22
  ]
6
23
  }
7
24
  }
@@ -0,0 +1,9 @@
1
+ name: ExampleDocument
2
+ attributes:
3
+ - name: title
4
+ title: Title
5
+ description: Title of the document
6
+ required: true
7
+ type: string
8
+ isEnum: false
9
+ isArray: false
@@ -0,0 +1,5 @@
1
+ name: ExampleEnum
2
+ values:
3
+ - value: ExampleValue
4
+ name: ''
5
+ description: ''
@@ -0,0 +1,9 @@
1
+ operationId: ExampleOperation
2
+ baseAction: Read
3
+ isPublic: true
4
+ isSystem: false
5
+ permissions: []
6
+ summary: Example operation.
7
+ description: Example operation demonstrating the composer operation format.
8
+ query: {}
9
+ mutation: {}
@@ -0,0 +1,9 @@
1
+ operationId: ExampleOperation
2
+ query:
3
+ - name: id
4
+ title: ID
5
+ description: ID of the example resource
6
+ required: true
7
+ type: string
8
+ isEnum: false
9
+ isArray: false
@@ -0,0 +1,17 @@
1
+ code: E1
2
+ title: exampleScenario
3
+ summary: Example scenario demonstrating basic operation flow
4
+ parameters:
5
+ - name: id
6
+ value: EXAMPLE_1
7
+ variableNames:
8
+ - id
9
+ steps:
10
+ - summary: Operation is executed successfully
11
+ role: USER
12
+ operationId: ExampleOperation
13
+ parameters:
14
+ - name: id
15
+ result:
16
+ - has:
17
+ path: id
@@ -0,0 +1,9 @@
1
+ name: ExampleSchema
2
+ attributes:
3
+ - name: id
4
+ title: ID
5
+ description: Unique identifier
6
+ required: true
7
+ type: string
8
+ isEnum: false
9
+ isArray: false
@@ -1 +1 @@
1
- {"version":3,"file":"ensureItem.d.ts","sourceRoot":"","sources":["../../../src/Service/test/ensureItem.ts"],"names":[],"mappings":"AAAA,OAAiB,EAAE,KAAK,KAAK,EAAE,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAE9D,4DAA4D;AAC5D,QAAA,MAAM,UAAU,GAAI,OAAO,KAAK,EAAE,OAAO,KAAK,SAG7C,CAAC;AAEF,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"ensureItem.d.ts","sourceRoot":"","sources":["../../../src/Service/test/ensureItem.ts"],"names":[],"mappings":"AACA,OAAiB,EAAE,KAAK,KAAK,EAAE,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAE9D,4DAA4D;AAC5D,QAAA,MAAM,UAAU,GAAI,OAAO,KAAK,EAAE,OAAO,KAAK,SAG7C,CAAC;AAEF,eAAe,UAAU,CAAC"}
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ /// <reference types="jest" />
6
7
  const findItem_1 = __importDefault(require("./findItem"));
7
8
  /** Ensures item to exists in a list for specified query. */
8
9
  const ensureItem = (items, query) => {
@@ -1 +1 @@
1
- {"version":3,"file":"ensureItem.js","sourceRoot":"","sources":["../../../src/Service/test/ensureItem.ts"],"names":[],"mappings":";;;;;AAAA,0DAA8D;AAE9D,4DAA4D;AAC5D,MAAM,UAAU,GAAG,CAAC,KAAY,EAAE,KAAY,EAAE,EAAE;IAChD,MAAM,IAAI,GAAG,IAAA,kBAAQ,EAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACpC,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;AAC7B,CAAC,CAAC;AAEF,kBAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"ensureItem.js","sourceRoot":"","sources":["../../../src/Service/test/ensureItem.ts"],"names":[],"mappings":";;;;;AAAA,8BAA8B;AAC9B,0DAA8D;AAE9D,4DAA4D;AAC5D,MAAM,UAAU,GAAG,CAAC,KAAY,EAAE,KAAY,EAAE,EAAE;IAChD,MAAM,IAAI,GAAG,IAAA,kBAAQ,EAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACpC,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;AAC7B,CAAC,CAAC;AAEF,kBAAe,UAAU,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ensureNoItem.d.ts","sourceRoot":"","sources":["../../../src/Service/test/ensureNoItem.ts"],"names":[],"mappings":"AAAA,OAAiB,EAAE,KAAK,KAAK,EAAE,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAE9D,iEAAiE;AACjE,QAAA,MAAM,YAAY,GAAI,MAAM,KAAK,EAAE,OAAO,KAAK,SAG9C,CAAC;AAEF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"ensureNoItem.d.ts","sourceRoot":"","sources":["../../../src/Service/test/ensureNoItem.ts"],"names":[],"mappings":"AACA,OAAiB,EAAE,KAAK,KAAK,EAAE,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAE9D,iEAAiE;AACjE,QAAA,MAAM,YAAY,GAAI,MAAM,KAAK,EAAE,OAAO,KAAK,SAG9C,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ /// <reference types="jest" />
6
7
  const findItem_1 = __importDefault(require("./findItem"));
7
8
  /** Ensures item does not exist in a list for specified query. */
8
9
  const ensureNoItem = (data, query) => {
@@ -1 +1 @@
1
- {"version":3,"file":"ensureNoItem.js","sourceRoot":"","sources":["../../../src/Service/test/ensureNoItem.ts"],"names":[],"mappings":";;;;;AAAA,0DAA8D;AAE9D,iEAAiE;AACjE,MAAM,YAAY,GAAG,CAAC,IAAW,EAAE,KAAY,EAAE,EAAE;IACjD,MAAM,IAAI,GAAG,IAAA,kBAAQ,EAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACnC,MAAM,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;AAC/B,CAAC,CAAC;AAEF,kBAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"ensureNoItem.js","sourceRoot":"","sources":["../../../src/Service/test/ensureNoItem.ts"],"names":[],"mappings":";;;;;AAAA,8BAA8B;AAC9B,0DAA8D;AAE9D,iEAAiE;AACjE,MAAM,YAAY,GAAG,CAAC,IAAW,EAAE,KAAY,EAAE,EAAE;IACjD,MAAM,IAAI,GAAG,IAAA,kBAAQ,EAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACnC,MAAM,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;AAC/B,CAAC,CAAC;AAEF,kBAAe,YAAY,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"firstItemGet.d.ts","sourceRoot":"","sources":["../../../src/Service/test/firstItemGet.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,4FAA4F;AAC5F,QAAA,MAAM,YAAY,GAAI,OAAO,KAAK,EAAE,eAAe,MAAM,EAAE,sBAAqB,OAAe,YAU9F,CAAC;AAEF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"firstItemGet.d.ts","sourceRoot":"","sources":["../../../src/Service/test/firstItemGet.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,4FAA4F;AAC5F,QAAA,MAAM,YAAY,GAAI,OAAO,KAAK,EAAE,eAAe,MAAM,EAAE,sBAAqB,OAAe,YAU9F,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ /// <reference types="jest" />
3
4
  const lodash_1 = require("lodash");
4
5
  const schema_1 = require("@kravc/schema");
5
6
  /** Returns value or ensures specified attribute exists for the first item from the list. */
@@ -1 +1 @@
1
- {"version":3,"file":"firstItemGet.js","sourceRoot":"","sources":["../../../src/Service/test/firstItemGet.ts"],"names":[],"mappings":";;AAAA,mCAA6B;AAC7B,0CAAoC;AAGpC,4FAA4F;AAC5F,MAAM,YAAY,GAAG,CAAC,KAAY,EAAE,aAAqB,EAAE,sBAA+B,KAAK,EAAE,EAAE;IACjG,MAAM,CAAE,SAAS,CAAE,GAAG,KAAK,CAAC;IAE5B,IAAI,mBAAmB,EAAE,CAAC;QACxB,OAAO,IAAA,YAAG,EAAC,SAAS,IAAI,EAAE,EAAE,aAAa,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;IAEhC,OAAO,IAAA,YAAG,EAAC,SAAS,EAAE,aAAa,CAAC,CAAC;AACvC,CAAC,CAAC;AAEF,kBAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"firstItemGet.js","sourceRoot":"","sources":["../../../src/Service/test/firstItemGet.ts"],"names":[],"mappings":";;AAAA,8BAA8B;AAC9B,mCAA6B;AAC7B,0CAAoC;AAGpC,4FAA4F;AAC5F,MAAM,YAAY,GAAG,CAAC,KAAY,EAAE,aAAqB,EAAE,sBAA+B,KAAK,EAAE,EAAE;IACjG,MAAM,CAAE,SAAS,CAAE,GAAG,KAAK,CAAC;IAE5B,IAAI,mBAAmB,EAAE,CAAC;QACxB,OAAO,IAAA,YAAG,EAAC,SAAS,IAAI,EAAE,EAAE,aAAa,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;IAEhC,OAAO,IAAA,YAAG,EAAC,SAAS,EAAE,aAAa,CAAC,CAAC;AACvC,CAAC,CAAC;AAEF,kBAAe,YAAY,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useComposerMiddleware.d.ts","sourceRoot":"","sources":["../../src/Service/useComposerMiddleware.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAc1C,8DAA8D;AAC9D,QAAA,MAAM,qBAAqB,GAAI,UAAU,OAAO,EAAE,SAAS,OAAO;;;;;;QAqCjE,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
1
+ {"version":3,"file":"useComposerMiddleware.d.ts","sourceRoot":"","sources":["../../src/Service/useComposerMiddleware.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AA6B1C,8DAA8D;AAC9D,QAAA,MAAM,qBAAqB,GAAI,UAAU,OAAO,EAAE,SAAS,OAAO;;;;;;QA0BjE,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
@@ -1,34 +1,41 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const read_yaml_file_1 = require("read-yaml-file");
3
+ const fs_1 = require("fs");
4
+ const path_1 = require("path");
5
+ const js_yaml_1 = require("js-yaml");
4
6
  const useOasMiddleware_1 = require("./useOasMiddleware");
5
7
  const ROOT_PATH = process.cwd();
6
- const COMPOSER_FILES = [
7
- '/Enums.yaml',
8
- '/Schemas.yaml',
9
- '/Documents.yaml',
10
- '/Scenarios.yaml',
11
- '/Operations.yaml',
12
- '/Parameters.yaml'
13
- ];
8
+ const COMPOSER_DIR_MAP = {
9
+ '/Enums.yaml': 'enums',
10
+ '/Schemas.yaml': 'schemas',
11
+ '/Documents.yaml': 'documents',
12
+ '/Scenarios.yaml': 'scenarios',
13
+ '/Operations.yaml': 'operations',
14
+ '/Parameters.yaml': 'parameters',
15
+ };
16
+ /** Reads all YAML files in a directory and returns their parsed contents as an array. */
17
+ const readYamlDir = (dirPath) => (0, fs_1.readdirSync)(dirPath)
18
+ .filter(entry => entry.endsWith('.yaml') || entry.endsWith('.yml'))
19
+ .map(entry => (0, js_yaml_1.load)((0, fs_1.readFileSync)((0, path_1.join)(dirPath, entry), 'utf8')));
20
+ /** Reads operations directory and returns operations grouped by document (subdirectory name). */
21
+ const readOperationsDir = (dirPath) => (0, fs_1.readdirSync)(dirPath)
22
+ .filter(entry => (0, fs_1.statSync)((0, path_1.join)(dirPath, entry)).isDirectory())
23
+ .map(document => ({
24
+ document,
25
+ operations: readYamlDir((0, path_1.join)(dirPath, document)),
26
+ }));
14
27
  /** Returns result if request is for service composer file. */
15
28
  const useComposerMiddleware = (_service, context) => {
16
29
  const { httpPath, httpMethod, isDevelopment } = context;
17
30
  const isGetRequest = httpMethod === 'get';
18
- /** Returns specified composer source file. */
19
- const readFileJson = (httpPath) => {
20
- const fileName = httpPath.replace('/', '');
21
- const composerSource = (0, read_yaml_file_1.sync)(`${ROOT_PATH}/.composer/${fileName}`);
22
- return JSON.stringify(composerSource, null, 2);
23
- };
24
- const isComposerPath = COMPOSER_FILES.includes(httpPath);
25
- const shouldReturnComposerSource = isDevelopment &&
26
- isGetRequest &&
27
- isComposerPath;
31
+ const composerDir = COMPOSER_DIR_MAP[httpPath];
32
+ const shouldReturnComposerSource = isDevelopment && isGetRequest && !!composerDir;
28
33
  if (!shouldReturnComposerSource) {
29
34
  return null;
30
35
  }
31
- const bodyJson = readFileJson(httpPath);
36
+ const dirPath = (0, path_1.join)(ROOT_PATH, '.composer', composerDir);
37
+ const data = httpPath === '/Operations.yaml' ? readOperationsDir(dirPath) : readYamlDir(dirPath);
38
+ const bodyJson = JSON.stringify(data, null, 2);
32
39
  return {
33
40
  headers: {
34
41
  'Content-Type': useOasMiddleware_1.JSON_TYPE
@@ -1 +1 @@
1
- {"version":3,"file":"useComposerMiddleware.js","sourceRoot":"","sources":["../../src/Service/useComposerMiddleware.ts"],"names":[],"mappings":";;AAAA,mDAAsC;AAEtC,yDAA0D;AAE1D,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;AAEhC,MAAM,cAAc,GAAG;IACrB,aAAa;IACb,eAAe;IACf,iBAAiB;IACjB,iBAAiB;IACjB,kBAAkB;IAClB,kBAAkB;CACnB,CAAC;AAEF,8DAA8D;AAC9D,MAAM,qBAAqB,GAAG,CAAC,QAAiB,EAAE,OAAgB,EAAE,EAAE;IACpE,MAAM,EACJ,QAAQ,EACR,UAAU,EACV,aAAa,EACd,GAAG,OAAO,CAAC;IAEZ,MAAM,YAAY,GAAG,UAAU,KAAK,KAAK,CAAC;IAE1C,8CAA8C;IAC9C,MAAM,YAAY,GAAG,CAAC,QAAgB,EAAE,EAAE;QACxC,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAC3C,MAAM,cAAc,GAAG,IAAA,qBAAI,EAAC,GAAG,SAAS,cAAc,QAAQ,EAAE,CAAC,CAAC;QAElE,OAAO,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,cAAc,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAEzD,MAAM,0BAA0B,GAC9B,aAAa;QACb,YAAY;QACZ,cAAc,CAAC;IAEjB,IAAI,CAAC,0BAA0B,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IAExC,OAAO;QACL,OAAO,EAAE;YACP,cAAc,EAAE,4BAAS;SAC1B;QACD,UAAU,EAAE,4BAAS;QACrB,IAAI,EAAE,QAAQ;KACf,CAAC;AACJ,CAAC,CAAC;AAEF,kBAAe,qBAAqB,CAAC"}
1
+ {"version":3,"file":"useComposerMiddleware.js","sourceRoot":"","sources":["../../src/Service/useComposerMiddleware.ts"],"names":[],"mappings":";;AAAA,2BAAyD;AACzD,+BAA4B;AAC5B,qCAA+B;AAE/B,yDAA0D;AAE1D,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;AAEhC,MAAM,gBAAgB,GAA2B;IAC/C,aAAa,EAAE,OAAO;IACtB,eAAe,EAAE,SAAS;IAC1B,iBAAiB,EAAE,WAAW;IAC9B,iBAAiB,EAAE,WAAW;IAC9B,kBAAkB,EAAE,YAAY;IAChC,kBAAkB,EAAE,YAAY;CACjC,CAAC;AAEF,yFAAyF;AACzF,MAAM,WAAW,GAAG,CAAC,OAAe,EAAa,EAAE,CACjD,IAAA,gBAAW,EAAC,OAAO,CAAC;KACjB,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;KAClE,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAA,cAAI,EAAC,IAAA,iBAAY,EAAC,IAAA,WAAI,EAAC,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;AAEpE,iGAAiG;AACjG,MAAM,iBAAiB,GAAG,CAAC,OAAe,EAAa,EAAE,CACvD,IAAA,gBAAW,EAAC,OAAO,CAAC;KACjB,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,IAAA,aAAQ,EAAC,IAAA,WAAI,EAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;KAC7D,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAChB,QAAQ;IACR,UAAU,EAAE,WAAW,CAAC,IAAA,WAAI,EAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;CACjD,CAAC,CAAC,CAAC;AAER,8DAA8D;AAC9D,MAAM,qBAAqB,GAAG,CAAC,QAAiB,EAAE,OAAgB,EAAE,EAAE;IACpE,MAAM,EACJ,QAAQ,EACR,UAAU,EACV,aAAa,EACd,GAAG,OAAO,CAAC;IAEZ,MAAM,YAAY,GAAG,UAAU,KAAK,KAAK,CAAC;IAC1C,MAAM,WAAW,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC/C,MAAM,0BAA0B,GAAG,aAAa,IAAI,YAAY,IAAI,CAAC,CAAC,WAAW,CAAC;IAElF,IAAI,CAAC,0BAA0B,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,OAAO,GAAG,IAAA,WAAI,EAAC,SAAS,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;IAC1D,MAAM,IAAI,GAAG,QAAQ,KAAK,kBAAkB,CAAC,CAAC,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACjG,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAE/C,OAAO;QACL,OAAO,EAAE;YACP,cAAc,EAAE,4BAAS;SAC1B;QACD,UAAU,EAAE,4BAAS;QACrB,IAAI,EAAE,QAAQ;KACf,CAAC;AACJ,CAAC,CAAC;AAEF,kBAAe,qBAAqB,CAAC"}
package/jest.config.mjs CHANGED
@@ -3,5 +3,9 @@ export default {
3
3
  preset: 'ts-jest',
4
4
  testMatch: ['<rootDir>/src/**/*.test.ts'],
5
5
  maxWorkers: 1,
6
- collectCoverageFrom: ['<rootDir>/src/**/*.ts'],
6
+ collectCoverageFrom: [
7
+ '<rootDir>/src/**/*.ts',
8
+ '!<rootDir>/src/**/index.ts',
9
+ '!<rootDir>/src/**/*.d.ts',
10
+ ],
7
11
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kravc/dos",
3
- "version": "2.0.0-alpha.21",
3
+ "version": "2.0.0-alpha.23",
4
4
  "description": "Convention-based, easy-to-use library for building API-driven serverless services.",
5
5
  "keywords": [
6
6
  "Service",
@@ -35,13 +35,13 @@
35
35
  "author": "Oleksandr Kravets <a@kra.vc>",
36
36
  "license": "ISC",
37
37
  "dependencies": {
38
- "@kravc/schema": "^2.8.0",
38
+ "@kravc/schema": "^2.8.3",
39
39
  "@types/jsonwebtoken": "^9.0.10",
40
40
  "cookie": "^1.1.1",
41
+ "js-yaml": "^4.1.1",
41
42
  "jsonwebtoken": "^9.0.3",
42
43
  "lodash": "^4.17.23",
43
44
  "pluralize": "^8.0.0",
44
- "read-yaml-file": "^2.1.0",
45
45
  "safe-stable-stringify": "^2.5.0",
46
46
  "ulid": "^3.0.2",
47
47
  "z-schema": "^6.0.2"
@@ -50,6 +50,7 @@
50
50
  "@eslint/js": "^10.0.1",
51
51
  "@kravc/http": "^0.5.0",
52
52
  "@types/jest": "^30.0.0",
53
+ "@types/js-yaml": "^4.0.9",
53
54
  "@types/lodash": "^4.17.23",
54
55
  "@types/pluralize": "^0.0.33",
55
56
  "eslint": "^10.0.1",
@@ -60,7 +61,7 @@
60
61
  "rimraf": "^6.1.3",
61
62
  "ts-jest": "^29.4.6",
62
63
  "ts-node": "^10.9.2",
63
- "typescript": "^5.9.3",
64
+ "typescript": "^6.0.2",
64
65
  "typescript-eslint": "^8.56.0"
65
66
  }
66
67
  }
@@ -192,6 +192,26 @@ describe('Service', () => {
192
192
  expect(statusCode).toEqual(200);
193
193
  });
194
194
 
195
+ it('returns operations grouped by document for /Operations.yaml path', async () => {
196
+ const request = {
197
+ path: '/Operations.yaml',
198
+ method: 'get'
199
+ } as HttpRequest;
200
+
201
+ const { statusCode, body } = await service.process(request);
202
+
203
+ expect(statusCode).toEqual(200);
204
+
205
+ const data = JSON.parse(body!);
206
+
207
+ expect(data).toEqual(expect.arrayContaining([
208
+ expect.objectContaining({
209
+ document: expect.any(String),
210
+ operations: expect.any(Array),
211
+ }),
212
+ ]));
213
+ });
214
+
195
215
  it('supports operations without parameters', async () => {
196
216
  const request = {
197
217
  path: '/Health',
@@ -1,3 +1,4 @@
1
+ /// <reference types="jest" />
1
2
  import findItem, { type Items, type Query } from './findItem';
2
3
 
3
4
  /** Ensures item to exists in a list for specified query. */
@@ -1,3 +1,4 @@
1
+ /// <reference types="jest" />
1
2
  import findItem, { type Items, type Query } from './findItem';
2
3
 
3
4
  /** Ensures item does not exist in a list for specified query. */
@@ -1,3 +1,4 @@
1
+ /// <reference types="jest" />
1
2
  import { get } from 'lodash';
2
3
  import { got } from '@kravc/schema';
3
4
  import { type Items } from './findItem';
@@ -1,17 +1,34 @@
1
- import { sync } from 'read-yaml-file';
1
+ import { readFileSync, readdirSync, statSync } from 'fs';
2
+ import { join } from 'path';
3
+ import { load } from 'js-yaml';
2
4
  import type { Context } from '../Context';
3
5
  import { OK_STATUS, JSON_TYPE } from './useOasMiddleware';
4
6
 
5
7
  const ROOT_PATH = process.cwd();
6
8
 
7
- const COMPOSER_FILES = [
8
- '/Enums.yaml',
9
- '/Schemas.yaml',
10
- '/Documents.yaml',
11
- '/Scenarios.yaml',
12
- '/Operations.yaml',
13
- '/Parameters.yaml'
14
- ];
9
+ const COMPOSER_DIR_MAP: Record<string, string> = {
10
+ '/Enums.yaml': 'enums',
11
+ '/Schemas.yaml': 'schemas',
12
+ '/Documents.yaml': 'documents',
13
+ '/Scenarios.yaml': 'scenarios',
14
+ '/Operations.yaml': 'operations',
15
+ '/Parameters.yaml': 'parameters',
16
+ };
17
+
18
+ /** Reads all YAML files in a directory and returns their parsed contents as an array. */
19
+ const readYamlDir = (dirPath: string): unknown[] =>
20
+ readdirSync(dirPath)
21
+ .filter(entry => entry.endsWith('.yaml') || entry.endsWith('.yml'))
22
+ .map(entry => load(readFileSync(join(dirPath, entry), 'utf8')));
23
+
24
+ /** Reads operations directory and returns operations grouped by document (subdirectory name). */
25
+ const readOperationsDir = (dirPath: string): unknown[] =>
26
+ readdirSync(dirPath)
27
+ .filter(entry => statSync(join(dirPath, entry)).isDirectory())
28
+ .map(document => ({
29
+ document,
30
+ operations: readYamlDir(join(dirPath, document)),
31
+ }));
15
32
 
16
33
  /** Returns result if request is for service composer file. */
17
34
  const useComposerMiddleware = (_service: unknown, context: Context) => {
@@ -22,27 +39,16 @@ const useComposerMiddleware = (_service: unknown, context: Context) => {
22
39
  } = context;
23
40
 
24
41
  const isGetRequest = httpMethod === 'get';
25
-
26
- /** Returns specified composer source file. */
27
- const readFileJson = (httpPath: string) => {
28
- const fileName = httpPath.replace('/', '');
29
- const composerSource = sync(`${ROOT_PATH}/.composer/${fileName}`);
30
-
31
- return JSON.stringify(composerSource, null, 2);
32
- };
33
-
34
- const isComposerPath = COMPOSER_FILES.includes(httpPath);
35
-
36
- const shouldReturnComposerSource =
37
- isDevelopment &&
38
- isGetRequest &&
39
- isComposerPath;
42
+ const composerDir = COMPOSER_DIR_MAP[httpPath];
43
+ const shouldReturnComposerSource = isDevelopment && isGetRequest && !!composerDir;
40
44
 
41
45
  if (!shouldReturnComposerSource) {
42
46
  return null;
43
47
  }
44
48
 
45
- const bodyJson = readFileJson(httpPath);
49
+ const dirPath = join(ROOT_PATH, '.composer', composerDir);
50
+ const data = httpPath === '/Operations.yaml' ? readOperationsDir(dirPath) : readYamlDir(dirPath);
51
+ const bodyJson = JSON.stringify(data, null, 2);
46
52
 
47
53
  return {
48
54
  headers: {
@@ -1 +0,0 @@
1
- []
@@ -1 +0,0 @@
1
- []
@@ -1 +0,0 @@
1
- []
@@ -1 +0,0 @@
1
- []
@@ -1 +0,0 @@
1
- []
@@ -1 +0,0 @@
1
- []