geniespec 0.1.1__tar.gz
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.
- geniespec-0.1.1/PKG-INFO +124 -0
- geniespec-0.1.1/README.md +110 -0
- geniespec-0.1.1/pyproject.toml +37 -0
- geniespec-0.1.1/pyproject.toml.orig +38 -0
- geniespec-0.1.1/src/geniespec/__init__.py +0 -0
- geniespec-0.1.1/src/geniespec/api_schema.yaml +372 -0
- geniespec-0.1.1/src/geniespec/cli.py +123 -0
- geniespec-0.1.1/src/geniespec/genie.py +596 -0
- geniespec-0.1.1/src/geniespec/languages.py +707 -0
- geniespec-0.1.1/src/geniespec/renderable_types.py +272 -0
- geniespec-0.1.1/src/geniespec/templates/python-server/{service}/__init__.py.j2 +1 -0
- geniespec-0.1.1/src/geniespec/templates/python-server/{service}/v{version}/__init__.py.j2 +1 -0
- geniespec-0.1.1/src/geniespec/templates/python-server/{service}/v{version}/api.py.j2 +68 -0
- geniespec-0.1.1/src/geniespec/templates/python-server/{service}/v{version}/endpoints.py.j2 +41 -0
- geniespec-0.1.1/src/geniespec/templates/python-server/{service}/v{version}/exceptions.py.j2 +68 -0
- geniespec-0.1.1/src/geniespec/templates/python-server/{service}/v{version}/internal.py.j2 +39 -0
- geniespec-0.1.1/src/geniespec/templates/python-server/{service}/v{version}/resources.py.j2 +37 -0
- geniespec-0.1.1/src/geniespec/templates/typescript-client/{service}/v{version}/client.ts.j2 +48 -0
- geniespec-0.1.1/src/geniespec/templates/typescript-client/{service}/v{version}/endpoints.ts.j2 +83 -0
- geniespec-0.1.1/src/geniespec/templates/typescript-client/{service}/v{version}/index.ts.j2 +4 -0
- geniespec-0.1.1/src/geniespec/templates/typescript-client/{service}/v{version}/resources.ts.j2 +66 -0
- geniespec-0.1.1/src/geniespec/types.py +170 -0
geniespec-0.1.1/PKG-INFO
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: geniespec
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Generate API code from an api.yaml spec
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Requires-Dist: jinja2>=3.1.6
|
|
7
|
+
Requires-Dist: pyyaml>=6.0.3
|
|
8
|
+
Requires-Dist: jsonschema>=4.26.0
|
|
9
|
+
Requires-Dist: pydantic>=2.13.5
|
|
10
|
+
Requires-Dist: kiba-core>=0.5.3.dev81,<0.5.4
|
|
11
|
+
Requires-Python: >=3.13, <4
|
|
12
|
+
Project-URL: repository, https://github.com/kibalabs/genie
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
15
|
+
# Genie
|
|
16
|
+
|
|
17
|
+
Genie (`geniespec` on PyPI) generates API code from an `api.yaml` spec. Install it like any other tool and run it from your build scripts; the generated code is gitignored, not committed.
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
geniespec build --spec api.yaml --target <python-server | typescript-client> [--output .]
|
|
21
|
+
geniespec watch --spec api.yaml --target <python-server | typescript-client> [--output .] [-- <command>]
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- `build` writes the target's package into the output directory. Only files in that package are touched: changed files are rewritten and files it no longer generates are removed.
|
|
25
|
+
- `python-server`: `./<service>_api/v<major>/` (`api`, `endpoints`, `resources`, `internal`, `exceptions`). Code run from the output directory imports it directly, e.g. `from my_service_api.v1 import api`. Needs `kiba-core` (`core.api`, `core.util.typing_util`; 0.5.3.dev87 or later for `File` fields), `pydantic` and `starlette`.
|
|
26
|
+
- `typescript-client`: `./<service>-api/v<major>/` (`client`, `endpoints`, `resources`, `index`) with a `<Service>ApiV<major>Client` that extends `@kibalabs/core`'s `ServiceClient`. Construct it with the url the API version is mounted at, e.g. `new MyServiceApiV1Client(requester, 'https://api.example.com/v1')`. Methods take path parameters, then a params object for the request fields, and return the response field; stream transitions take a callback for each item; transitions with `File` fields send a multipart form. Transitions with `responseType: redirect` or a `query-parameters` field are left out, as browsers open redirects directly and query-parameters fields receive third-party callbacks. Needs `@kibalabs/core`.
|
|
27
|
+
- `watch` builds, then rebuilds whenever the spec changes. If the spec is invalid it logs the error and keeps the previous output. Given a command after `--`, it runs it once the first build is done, keeps rebuilding while it runs, exits with its exit code and stops it when watch itself is stopped, e.g. `geniespec watch --spec api.yaml --target python-server -- uvicorn app:app --reload`.
|
|
28
|
+
- The bundled templates are examples of a kibalabs-style target.
|
|
29
|
+
|
|
30
|
+
## Enums, oneOfs and files
|
|
31
|
+
|
|
32
|
+
Enums are string values limited to a list. Name them at the top level to reuse them, or give a field its own:
|
|
33
|
+
|
|
34
|
+
```yaml
|
|
35
|
+
enums:
|
|
36
|
+
- name: ViewKind
|
|
37
|
+
values: [member, cycle-start]
|
|
38
|
+
resources:
|
|
39
|
+
- singleName: View
|
|
40
|
+
collectionName: Views
|
|
41
|
+
attributes:
|
|
42
|
+
- name: kind
|
|
43
|
+
type: ViewKind
|
|
44
|
+
- name: size
|
|
45
|
+
type: Enum
|
|
46
|
+
enumValues: [small, large]
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
`python-server` types them as `typing.Literal[...]` (named ones as `ViewKindV1` in `resources`) and rejects requests with other values; `typescript-client` types them as `'member' | 'cycle-start'` (named ones as an exported `ViewKindV1`).
|
|
50
|
+
|
|
51
|
+
`type: File` request fields upload a file. They are only allowed on POST transitions, and the transition's other fields must be single primitive or enum values, as the request is sent as a multipart form. Internal methods receive kiba-core's `UploadedFile` (`filename`, `contentType`, `content`); clients pass a `File`.
|
|
52
|
+
|
|
53
|
+
A oneOf is a value that is one of several resources, told apart by a discriminator attribute. Each member resource needs that attribute as a non-nullable enum with a single value:
|
|
54
|
+
|
|
55
|
+
```yaml
|
|
56
|
+
oneOfs:
|
|
57
|
+
- name: ViewContent
|
|
58
|
+
discriminator: kind
|
|
59
|
+
types: [ChartContent, TableContent]
|
|
60
|
+
resources:
|
|
61
|
+
- singleName: ChartContent
|
|
62
|
+
collectionName: ChartContents
|
|
63
|
+
attributes:
|
|
64
|
+
- name: kind
|
|
65
|
+
type: Enum
|
|
66
|
+
enumValues: [chart]
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Fields use it like any other type (`type: ViewContent`, also inside `List` and `Mapping`). `python-server` generates a `ViewContentV1` pydantic discriminated union in `resources`; `typescript-client` generates a `ViewContentV1` union type and a `viewContentV1FromObject` function that builds the member class named by the discriminator (and throws for unknown values).
|
|
70
|
+
|
|
71
|
+
# Development
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
make install
|
|
75
|
+
make lint-check type-check test
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
`tests/python_server` covers the core and the `python-server` target (the core tests generate through it) and runs in `Dockerfile`. `tests/typescript_client` covers the `typescript-client` target; it needs node and runs in `typescript-client.Dockerfile`:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
make install-typescript-client
|
|
82
|
+
make test-typescript-client
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Merges to `main` publish a dev version to PyPI. To release, bump `version` in `pyproject.toml` in a PR, then run the Release workflow on `main` (Actions → Release → Run workflow). It tags `vX.Y.Z` and the Publish workflow publishes it. Only the release workflow can push version tags.
|
|
86
|
+
|
|
87
|
+
# Things that need work
|
|
88
|
+
|
|
89
|
+
## Typing of params and fields in general
|
|
90
|
+
|
|
91
|
+
I think we need to create an object for Type. what would it look like?
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
class BaseFieldType:
|
|
96
|
+
isNullable: bool
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class RawFieldType(BaseFieldType):
|
|
100
|
+
name: str
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class ClassFieldType(BaseFieldType):
|
|
104
|
+
fieldType: RawFieldType
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class ListFieldType:(BaseFieldType)
|
|
108
|
+
fieldType: RawFieldType
|
|
109
|
+
isNullable: bool
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class MappingFieldType(BaseFieldType):
|
|
113
|
+
keyFieldType: RawFieldType
|
|
114
|
+
valueFieldType: RawFieldType
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class OneOfFieldType(BaseFieldType):
|
|
118
|
+
fieldTypes: list[RawFieldType]
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class EnumFieldType(BaseFieldType):
|
|
122
|
+
values: list[str]
|
|
123
|
+
|
|
124
|
+
```
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Genie
|
|
2
|
+
|
|
3
|
+
Genie (`geniespec` on PyPI) generates API code from an `api.yaml` spec. Install it like any other tool and run it from your build scripts; the generated code is gitignored, not committed.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
geniespec build --spec api.yaml --target <python-server | typescript-client> [--output .]
|
|
7
|
+
geniespec watch --spec api.yaml --target <python-server | typescript-client> [--output .] [-- <command>]
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
- `build` writes the target's package into the output directory. Only files in that package are touched: changed files are rewritten and files it no longer generates are removed.
|
|
11
|
+
- `python-server`: `./<service>_api/v<major>/` (`api`, `endpoints`, `resources`, `internal`, `exceptions`). Code run from the output directory imports it directly, e.g. `from my_service_api.v1 import api`. Needs `kiba-core` (`core.api`, `core.util.typing_util`; 0.5.3.dev87 or later for `File` fields), `pydantic` and `starlette`.
|
|
12
|
+
- `typescript-client`: `./<service>-api/v<major>/` (`client`, `endpoints`, `resources`, `index`) with a `<Service>ApiV<major>Client` that extends `@kibalabs/core`'s `ServiceClient`. Construct it with the url the API version is mounted at, e.g. `new MyServiceApiV1Client(requester, 'https://api.example.com/v1')`. Methods take path parameters, then a params object for the request fields, and return the response field; stream transitions take a callback for each item; transitions with `File` fields send a multipart form. Transitions with `responseType: redirect` or a `query-parameters` field are left out, as browsers open redirects directly and query-parameters fields receive third-party callbacks. Needs `@kibalabs/core`.
|
|
13
|
+
- `watch` builds, then rebuilds whenever the spec changes. If the spec is invalid it logs the error and keeps the previous output. Given a command after `--`, it runs it once the first build is done, keeps rebuilding while it runs, exits with its exit code and stops it when watch itself is stopped, e.g. `geniespec watch --spec api.yaml --target python-server -- uvicorn app:app --reload`.
|
|
14
|
+
- The bundled templates are examples of a kibalabs-style target.
|
|
15
|
+
|
|
16
|
+
## Enums, oneOfs and files
|
|
17
|
+
|
|
18
|
+
Enums are string values limited to a list. Name them at the top level to reuse them, or give a field its own:
|
|
19
|
+
|
|
20
|
+
```yaml
|
|
21
|
+
enums:
|
|
22
|
+
- name: ViewKind
|
|
23
|
+
values: [member, cycle-start]
|
|
24
|
+
resources:
|
|
25
|
+
- singleName: View
|
|
26
|
+
collectionName: Views
|
|
27
|
+
attributes:
|
|
28
|
+
- name: kind
|
|
29
|
+
type: ViewKind
|
|
30
|
+
- name: size
|
|
31
|
+
type: Enum
|
|
32
|
+
enumValues: [small, large]
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`python-server` types them as `typing.Literal[...]` (named ones as `ViewKindV1` in `resources`) and rejects requests with other values; `typescript-client` types them as `'member' | 'cycle-start'` (named ones as an exported `ViewKindV1`).
|
|
36
|
+
|
|
37
|
+
`type: File` request fields upload a file. They are only allowed on POST transitions, and the transition's other fields must be single primitive or enum values, as the request is sent as a multipart form. Internal methods receive kiba-core's `UploadedFile` (`filename`, `contentType`, `content`); clients pass a `File`.
|
|
38
|
+
|
|
39
|
+
A oneOf is a value that is one of several resources, told apart by a discriminator attribute. Each member resource needs that attribute as a non-nullable enum with a single value:
|
|
40
|
+
|
|
41
|
+
```yaml
|
|
42
|
+
oneOfs:
|
|
43
|
+
- name: ViewContent
|
|
44
|
+
discriminator: kind
|
|
45
|
+
types: [ChartContent, TableContent]
|
|
46
|
+
resources:
|
|
47
|
+
- singleName: ChartContent
|
|
48
|
+
collectionName: ChartContents
|
|
49
|
+
attributes:
|
|
50
|
+
- name: kind
|
|
51
|
+
type: Enum
|
|
52
|
+
enumValues: [chart]
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Fields use it like any other type (`type: ViewContent`, also inside `List` and `Mapping`). `python-server` generates a `ViewContentV1` pydantic discriminated union in `resources`; `typescript-client` generates a `ViewContentV1` union type and a `viewContentV1FromObject` function that builds the member class named by the discriminator (and throws for unknown values).
|
|
56
|
+
|
|
57
|
+
# Development
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
make install
|
|
61
|
+
make lint-check type-check test
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`tests/python_server` covers the core and the `python-server` target (the core tests generate through it) and runs in `Dockerfile`. `tests/typescript_client` covers the `typescript-client` target; it needs node and runs in `typescript-client.Dockerfile`:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
make install-typescript-client
|
|
68
|
+
make test-typescript-client
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Merges to `main` publish a dev version to PyPI. To release, bump `version` in `pyproject.toml` in a PR, then run the Release workflow on `main` (Actions → Release → Run workflow). It tags `vX.Y.Z` and the Publish workflow publishes it. Only the release workflow can push version tags.
|
|
72
|
+
|
|
73
|
+
# Things that need work
|
|
74
|
+
|
|
75
|
+
## Typing of params and fields in general
|
|
76
|
+
|
|
77
|
+
I think we need to create an object for Type. what would it look like?
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
class BaseFieldType:
|
|
82
|
+
isNullable: bool
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class RawFieldType(BaseFieldType):
|
|
86
|
+
name: str
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class ClassFieldType(BaseFieldType):
|
|
90
|
+
fieldType: RawFieldType
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class ListFieldType:(BaseFieldType)
|
|
94
|
+
fieldType: RawFieldType
|
|
95
|
+
isNullable: bool
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class MappingFieldType(BaseFieldType):
|
|
99
|
+
keyFieldType: RawFieldType
|
|
100
|
+
valueFieldType: RawFieldType
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class OneOfFieldType(BaseFieldType):
|
|
104
|
+
fieldTypes: list[RawFieldType]
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class EnumFieldType(BaseFieldType):
|
|
108
|
+
values: list[str]
|
|
109
|
+
|
|
110
|
+
```
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "geniespec"
|
|
3
|
+
version = "0.1.1"
|
|
4
|
+
description = "Generate API code from an api.yaml spec"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
requires-python = ">=3.13, <4"
|
|
8
|
+
dependencies = [
|
|
9
|
+
"jinja2>=3.1.6",
|
|
10
|
+
"pyyaml>=6.0.3",
|
|
11
|
+
"jsonschema>=4.26.0",
|
|
12
|
+
"pydantic>=2.13.5",
|
|
13
|
+
"kiba-core>=0.5.3.dev81,<0.5.4",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
[project.scripts]
|
|
17
|
+
geniespec = "geniespec.cli:main"
|
|
18
|
+
|
|
19
|
+
[project.urls]
|
|
20
|
+
repository = "https://github.com/kibalabs/genie"
|
|
21
|
+
|
|
22
|
+
[dependency-groups]
|
|
23
|
+
dev = [
|
|
24
|
+
"kiba-build==0.1.11.dev15",
|
|
25
|
+
"kiba-core[core-api,requester]>=0.5.3.dev87,<0.5.4",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[build-system]
|
|
29
|
+
requires = ["uv_build>=0.12,<0.13"]
|
|
30
|
+
build-backend = "uv_build"
|
|
31
|
+
|
|
32
|
+
[tool.pytest.ini_options]
|
|
33
|
+
pythonpath = ["src"]
|
|
34
|
+
|
|
35
|
+
[tool.bumpversion]
|
|
36
|
+
search = 'version = "{current_version}"'
|
|
37
|
+
replace = 'version = "{new_version}"'
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "geniespec"
|
|
3
|
+
version = "0.1.1"
|
|
4
|
+
description = "Generate API code from an api.yaml spec"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
requires-python = ">=3.13, <4"
|
|
8
|
+
dependencies = [
|
|
9
|
+
"jinja2>=3.1.6",
|
|
10
|
+
"pyyaml>=6.0.3",
|
|
11
|
+
"jsonschema>=4.26.0",
|
|
12
|
+
"pydantic>=2.13.5",
|
|
13
|
+
"kiba-core>=0.5.3.dev81,<0.5.4",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
[project.scripts]
|
|
17
|
+
geniespec = "geniespec.cli:main"
|
|
18
|
+
|
|
19
|
+
[project.urls]
|
|
20
|
+
repository = "https://github.com/kibalabs/genie"
|
|
21
|
+
|
|
22
|
+
[dependency-groups]
|
|
23
|
+
dev = [
|
|
24
|
+
"kiba-build==0.1.11.dev15",
|
|
25
|
+
"kiba-core[core-api,requester]>=0.5.3.dev87,<0.5.4",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[build-system]
|
|
29
|
+
requires = ["uv_build>=0.12,<0.13"]
|
|
30
|
+
build-backend = "uv_build"
|
|
31
|
+
|
|
32
|
+
[tool.pytest.ini_options]
|
|
33
|
+
pythonpath = ["src"]
|
|
34
|
+
|
|
35
|
+
# NOTE(krishan711): without this, bumping the version also rewrites dependency pins that contain it (e.g. 0.1.1 inside kiba-build==0.1.11.dev15)
|
|
36
|
+
[tool.bumpversion]
|
|
37
|
+
search = "version = \"{current_version}\""
|
|
38
|
+
replace = "version = \"{new_version}\""
|
|
File without changes
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
$schema: 'http://json-schema.org/draft-07/schema#'
|
|
2
|
+
$id: kibaRestApiSchema
|
|
3
|
+
type: object
|
|
4
|
+
additionalProperties: false
|
|
5
|
+
required:
|
|
6
|
+
- version
|
|
7
|
+
- serviceName
|
|
8
|
+
- pythonClientPackageName
|
|
9
|
+
- typescriptClientPackageName
|
|
10
|
+
properties:
|
|
11
|
+
version:
|
|
12
|
+
type: string
|
|
13
|
+
pattern: '^([0-9]|[1-9][0-9]*)\.([0-9]|[1-9][0-9]*)\.([0-9]|[1-9][0-9]*)$'
|
|
14
|
+
serviceName:
|
|
15
|
+
type: string
|
|
16
|
+
pattern: '^[a-z][a-z-]*$'
|
|
17
|
+
pythonClientPackageName:
|
|
18
|
+
type: string
|
|
19
|
+
pattern: '^[a-z][-a-z]*$'
|
|
20
|
+
typescriptClientPackageName:
|
|
21
|
+
type: string
|
|
22
|
+
pattern: '[@/-a-z]*$'
|
|
23
|
+
transitions:
|
|
24
|
+
type: array
|
|
25
|
+
items:
|
|
26
|
+
$ref: '#/definitions/RootTransition'
|
|
27
|
+
resources:
|
|
28
|
+
type: array
|
|
29
|
+
items:
|
|
30
|
+
$ref: '#/definitions/Resource'
|
|
31
|
+
exceptions:
|
|
32
|
+
type: array
|
|
33
|
+
items:
|
|
34
|
+
$ref: '#/definitions/Exception'
|
|
35
|
+
enums:
|
|
36
|
+
type: array
|
|
37
|
+
items:
|
|
38
|
+
$ref: '#/definitions/Enum'
|
|
39
|
+
oneOfs:
|
|
40
|
+
type: array
|
|
41
|
+
items:
|
|
42
|
+
$ref: '#/definitions/OneOf'
|
|
43
|
+
imports:
|
|
44
|
+
type: array
|
|
45
|
+
items:
|
|
46
|
+
type: string
|
|
47
|
+
defaultAuthentication:
|
|
48
|
+
type:
|
|
49
|
+
- "null"
|
|
50
|
+
- string
|
|
51
|
+
pattern: '^[a-z][a-z0-9-]*$'
|
|
52
|
+
definitions:
|
|
53
|
+
EnumValues:
|
|
54
|
+
type: array
|
|
55
|
+
minItems: 1
|
|
56
|
+
uniqueItems: true
|
|
57
|
+
items:
|
|
58
|
+
type: string
|
|
59
|
+
pattern: '^[A-Za-z0-9][A-Za-z0-9_-]*$'
|
|
60
|
+
Enum:
|
|
61
|
+
type: object
|
|
62
|
+
additionalProperties: false
|
|
63
|
+
required:
|
|
64
|
+
- name
|
|
65
|
+
- values
|
|
66
|
+
properties:
|
|
67
|
+
name:
|
|
68
|
+
type: string
|
|
69
|
+
pattern: '^[A-Z][A-Za-z]*$'
|
|
70
|
+
values:
|
|
71
|
+
$ref: '#/definitions/EnumValues'
|
|
72
|
+
OneOf:
|
|
73
|
+
type: object
|
|
74
|
+
additionalProperties: false
|
|
75
|
+
required:
|
|
76
|
+
- name
|
|
77
|
+
- discriminator
|
|
78
|
+
- types
|
|
79
|
+
properties:
|
|
80
|
+
name:
|
|
81
|
+
type: string
|
|
82
|
+
pattern: '^[A-Z][A-Za-z]*$'
|
|
83
|
+
discriminator:
|
|
84
|
+
type: string
|
|
85
|
+
pattern: '^[a-z][A-Za-z0-9-]*$'
|
|
86
|
+
types:
|
|
87
|
+
type: array
|
|
88
|
+
minItems: 2
|
|
89
|
+
uniqueItems: true
|
|
90
|
+
items:
|
|
91
|
+
type: string
|
|
92
|
+
pattern: '^[A-Z][A-Za-z-]*$'
|
|
93
|
+
Attribute:
|
|
94
|
+
type: object
|
|
95
|
+
additionalProperties: false
|
|
96
|
+
required:
|
|
97
|
+
- name
|
|
98
|
+
- type
|
|
99
|
+
properties:
|
|
100
|
+
name:
|
|
101
|
+
type: string
|
|
102
|
+
pattern: '^[a-z][A-Za-z0-9-]*$'
|
|
103
|
+
type:
|
|
104
|
+
type: string
|
|
105
|
+
pattern: '^[A-Z][A-Za-z-\[\]_, ]*$'
|
|
106
|
+
listValueTypes:
|
|
107
|
+
type: array
|
|
108
|
+
minItems: 1
|
|
109
|
+
items:
|
|
110
|
+
type: string
|
|
111
|
+
pattern: '^[A-Z][A-Za-z-\[\]_, ]*$'
|
|
112
|
+
isPrimary:
|
|
113
|
+
type: boolean
|
|
114
|
+
isUnique:
|
|
115
|
+
type: boolean
|
|
116
|
+
shouldDisableGetEndpoint:
|
|
117
|
+
type: boolean
|
|
118
|
+
isUnfilterable:
|
|
119
|
+
type: boolean
|
|
120
|
+
isUpdatable:
|
|
121
|
+
type: boolean
|
|
122
|
+
isNullable:
|
|
123
|
+
type: boolean
|
|
124
|
+
isDeprecated:
|
|
125
|
+
type: boolean
|
|
126
|
+
defaultValue:
|
|
127
|
+
type:
|
|
128
|
+
- string
|
|
129
|
+
- number
|
|
130
|
+
- boolean
|
|
131
|
+
- 'null'
|
|
132
|
+
isSettable:
|
|
133
|
+
type: boolean
|
|
134
|
+
isAccessibleIndependently:
|
|
135
|
+
type: boolean
|
|
136
|
+
mappingKeyType:
|
|
137
|
+
type: string
|
|
138
|
+
pattern: '^[A-Z][A-Za-z-\[\]_, ]*$'
|
|
139
|
+
mappingValueTypes:
|
|
140
|
+
type: array
|
|
141
|
+
items:
|
|
142
|
+
type: string
|
|
143
|
+
pattern: '^[A-Z][A-Za-z-\[\]_, ]*$'
|
|
144
|
+
enumValues:
|
|
145
|
+
$ref: '#/definitions/EnumValues'
|
|
146
|
+
Resource:
|
|
147
|
+
type: object
|
|
148
|
+
additionalProperties: false
|
|
149
|
+
required:
|
|
150
|
+
- singleName
|
|
151
|
+
- collectionName
|
|
152
|
+
properties:
|
|
153
|
+
singleName:
|
|
154
|
+
type: string
|
|
155
|
+
pattern: '^[A-Z][A-Za-z-]*$'
|
|
156
|
+
collectionName:
|
|
157
|
+
type: string
|
|
158
|
+
pattern: '^[A-Z][A-Za-z-]*$'
|
|
159
|
+
parentResource:
|
|
160
|
+
type: string
|
|
161
|
+
pattern: '^[A-Z][A-Za-z-]*$'
|
|
162
|
+
attributes:
|
|
163
|
+
type: array
|
|
164
|
+
items:
|
|
165
|
+
$ref: '#/definitions/Attribute'
|
|
166
|
+
transitions:
|
|
167
|
+
type: array
|
|
168
|
+
items:
|
|
169
|
+
$ref: '#/definitions/Transition'
|
|
170
|
+
accessibleFrom:
|
|
171
|
+
type: array
|
|
172
|
+
items:
|
|
173
|
+
type: string
|
|
174
|
+
BaseTransition:
|
|
175
|
+
type: object
|
|
176
|
+
additionalProperties: false
|
|
177
|
+
required:
|
|
178
|
+
- action
|
|
179
|
+
properties:
|
|
180
|
+
action:
|
|
181
|
+
type: string
|
|
182
|
+
pattern: '^[A-Z][A-Z-]*$'
|
|
183
|
+
method:
|
|
184
|
+
type: string
|
|
185
|
+
enum:
|
|
186
|
+
- GET
|
|
187
|
+
- POST
|
|
188
|
+
requestFields:
|
|
189
|
+
type: array
|
|
190
|
+
items:
|
|
191
|
+
$ref: '#/definitions/RequestField'
|
|
192
|
+
responseField:
|
|
193
|
+
$ref: '#/definitions/ResponseField'
|
|
194
|
+
authentication:
|
|
195
|
+
type:
|
|
196
|
+
- "null"
|
|
197
|
+
- string
|
|
198
|
+
pattern: '^[a-z][a-z0-9-]*$'
|
|
199
|
+
responseType:
|
|
200
|
+
type: string
|
|
201
|
+
enum:
|
|
202
|
+
- json
|
|
203
|
+
- stream
|
|
204
|
+
- redirect
|
|
205
|
+
Transition:
|
|
206
|
+
type: object
|
|
207
|
+
additionalProperties: false
|
|
208
|
+
required:
|
|
209
|
+
- action
|
|
210
|
+
properties:
|
|
211
|
+
action:
|
|
212
|
+
type: string
|
|
213
|
+
pattern: '^[A-Z][A-Z-]*$'
|
|
214
|
+
method:
|
|
215
|
+
type: string
|
|
216
|
+
enum:
|
|
217
|
+
- GET
|
|
218
|
+
- POST
|
|
219
|
+
requestFields:
|
|
220
|
+
type: array
|
|
221
|
+
items:
|
|
222
|
+
$ref: '#/definitions/RequestField'
|
|
223
|
+
responseField:
|
|
224
|
+
$ref: '#/definitions/ResponseField'
|
|
225
|
+
authentication:
|
|
226
|
+
type:
|
|
227
|
+
- "null"
|
|
228
|
+
- string
|
|
229
|
+
pattern: '^[a-z][a-z0-9-]*$'
|
|
230
|
+
responseType:
|
|
231
|
+
type: string
|
|
232
|
+
enum:
|
|
233
|
+
- json
|
|
234
|
+
- stream
|
|
235
|
+
- redirect
|
|
236
|
+
operatesOn:
|
|
237
|
+
type: string
|
|
238
|
+
enum:
|
|
239
|
+
- individual
|
|
240
|
+
- collection
|
|
241
|
+
isIndirectAction:
|
|
242
|
+
type: boolean
|
|
243
|
+
RootTransition:
|
|
244
|
+
type: object
|
|
245
|
+
allOf:
|
|
246
|
+
- $ref: '#/definitions/BaseTransition'
|
|
247
|
+
RequestField:
|
|
248
|
+
type: object
|
|
249
|
+
additionalProperties: false
|
|
250
|
+
required:
|
|
251
|
+
- name
|
|
252
|
+
- type
|
|
253
|
+
properties:
|
|
254
|
+
name:
|
|
255
|
+
type: string
|
|
256
|
+
pattern: '^[a-z][A-Za-z0-9-]*$'
|
|
257
|
+
type:
|
|
258
|
+
type: string
|
|
259
|
+
pattern: '^[A-Z][A-Za-z-\[\]_, ]*$'
|
|
260
|
+
listValueTypes:
|
|
261
|
+
type: array
|
|
262
|
+
minItems: 1
|
|
263
|
+
items:
|
|
264
|
+
type: string
|
|
265
|
+
pattern: '^[A-Z][A-Za-z-\[\]_, ]*$'
|
|
266
|
+
mappingKeyType:
|
|
267
|
+
type: string
|
|
268
|
+
pattern: '^[A-Z][A-Za-z-\[\]_, ]*$'
|
|
269
|
+
mappingValueTypes:
|
|
270
|
+
type: array
|
|
271
|
+
items:
|
|
272
|
+
type: string
|
|
273
|
+
pattern: '^[A-Z][A-Za-z-\[\]_, ]*$'
|
|
274
|
+
enumValues:
|
|
275
|
+
$ref: '#/definitions/EnumValues'
|
|
276
|
+
isRequired:
|
|
277
|
+
type: boolean
|
|
278
|
+
defaultValue:
|
|
279
|
+
type:
|
|
280
|
+
- string
|
|
281
|
+
- number
|
|
282
|
+
- boolean
|
|
283
|
+
- 'null'
|
|
284
|
+
isDeprecated:
|
|
285
|
+
type: boolean
|
|
286
|
+
maxValue:
|
|
287
|
+
type:
|
|
288
|
+
- string
|
|
289
|
+
- number
|
|
290
|
+
minValue:
|
|
291
|
+
type:
|
|
292
|
+
- string
|
|
293
|
+
- number
|
|
294
|
+
source:
|
|
295
|
+
type: string
|
|
296
|
+
enum:
|
|
297
|
+
- request
|
|
298
|
+
- query-parameters
|
|
299
|
+
ResponseField:
|
|
300
|
+
type: object
|
|
301
|
+
additionalProperties: false
|
|
302
|
+
required:
|
|
303
|
+
- name
|
|
304
|
+
- type
|
|
305
|
+
properties:
|
|
306
|
+
name:
|
|
307
|
+
type: string
|
|
308
|
+
pattern: '^[a-z][A-Za-z-]*$'
|
|
309
|
+
type:
|
|
310
|
+
type: string
|
|
311
|
+
pattern: '^[A-Z][A-Za-z-\[\]_, ]*$'
|
|
312
|
+
listValueTypes:
|
|
313
|
+
type: array
|
|
314
|
+
minItems: 1
|
|
315
|
+
items:
|
|
316
|
+
type: string
|
|
317
|
+
pattern: '^[A-Z][A-Za-z-\[\]_, ]*$'
|
|
318
|
+
mappingKeyType:
|
|
319
|
+
type: string
|
|
320
|
+
pattern: '^[A-Z][A-Za-z-\[\]_, ]*$'
|
|
321
|
+
mappingValueTypes:
|
|
322
|
+
type: array
|
|
323
|
+
items:
|
|
324
|
+
type: string
|
|
325
|
+
pattern: '^[A-Z][A-Za-z-\[\]_, ]*$'
|
|
326
|
+
enumValues:
|
|
327
|
+
$ref: '#/definitions/EnumValues'
|
|
328
|
+
isNullable:
|
|
329
|
+
type: boolean
|
|
330
|
+
isList:
|
|
331
|
+
type: boolean
|
|
332
|
+
Exception:
|
|
333
|
+
type: object
|
|
334
|
+
additionalProperties: false
|
|
335
|
+
required:
|
|
336
|
+
- name
|
|
337
|
+
properties:
|
|
338
|
+
name:
|
|
339
|
+
type: string
|
|
340
|
+
pattern: '^[A-Z][A-Za-z-]*Exception$'
|
|
341
|
+
message:
|
|
342
|
+
type: string
|
|
343
|
+
extends:
|
|
344
|
+
type: string
|
|
345
|
+
pattern: '^([a-z-]+.exceptions.[A-Za-z-]*)|([A-Za-z-]*)'
|
|
346
|
+
statusCode:
|
|
347
|
+
type: integer
|
|
348
|
+
fields:
|
|
349
|
+
type: array
|
|
350
|
+
items:
|
|
351
|
+
$ref: '#/definitions/ExceptionField'
|
|
352
|
+
ExceptionField:
|
|
353
|
+
type: object
|
|
354
|
+
additionalProperties: false
|
|
355
|
+
required:
|
|
356
|
+
- name
|
|
357
|
+
- type
|
|
358
|
+
properties:
|
|
359
|
+
name:
|
|
360
|
+
type: string
|
|
361
|
+
pattern: '^[a-z][A-Za-z-]*$'
|
|
362
|
+
type:
|
|
363
|
+
type: string
|
|
364
|
+
pattern: '^[A-Z][A-Za-z-\[\]_, ]*$'
|
|
365
|
+
listValueTypes:
|
|
366
|
+
type: array
|
|
367
|
+
minItems: 1
|
|
368
|
+
items:
|
|
369
|
+
type: string
|
|
370
|
+
pattern: '^[A-Z][A-Za-z-\[\]_, ]*$'
|
|
371
|
+
isRequired:
|
|
372
|
+
type: boolean
|