-
Notifications
You must be signed in to change notification settings - Fork 106
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reapply "Convert swagger.json to OAS 3.0 before generating SDK types (#…
- Loading branch information
1 parent
2ea74f3
commit 9f44712
Showing
25 changed files
with
912 additions
and
462 deletions.
There are no files selected for viewing
49 changes: 49 additions & 0 deletions
49
packages/discovery-provider/src/api/v1/models/access_gate.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
from flask_restx import fields | ||
|
||
from .common import ns | ||
from .extensions.models import OneOfModel, WildcardModel | ||
|
||
tip_gate = ns.model("tip_gate", {"tip_user_id": fields.Integer(required=True)}) | ||
follow_gate = ns.model("follow_gate", {"follow_user_id": fields.Integer(required=True)}) | ||
nft_collection = ns.model( | ||
"nft_collection", | ||
{ | ||
"chain": fields.String(enum=["eth", "sol"], required=True), | ||
"address": fields.String(required=True), | ||
"name": fields.String(required=True), | ||
"imageUrl": fields.String(), | ||
"externalLink": fields.String(), | ||
}, | ||
) | ||
nft_gate = ns.model( | ||
"nft_gate", {"nft_collection": fields.Nested(nft_collection, required=True)} | ||
) | ||
|
||
wild_card_split = WildcardModel( | ||
"wild_card_split", {"*": fields.Wildcard(fields.Integer)} | ||
) | ||
ns.add_model("wild_card_split", wild_card_split) | ||
|
||
usdc_gate = ns.model( | ||
"usdc_gate", | ||
{ | ||
"splits": fields.Nested(wild_card_split, required=True), | ||
"price": fields.Integer(required=True), | ||
}, | ||
) | ||
purchase_gate = ns.model( | ||
"purchase_gate", {"usdc_purchase": fields.Nested(usdc_gate, required=True)} | ||
) | ||
|
||
access_gate = ns.add_model( | ||
"access_gate", | ||
OneOfModel( | ||
"access_gate", | ||
[ | ||
fields.Nested(tip_gate), | ||
fields.Nested(follow_gate), | ||
fields.Nested(purchase_gate), | ||
fields.Nested(nft_gate), | ||
], | ||
), | ||
) |
Empty file.
101 changes: 101 additions & 0 deletions
101
packages/discovery-provider/src/api/v1/models/extensions/fields.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import logging | ||
|
||
from flask_restx import fields, marshal | ||
|
||
from .models import OneOfModel | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
# region: Copied from flask_restx | ||
def is_indexable_but_not_string(obj): | ||
return not hasattr(obj, "strip") and hasattr(obj, "__iter__") | ||
|
||
|
||
def is_integer_indexable(obj): | ||
return isinstance(obj, list) or isinstance(obj, tuple) | ||
|
||
|
||
def get_value(key, obj, default=None): | ||
"""Helper for pulling a keyed value off various types of objects""" | ||
if isinstance(key, int): | ||
return _get_value_for_key(key, obj, default) | ||
elif callable(key): | ||
return key(obj) | ||
else: | ||
return _get_value_for_keys(key.split("."), obj, default) | ||
|
||
|
||
def _get_value_for_keys(keys, obj, default): | ||
if len(keys) == 1: | ||
return _get_value_for_key(keys[0], obj, default) | ||
else: | ||
return _get_value_for_keys( | ||
keys[1:], _get_value_for_key(keys[0], obj, default), default | ||
) | ||
|
||
|
||
def _get_value_for_key(key, obj, default): | ||
if is_indexable_but_not_string(obj): | ||
try: | ||
return obj[key] | ||
except (IndexError, TypeError, KeyError): | ||
pass | ||
if is_integer_indexable(obj): | ||
try: | ||
return obj[int(key)] | ||
except (IndexError, TypeError, ValueError): | ||
pass | ||
return getattr(obj, key, default) | ||
|
||
|
||
# endregion Copied from flask_restx | ||
|
||
|
||
class NestedOneOf(fields.Nested): | ||
""" | ||
Unlike other models, the OneOfModel doesn't inherit dict. fields.Nested | ||
doesn't know how to process the output - it tries to marshal the model | ||
as a dict. | ||
This NestedOneOf is used the same as fields.Nested but only for OneOfModels. | ||
It attempts to marshal to each of the fields specified in OneOfModel and | ||
returns whichever one matches the original object, throwing if none do. | ||
The throwing behavior is different from other fields, and the "marshalling" | ||
behaves more like "validating". Care should be taken to ensure only the | ||
exact matching data is represented in this field. | ||
example: | ||
``` | ||
ns.add_model("my_one_of", OneOfModel("my_one_of", [fields.Nested(model_a), fields.Nested(model_b)])) | ||
my_model = ns.model("my_model", { "my_field": NestedOneOf(my_one_of, allow_null=True) }) | ||
``` | ||
See also: access_gate usage in tracks.py | ||
""" | ||
|
||
def __init__(self, model: OneOfModel, **kwargs): | ||
super(NestedOneOf, self).__init__(model, **kwargs) | ||
|
||
def output(self, key, data, **kwargs): | ||
value = get_value(key, data) | ||
if value is None: | ||
if self.allow_null: | ||
return None | ||
elif self.default is not None: | ||
return self.default | ||
for field in self.model.fields: | ||
try: | ||
marshalled = marshal(value, field.nested) | ||
if value == marshalled: | ||
return value | ||
except fields.MarshallingError as e: | ||
logger.error( | ||
f"fields.py | NestedOneOf | Failed to marshal key={key} value={value} error={e.msg}" | ||
) | ||
logger.error( | ||
f"fields.py | NestedOneOf | Failed to marshal key={key} value={data}: No matching models." | ||
) | ||
return value |
76 changes: 76 additions & 0 deletions
76
packages/discovery-provider/src/api/v1/models/extensions/models.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
from typing import List | ||
|
||
from flask_restx import Model, SchemaModel, fields | ||
|
||
|
||
class OneOfModel(SchemaModel): | ||
""" | ||
This is a dirty, dirty hack. | ||
Swagger 2.0 doesn't support the oneOf composition provided in OAS 3.0.0+. | ||
This model does one possible representation of oneOf. | ||
This model makes the resulting swagger.json schema invalid. | ||
The Swagger UI seems to ignore the invalid schema. The OpenAPI generator | ||
can be configured to ignore it as well. In the Audiuis SDK Typescript | ||
generator, validation is skipped, and an OAS 3.0.0 spec is generated from | ||
the invalid swagger.json. In the conversion, OneOfModels become simple | ||
objects, so they are re-added from the swagger.json before generating | ||
the Typescript types. | ||
When marshalling, the dat must match **exactly** one of the formats. | ||
Unlike normal marshallers, this model is more of a validator. Without | ||
a discriminator, it doesn't know what to marshal to, so it just checks | ||
that the data matches one of the models. | ||
** ONLY USE WITH `NestedOneOf`, it does NOT work with fields.Nested ** | ||
example: | ||
``` | ||
ns.add_model("my_one_of", OneOfModel("my_one_of", [fields.Nested(model_a), fields.Nested(model_b)])) | ||
my_model = ns.model("my_model", { "my_field": NestedOneOf(my_one_of, allow_null=True) }) | ||
``` | ||
schema output: | ||
``` | ||
{ | ||
// ... | ||
"definitions": { | ||
"my_one_of": { | ||
"oneOf" [ | ||
{ "ref": "#/definitions/model_a" }, | ||
{ "ref": "#/definitinos/model_b" } | ||
] | ||
} | ||
} | ||
} | ||
``` | ||
See also: access_gate usage in tracks.py | ||
""" | ||
|
||
def __init__(self, name, fields: List[fields.Nested], *args, **kwargs): | ||
super(OneOfModel, self).__init__( | ||
name, {"oneOf": [field.__schema__ for field in fields]} | ||
) | ||
self.fields = fields | ||
|
||
# hack to register related models - hijacks Polymorphism pattern | ||
self.__parents__ = [field.nested for field in self.fields] | ||
|
||
@property | ||
def __schema__(self): | ||
# override the base model to prevent the polymorph allOf from happening | ||
return self._schema | ||
|
||
|
||
class WildcardModel(Model): | ||
"""Hack of the Model that allows the schema to be properly formatted for a wildcard field.""" | ||
|
||
@property | ||
def _schema(self): | ||
# Skip the schema for this and surface the child schema if the wildcard is found | ||
if "*" in self: | ||
return self["*"].__schema__ | ||
return super(WildcardModel, self)._schema() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 0 additions & 12 deletions
12
packages/discovery-provider/src/api/v1/models/wildcard_model.py
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
packages/libs/src/sdk/api/generated/default/.openapi-generator/VERSION
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
7.6.0-SNAPSHOT | ||
7.5.0-SNAPSHOT |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
packages/libs/src/sdk/api/generated/full/.openapi-generator/VERSION
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
7.6.0-SNAPSHOT | ||
7.5.0-SNAPSHOT |
Oops, something went wrong.