@noego/stitch 1.0.0
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-schema.md +139 -0
- package/bin/stitch.js +156 -0
- package/dist/browser/index.d.ts +4 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/cli/StitchCLI.d.ts +12 -0
- package/dist/cli/StitchCLI.d.ts.map +1 -0
- package/dist/client.cjs +2 -0
- package/dist/client.cjs.map +1 -0
- package/dist/client.mjs +83 -0
- package/dist/client.mjs.map +1 -0
- package/dist/core/ConfigParser.d.ts +16 -0
- package/dist/core/ConfigParser.d.ts.map +1 -0
- package/dist/core/StitchEngine.d.ts +31 -0
- package/dist/core/StitchEngine.d.ts.map +1 -0
- package/dist/core/Validator.d.ts +18 -0
- package/dist/core/Validator.d.ts.map +1 -0
- package/dist/core/ViteHelper.d.ts +33 -0
- package/dist/core/ViteHelper.d.ts.map +1 -0
- package/dist/core/YamlMerger.d.ts +29 -0
- package/dist/core/YamlMerger.d.ts.map +1 -0
- package/dist/core/YamlMergerBrowser.d.ts +18 -0
- package/dist/core/YamlMergerBrowser.d.ts.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/types/StitchTypes.d.ts +38 -0
- package/dist/types/StitchTypes.d.ts.map +1 -0
- package/dist-ssr/browser/index.d.ts +4 -0
- package/dist-ssr/browser/index.d.ts.map +1 -0
- package/dist-ssr/cli/StitchCLI.d.ts +12 -0
- package/dist-ssr/cli/StitchCLI.d.ts.map +1 -0
- package/dist-ssr/core/ConfigParser.d.ts +16 -0
- package/dist-ssr/core/ConfigParser.d.ts.map +1 -0
- package/dist-ssr/core/StitchEngine.d.ts +31 -0
- package/dist-ssr/core/StitchEngine.d.ts.map +1 -0
- package/dist-ssr/core/Validator.d.ts +18 -0
- package/dist-ssr/core/Validator.d.ts.map +1 -0
- package/dist-ssr/core/ViteHelper.d.ts +33 -0
- package/dist-ssr/core/ViteHelper.d.ts.map +1 -0
- package/dist-ssr/core/YamlMerger.d.ts +29 -0
- package/dist-ssr/core/YamlMerger.d.ts.map +1 -0
- package/dist-ssr/core/YamlMergerBrowser.d.ts +18 -0
- package/dist-ssr/core/YamlMergerBrowser.d.ts.map +1 -0
- package/dist-ssr/index.d.ts +15 -0
- package/dist-ssr/index.d.ts.map +1 -0
- package/dist-ssr/server.cjs +574 -0
- package/dist-ssr/server.cjs.map +1 -0
- package/dist-ssr/server.d.ts +2 -0
- package/dist-ssr/server.js +554 -0
- package/dist-ssr/server.js.map +1 -0
- package/dist-ssr/types/StitchTypes.d.ts +38 -0
- package/dist-ssr/types/StitchTypes.d.ts.map +1 -0
- package/docs/advanced_validation.md +188 -0
- package/docs/middleware.md +507 -0
- package/docs/modules.md +175 -0
- package/docs/project.md +856 -0
- package/docs/validation.md +77 -0
- package/package.json +67 -0
- package/readme.md +159 -0
- package/schemas/schema.json +360 -0
- package/schemas/stitch-schema.json +38 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Request Validation in This OpenAPI Server
|
|
2
|
+
|
|
3
|
+
This project uses **Fastify** as the underlying web server, plus an **OpenAPI-driven** approach to routes and validation. Here’s how it works:
|
|
4
|
+
|
|
5
|
+
1. **OpenAPI Document**
|
|
6
|
+
You define your endpoints, request/response schemas, etc. in `example/openapi.yaml`. For example:
|
|
7
|
+
|
|
8
|
+
```yaml
|
|
9
|
+
paths:
|
|
10
|
+
/user/create:
|
|
11
|
+
post:
|
|
12
|
+
x-controller: user.controller
|
|
13
|
+
x-action: create
|
|
14
|
+
summary: Create a new User
|
|
15
|
+
requestBody:
|
|
16
|
+
required: true
|
|
17
|
+
content:
|
|
18
|
+
application/json:
|
|
19
|
+
schema:
|
|
20
|
+
$ref: '#/components/schemas/NewUser'
|
|
21
|
+
responses:
|
|
22
|
+
'200':
|
|
23
|
+
description: Success
|
|
24
|
+
components:
|
|
25
|
+
schemas:
|
|
26
|
+
NewUser:
|
|
27
|
+
type: object
|
|
28
|
+
required:
|
|
29
|
+
- email
|
|
30
|
+
- password
|
|
31
|
+
properties:
|
|
32
|
+
email:
|
|
33
|
+
type: string
|
|
34
|
+
format: email
|
|
35
|
+
password:
|
|
36
|
+
type: string
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
2. **Route Generation**
|
|
40
|
+
- Our framework loads your `openapi.yaml` using the [`OpenAPIParser`](./framework/openapi/parser.ts).
|
|
41
|
+
- The [`FastifyServerImplentation.createRoutes()`](./framework/fastify/FastifyServerImplentation.ts) method reads each path’s schema and automatically sets up Fastify routes with a `schema` property that represents your request params, query, and body definitions.
|
|
42
|
+
- Fastify’s built-in validation uses [Ajv](https://ajv.js.org/) behind the scenes to validate inbound requests against those schemas.
|
|
43
|
+
|
|
44
|
+
3. **Validation Pipeline**
|
|
45
|
+
- When a client sends a request to `/user/create`, Fastify matches it to the route defined in `openapi.yaml`.
|
|
46
|
+
- Fastify checks if any `parameters` (for path/query) or `requestBody` data are provided in the correct shape.
|
|
47
|
+
- If the data doesn’t match the schema, **Fastify** automatically returns an error (e.g. `400`).
|
|
48
|
+
- If it’s valid, the request proceeds to your controller method (like `UserController.create`).
|
|
49
|
+
|
|
50
|
+
4. **Schema Inference**
|
|
51
|
+
- For `requestBody`, the schema is taken from `requestBody.content['application/json'].schema`.
|
|
52
|
+
- For path or query parameters, the schema is taken from `parameters[].schema` in `openapi.yaml`.
|
|
53
|
+
- You can also define response schemas if you want response validation.
|
|
54
|
+
|
|
55
|
+
5. **Example**
|
|
56
|
+
Let’s look at the `NewUser` schema. It declares `email` as a string with an email format, and `password` as required. If a request is missing those, you’ll get an error like:
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"statusCode": 400,
|
|
61
|
+
"error": "Bad Request",
|
|
62
|
+
"message": "body must have required property 'password'"
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
6. **No Extra Controller Code Needed**
|
|
67
|
+
- Since Fastify handles validation, your controllers only receive valid data.
|
|
68
|
+
- If the request is invalid, the request never reaches your controller logic.
|
|
69
|
+
|
|
70
|
+
7. **Where to Edit Schemas**
|
|
71
|
+
- Any time you need to change request/response shapes, update `example/openapi.yaml`.
|
|
72
|
+
- The changes automatically reflect in the generated routes and validation rules.
|
|
73
|
+
|
|
74
|
+
8. **Advanced Validation**
|
|
75
|
+
- If you need custom rules that aren’t possible in JSON Schema, you can add a [Fastify or Ajv plugin](https://www.fastify.io/docs/latest/Reference/Validation-and-Serialization/#adding-new-keywords).
|
|
76
|
+
- But generally, the base JSON Schema approach covers most cases.
|
|
77
|
+
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@noego/stitch",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"license": "ISC",
|
|
6
|
+
"author": "",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./dist-ssr/server.cjs",
|
|
9
|
+
"module": "./dist-ssr/server.js",
|
|
10
|
+
"bin": {
|
|
11
|
+
"stitch": "./bin/stitch.js"
|
|
12
|
+
},
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist-ssr/server.d.ts",
|
|
16
|
+
"import": "./dist-ssr/server.js",
|
|
17
|
+
"require": "./dist-ssr/server.cjs",
|
|
18
|
+
"default": "./dist-ssr/server.js"
|
|
19
|
+
},
|
|
20
|
+
"./browser": {
|
|
21
|
+
"types": "./dist/browser/index.d.ts",
|
|
22
|
+
"import": "./dist/client.mjs",
|
|
23
|
+
"require": "./dist/client.cjs",
|
|
24
|
+
"default": "./dist/client.mjs"
|
|
25
|
+
},
|
|
26
|
+
"./server": {
|
|
27
|
+
"types": "./dist-ssr/server.d.ts",
|
|
28
|
+
"import": "./dist-ssr/server.js",
|
|
29
|
+
"require": "./dist-ssr/server.cjs",
|
|
30
|
+
"default": "./dist-ssr/server.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build:client": "vite build --config vite.config.js",
|
|
35
|
+
"build:ssr": "SSR=true vite build --ssr",
|
|
36
|
+
"build": "npm run build:client && npm run build:ssr",
|
|
37
|
+
"prepublishOnly": "npm run build",
|
|
38
|
+
"dev": "tsx cli.ts dev",
|
|
39
|
+
"start": "tsx cli.ts run",
|
|
40
|
+
"test": "jest",
|
|
41
|
+
"test:watch": "jest --watch"
|
|
42
|
+
},
|
|
43
|
+
"types": "./dist-ssr/server.d.ts",
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"ajv": "^8.17.1",
|
|
46
|
+
"ajv-formats": "^3.0.1",
|
|
47
|
+
"chokidar": "^3.5.3",
|
|
48
|
+
"glob": "^10.3.10",
|
|
49
|
+
"js-yaml": "^4.1.0",
|
|
50
|
+
"minimist": "^1.2.8"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@types/glob": "^8.1.0",
|
|
54
|
+
"@types/jest": "^29.5.12",
|
|
55
|
+
"@types/js-yaml": "^4.0.9",
|
|
56
|
+
"@types/minimist": "^1.2.5",
|
|
57
|
+
"@types/node": "^20.11.25",
|
|
58
|
+
"jest": "^29.7.0",
|
|
59
|
+
"source-map-support": "^0.5.21",
|
|
60
|
+
"ts-jest": "^29.2.5",
|
|
61
|
+
"ts-node": "^10.9.2",
|
|
62
|
+
"tsx": "^4.19.4",
|
|
63
|
+
"typescript": "^5.8.3",
|
|
64
|
+
"vite": "^6.3.5",
|
|
65
|
+
"vite-plugin-dts": "^4.5.4"
|
|
66
|
+
}
|
|
67
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Stitch — Modular YAML Merging and Validation
|
|
2
|
+
|
|
3
|
+
Stitch merges multiple YAML files into a single, validated artifact. It’s ideal for modular OpenAPI specs and other structured YAML, with CLI, Node, and browser support — plus VSCode schema integration for real‑time validation.
|
|
4
|
+
|
|
5
|
+
## Why Stitch
|
|
6
|
+
|
|
7
|
+
- Modularize YAML: Keep specs split across files and folders without losing clarity.
|
|
8
|
+
- Validate output: Use JSON Schema (AJV) or basic structure checks.
|
|
9
|
+
- Watch and rebuild: Fast dev feedback when files change.
|
|
10
|
+
- Run anywhere: Same engine for CLI, Node, and browser (Vite).
|
|
11
|
+
- IDE assistance: Auto‑configure VSCode to validate YAML as you type.
|
|
12
|
+
|
|
13
|
+
## Key Capabilities
|
|
14
|
+
|
|
15
|
+
- Merge: Ordered deep‑merge of YAML files and globs; later files override earlier keys.
|
|
16
|
+
- Validate: AJV JSON Schema or basic OpenAPI structure checks.
|
|
17
|
+
- Output: YAML or JSON to stdout or file (with generated‑file headers when writing files).
|
|
18
|
+
- Watch: Rebuild on changes with chokidar.
|
|
19
|
+
- VSCode: Install yaml.schemas mapping into `.vscode/settings.json`.
|
|
20
|
+
- Browser: Merge content via `import.meta.glob` or raw strings (Vite).
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
### CLI
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
stitch [command] [input-file] [options]
|
|
28
|
+
|
|
29
|
+
# Build and print to stdout (defaults to stitch.yaml)
|
|
30
|
+
stitch build
|
|
31
|
+
|
|
32
|
+
# Build specific config
|
|
33
|
+
stitch build my-config.yaml
|
|
34
|
+
|
|
35
|
+
# Output to a file (adds generated-file header)
|
|
36
|
+
stitch build --output dist/openapi.yaml
|
|
37
|
+
|
|
38
|
+
# Output JSON instead of YAML
|
|
39
|
+
stitch build --format json
|
|
40
|
+
|
|
41
|
+
# Validate (basic) or with a schema
|
|
42
|
+
stitch build --validate
|
|
43
|
+
stitch build --validate schemas/schema.json
|
|
44
|
+
|
|
45
|
+
# Watch for changes and rebuild
|
|
46
|
+
stitch watch --validate schemas/schema.json
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Options
|
|
50
|
+
- `--output <file>`: write to a file instead of stdout
|
|
51
|
+
- `--format <json|yaml>`: output format (default: yaml)
|
|
52
|
+
- `--validate [schema]`: basic validation or path to JSON Schema
|
|
53
|
+
- `--quiet`: build/validate but don’t print content
|
|
54
|
+
|
|
55
|
+
### Programmatic (Node)
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import { stitch, StitchEngine } from 'stitch';
|
|
59
|
+
|
|
60
|
+
// Convenience API
|
|
61
|
+
await stitch.build({
|
|
62
|
+
input: 'stitch.yaml',
|
|
63
|
+
output: 'dist/openapi.yaml',
|
|
64
|
+
format: 'yaml',
|
|
65
|
+
validate: 'schemas/schema.json',
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Direct engine usage
|
|
69
|
+
const engine = new StitchEngine();
|
|
70
|
+
const result = engine.buildSync('stitch.yaml', { format: 'json' });
|
|
71
|
+
await engine.watch('stitch.yaml', { validate: true });
|
|
72
|
+
|
|
73
|
+
// VSCode schema installation
|
|
74
|
+
engine.install({
|
|
75
|
+
schemaPath: 'schemas/schema.json',
|
|
76
|
+
targets: ['*.yaml', 'openapi/*.yaml'],
|
|
77
|
+
vscodeSettingsPath: '.vscode/settings.json',
|
|
78
|
+
});
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Browser / Vite
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
import { stitchFromViteImports, stitchFromContent } from 'stitch/browser';
|
|
85
|
+
|
|
86
|
+
// Vite import.meta.glob integration
|
|
87
|
+
const imports = import.meta.glob('./openapi/*.yaml', { as: 'raw' });
|
|
88
|
+
const merged = await stitchFromViteImports(imports);
|
|
89
|
+
|
|
90
|
+
// Direct content merging
|
|
91
|
+
const result = stitchFromContent([
|
|
92
|
+
{ content: baseYaml, name: 'base.yaml' },
|
|
93
|
+
{ content: pathsYaml, name: 'paths.yaml' },
|
|
94
|
+
]);
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Merge Rules
|
|
98
|
+
|
|
99
|
+
- Objects: deep‑merge — later files override keys.
|
|
100
|
+
- Arrays: later arrays replace earlier arrays (no concatenation).
|
|
101
|
+
- Primitives: later values replace earlier values.
|
|
102
|
+
|
|
103
|
+
## Validation
|
|
104
|
+
|
|
105
|
+
- Basic: `--validate` enables lightweight OpenAPI shape checks (`openapi`, `info`).
|
|
106
|
+
- JSON Schema: `--validate schemas/schema.json` enables full AJV validation against your schema.
|
|
107
|
+
|
|
108
|
+
## VSCode Integration
|
|
109
|
+
|
|
110
|
+
Install a JSON Schema mapping so VSCode validates YAML in real‑time:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
stitch install schemas/schema.json --target "**/*.yaml"
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Manual configuration example (`.vscode/settings.json`):
|
|
117
|
+
|
|
118
|
+
```json
|
|
119
|
+
{
|
|
120
|
+
"yaml.schemas": {
|
|
121
|
+
"./schemas/schema.json": ["**/*.yaml"]
|
|
122
|
+
},
|
|
123
|
+
"yaml.validate": true
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Alternative paths
|
|
128
|
+
- "@noego/forge/schema.json" – Package export (if supported by VSCode)
|
|
129
|
+
- "node_modules/@noego/forge/schema.json" – Direct node_modules path (most reliable)
|
|
130
|
+
|
|
131
|
+
## Example Project Structure
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
project/
|
|
135
|
+
├── stitch.yaml
|
|
136
|
+
├── openapi/
|
|
137
|
+
│ ├── base.yaml
|
|
138
|
+
│ ├── paths/
|
|
139
|
+
│ │ ├── users.yaml
|
|
140
|
+
│ │ └── posts.yaml
|
|
141
|
+
│ └── components/
|
|
142
|
+
│ └── schemas/
|
|
143
|
+
└── schemas/
|
|
144
|
+
└── schema.json
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Framework Integrations (Optional)
|
|
148
|
+
|
|
149
|
+
If you use framework‑specific schemas, you can install them too:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
stitch install @noego/forge/schema.json --target "openapi/*.yaml"
|
|
153
|
+
stitch install @noego/dinner/schema.json --target "**/*.yaml"
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## License
|
|
157
|
+
|
|
158
|
+
MIT
|
|
159
|
+
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"title": "Dinner Framework OpenAPI Schema",
|
|
4
|
+
"description": "JSON Schema for OpenAPI 3.0.3 specification with Dinner framework extensions",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": [],
|
|
7
|
+
"properties": {
|
|
8
|
+
"openapi": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"pattern": "^3\\.0\\.[0-9]+(\\.[0-9]+)*$",
|
|
11
|
+
"description": "The OpenAPI specification version"
|
|
12
|
+
},
|
|
13
|
+
"info": {
|
|
14
|
+
"type": "object",
|
|
15
|
+
"required": ["title", "version"],
|
|
16
|
+
"properties": {
|
|
17
|
+
"title": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"description": "The title of the API"
|
|
20
|
+
},
|
|
21
|
+
"version": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"description": "The version of the API"
|
|
24
|
+
},
|
|
25
|
+
"description": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"description": "A description of the API"
|
|
28
|
+
},
|
|
29
|
+
"contact": {
|
|
30
|
+
"type": "object",
|
|
31
|
+
"properties": {
|
|
32
|
+
"name": { "type": "string" },
|
|
33
|
+
"url": { "type": "string" },
|
|
34
|
+
"email": { "type": "string" }
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"license": {
|
|
38
|
+
"type": "object",
|
|
39
|
+
"required": ["name"],
|
|
40
|
+
"properties": {
|
|
41
|
+
"name": { "type": "string" },
|
|
42
|
+
"url": { "type": "string" }
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"servers": {
|
|
48
|
+
"type": "array",
|
|
49
|
+
"items": {
|
|
50
|
+
"type": "object",
|
|
51
|
+
"required": ["url"],
|
|
52
|
+
"properties": {
|
|
53
|
+
"url": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"description": "A URL to the target host"
|
|
56
|
+
},
|
|
57
|
+
"description": {
|
|
58
|
+
"type": "string",
|
|
59
|
+
"description": "An optional string describing the host"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"paths": {
|
|
65
|
+
"type": "object",
|
|
66
|
+
"patternProperties": {
|
|
67
|
+
"^/": {
|
|
68
|
+
"type": "object",
|
|
69
|
+
"properties": {
|
|
70
|
+
"get": { "$ref": "#/definitions/operation" },
|
|
71
|
+
"post": { "$ref": "#/definitions/operation" },
|
|
72
|
+
"put": { "$ref": "#/definitions/operation" },
|
|
73
|
+
"delete": { "$ref": "#/definitions/operation" },
|
|
74
|
+
"patch": { "$ref": "#/definitions/operation" },
|
|
75
|
+
"head": { "$ref": "#/definitions/operation" },
|
|
76
|
+
"options": { "$ref": "#/definitions/operation" },
|
|
77
|
+
"trace": { "$ref": "#/definitions/operation" },
|
|
78
|
+
"parameters": {
|
|
79
|
+
"type": "array",
|
|
80
|
+
"items": { "$ref": "#/definitions/parameter" }
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
"additionalProperties": false
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"additionalProperties": false
|
|
87
|
+
},
|
|
88
|
+
"module": {
|
|
89
|
+
"type": "object",
|
|
90
|
+
"description": "Dinner framework: Module definitions with base paths and sub-paths",
|
|
91
|
+
"patternProperties": {
|
|
92
|
+
"^[a-zA-Z0-9_-]+$": {
|
|
93
|
+
"type": "object",
|
|
94
|
+
"required": ["basePath", "paths"],
|
|
95
|
+
"properties": {
|
|
96
|
+
"basePath": {
|
|
97
|
+
"type": "string",
|
|
98
|
+
"pattern": "^/",
|
|
99
|
+
"description": "Base path for all routes in this module"
|
|
100
|
+
},
|
|
101
|
+
"paths": {
|
|
102
|
+
"type": "object",
|
|
103
|
+
"patternProperties": {
|
|
104
|
+
"^/": {
|
|
105
|
+
"type": "object",
|
|
106
|
+
"properties": {
|
|
107
|
+
"get": { "$ref": "#/definitions/operation" },
|
|
108
|
+
"post": { "$ref": "#/definitions/operation" },
|
|
109
|
+
"put": { "$ref": "#/definitions/operation" },
|
|
110
|
+
"delete": { "$ref": "#/definitions/operation" },
|
|
111
|
+
"patch": { "$ref": "#/definitions/operation" },
|
|
112
|
+
"head": { "$ref": "#/definitions/operation" },
|
|
113
|
+
"options": { "$ref": "#/definitions/operation" },
|
|
114
|
+
"trace": { "$ref": "#/definitions/operation" },
|
|
115
|
+
"parameters": {
|
|
116
|
+
"type": "array",
|
|
117
|
+
"items": { "$ref": "#/definitions/parameter" }
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
"additionalProperties": false
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
"additionalProperties": false
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
"additionalProperties": false
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
"additionalProperties": false
|
|
130
|
+
},
|
|
131
|
+
"components": {
|
|
132
|
+
"type": "object",
|
|
133
|
+
"properties": {
|
|
134
|
+
"schemas": {
|
|
135
|
+
"type": "object",
|
|
136
|
+
"patternProperties": {
|
|
137
|
+
"^[a-zA-Z0-9\\.\\-_]+$": {
|
|
138
|
+
"$ref": "#/definitions/schema"
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
"responses": {
|
|
143
|
+
"type": "object",
|
|
144
|
+
"patternProperties": {
|
|
145
|
+
"^[a-zA-Z0-9\\.\\-_]+$": {
|
|
146
|
+
"$ref": "#/definitions/response"
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
"parameters": {
|
|
151
|
+
"type": "object",
|
|
152
|
+
"patternProperties": {
|
|
153
|
+
"^[a-zA-Z0-9\\.\\-_]+$": {
|
|
154
|
+
"$ref": "#/definitions/parameter"
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
"securitySchemes": {
|
|
159
|
+
"type": "object",
|
|
160
|
+
"patternProperties": {
|
|
161
|
+
"^[a-zA-Z0-9\\.\\-_]+$": {
|
|
162
|
+
"$ref": "#/definitions/securityScheme"
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
"security": {
|
|
169
|
+
"type": "array",
|
|
170
|
+
"items": {
|
|
171
|
+
"type": "object"
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
"tags": {
|
|
175
|
+
"type": "array",
|
|
176
|
+
"items": {
|
|
177
|
+
"type": "object",
|
|
178
|
+
"required": ["name"],
|
|
179
|
+
"properties": {
|
|
180
|
+
"name": { "type": "string" },
|
|
181
|
+
"description": { "type": "string" }
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
"definitions": {
|
|
187
|
+
"operation": {
|
|
188
|
+
"type": "object",
|
|
189
|
+
"required": ["x-controller", "x-action"],
|
|
190
|
+
"properties": {
|
|
191
|
+
"summary": {
|
|
192
|
+
"type": "string",
|
|
193
|
+
"description": "A brief summary of what the operation does"
|
|
194
|
+
},
|
|
195
|
+
"description": {
|
|
196
|
+
"type": "string",
|
|
197
|
+
"description": "A verbose explanation of the operation behavior"
|
|
198
|
+
},
|
|
199
|
+
"operationId": {
|
|
200
|
+
"type": "string",
|
|
201
|
+
"description": "Unique string used to identify the operation"
|
|
202
|
+
},
|
|
203
|
+
"parameters": {
|
|
204
|
+
"type": "array",
|
|
205
|
+
"items": { "$ref": "#/definitions/parameter" }
|
|
206
|
+
},
|
|
207
|
+
"requestBody": {
|
|
208
|
+
"$ref": "#/definitions/requestBody"
|
|
209
|
+
},
|
|
210
|
+
"responses": {
|
|
211
|
+
"type": "object",
|
|
212
|
+
"patternProperties": {
|
|
213
|
+
"^[1-5][0-9][0-9]$|^default$": {
|
|
214
|
+
"$ref": "#/definitions/response"
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
"tags": {
|
|
219
|
+
"type": "array",
|
|
220
|
+
"items": { "type": "string" }
|
|
221
|
+
},
|
|
222
|
+
"security": {
|
|
223
|
+
"type": "array",
|
|
224
|
+
"items": { "type": "object" }
|
|
225
|
+
},
|
|
226
|
+
"x-controller": {
|
|
227
|
+
"type": "string",
|
|
228
|
+
"description": "Dinner framework: Controller class path (e.g., 'controllers/user.controller')"
|
|
229
|
+
},
|
|
230
|
+
"x-action": {
|
|
231
|
+
"type": "string",
|
|
232
|
+
"description": "Dinner framework: Controller method name (e.g., 'create', 'getAll')"
|
|
233
|
+
},
|
|
234
|
+
"x-middleware": {
|
|
235
|
+
"type": "array",
|
|
236
|
+
"items": { "type": "string" },
|
|
237
|
+
"description": "Dinner framework: Middleware chain to apply before controller action"
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
"additionalProperties": false
|
|
241
|
+
},
|
|
242
|
+
"response": {
|
|
243
|
+
"type": "object",
|
|
244
|
+
"required": ["description"],
|
|
245
|
+
"properties": {
|
|
246
|
+
"description": {
|
|
247
|
+
"type": "string",
|
|
248
|
+
"description": "A description of the response"
|
|
249
|
+
},
|
|
250
|
+
"content": {
|
|
251
|
+
"type": "object",
|
|
252
|
+
"patternProperties": {
|
|
253
|
+
"^[a-zA-Z0-9][a-zA-Z0-9!#$&\\-\\^_]*\\/[a-zA-Z0-9][a-zA-Z0-9!#$&\\-\\^_]*$": {
|
|
254
|
+
"type": "object",
|
|
255
|
+
"properties": {
|
|
256
|
+
"schema": { "$ref": "#/definitions/schema" }
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
"headers": {
|
|
262
|
+
"type": "object",
|
|
263
|
+
"patternProperties": {
|
|
264
|
+
"^[a-zA-Z0-9\\.\\-_]+$": {
|
|
265
|
+
"type": "object",
|
|
266
|
+
"properties": {
|
|
267
|
+
"description": { "type": "string" },
|
|
268
|
+
"schema": { "$ref": "#/definitions/schema" }
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
"parameter": {
|
|
276
|
+
"type": "object",
|
|
277
|
+
"required": ["name", "in"],
|
|
278
|
+
"properties": {
|
|
279
|
+
"name": { "type": "string" },
|
|
280
|
+
"in": {
|
|
281
|
+
"type": "string",
|
|
282
|
+
"enum": ["query", "header", "path", "cookie"]
|
|
283
|
+
},
|
|
284
|
+
"description": { "type": "string" },
|
|
285
|
+
"required": { "type": "boolean" },
|
|
286
|
+
"schema": { "$ref": "#/definitions/schema" }
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
"requestBody": {
|
|
290
|
+
"type": "object",
|
|
291
|
+
"properties": {
|
|
292
|
+
"description": { "type": "string" },
|
|
293
|
+
"content": {
|
|
294
|
+
"type": "object",
|
|
295
|
+
"patternProperties": {
|
|
296
|
+
"^[a-zA-Z0-9][a-zA-Z0-9!#$&\\-\\^_]*\\/[a-zA-Z0-9][a-zA-Z0-9!#$&\\-\\^_]*$": {
|
|
297
|
+
"type": "object",
|
|
298
|
+
"properties": {
|
|
299
|
+
"schema": { "$ref": "#/definitions/schema" }
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
"required": { "type": "boolean" }
|
|
305
|
+
}
|
|
306
|
+
},
|
|
307
|
+
"schema": {
|
|
308
|
+
"type": "object",
|
|
309
|
+
"properties": {
|
|
310
|
+
"type": {
|
|
311
|
+
"type": "string",
|
|
312
|
+
"enum": ["null", "boolean", "object", "array", "number", "string", "integer"]
|
|
313
|
+
},
|
|
314
|
+
"properties": {
|
|
315
|
+
"type": "object",
|
|
316
|
+
"patternProperties": {
|
|
317
|
+
"^.*$": { "$ref": "#/definitions/schema" }
|
|
318
|
+
}
|
|
319
|
+
},
|
|
320
|
+
"items": { "$ref": "#/definitions/schema" },
|
|
321
|
+
"required": {
|
|
322
|
+
"type": "array",
|
|
323
|
+
"items": { "type": "string" }
|
|
324
|
+
},
|
|
325
|
+
"format": { "type": "string" },
|
|
326
|
+
"enum": {
|
|
327
|
+
"type": "array"
|
|
328
|
+
},
|
|
329
|
+
"minimum": { "type": "number" },
|
|
330
|
+
"maximum": { "type": "number" },
|
|
331
|
+
"minLength": { "type": "integer", "minimum": 0 },
|
|
332
|
+
"maxLength": { "type": "integer", "minimum": 0 },
|
|
333
|
+
"pattern": { "type": "string" },
|
|
334
|
+
"description": { "type": "string" },
|
|
335
|
+
"example": {},
|
|
336
|
+
"default": {},
|
|
337
|
+
"$ref": { "type": "string" }
|
|
338
|
+
}
|
|
339
|
+
},
|
|
340
|
+
"securityScheme": {
|
|
341
|
+
"type": "object",
|
|
342
|
+
"required": ["type"],
|
|
343
|
+
"properties": {
|
|
344
|
+
"type": {
|
|
345
|
+
"type": "string",
|
|
346
|
+
"enum": ["apiKey", "http", "oauth2", "openIdConnect"]
|
|
347
|
+
},
|
|
348
|
+
"description": { "type": "string" },
|
|
349
|
+
"name": { "type": "string" },
|
|
350
|
+
"in": {
|
|
351
|
+
"type": "string",
|
|
352
|
+
"enum": ["query", "header", "cookie"]
|
|
353
|
+
},
|
|
354
|
+
"scheme": { "type": "string" },
|
|
355
|
+
"bearerFormat": { "type": "string" }
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|