Metadata-Version: 2.1
Name: chillapi
Version: 0.0.1
Summary: A library to create APIs focused on data projects
Home-page: UNKNOWN
Author: andrescevp@gmail.com
License: MIT
Description: # ChillApi
        
        ## Motivation
        
        This project was born to increase the speed of delivery and development of APIs.
        
        The premise is simple, not all roles can feel comfortable swimming in a sea of indented code, however they do feel comfortable in SQL languages. And those who do feel comfortable programming may prefer to use a tool that configures and propagates information than extending an ORM, routes, forms, etc; thus being able to spend more time on other types of tasks.
        
        The connection and execution of queries is done in raw, that is, there is no ORM involved.
        
        The implementation of this framework is on Flask using a series of additional libraries and adopting others to satisfy the requirements of the same.
        
        # setup
        
        Create a `api.yaml` file:
        ```yaml
        app:
          name: ChillApi
          version: '0.1'
          swagger_url: '/swagger'
          swagger_ui_url: '/doc'
          host: 0.0.0.0
          port: 8000
          debug: True
          #  externalDocs:
          #    description: Find more info here
          #    url: https://example.com
          #  license:
          #    name: Apache 2.0
          #    url: https://www.apache.org/licenses/LICENSE-2.0.html
          #  contact:
          #    name: API Support
          #    url: http://www.example.com/support
          #    email: support@example.com
          securitySchemes:
            bearerAuth: # arbitrary name for the security scheme
              type: http
              scheme: bearer
              bearerFormat: JWT
          security:
            - bearerAuth: [ ]
          security_level: STANDARD
          security_handler:
            package: my_app.auth
            handler: auth
        environment:
          __CHILLAPI_DB_DSN__: '$DB_URL'
        #  __CHILLAPI_DB_DSN__: 'sqlite:///var/db.sqlite'
          __CHILLAPI_APP_SECRET_KEY__: 'super-secret-key'
        logger:
          app:
            output: stdout
            level: 10
          audit_logger:
            output: stdout
            level: 40
          error_handler:
            output: stdout
            level: 40
          sqlalchemy:
            output: stdout
            level: 40
        database:
          schema: public
          defaults:
            tables:
              id_field: id
              fields_excluded: # silent check if exists in the table
                all:
                  - created_at
                  - updated_by
                  - updated_at
                  - created_by
                  - deleted_at
                  - deleted_by
                GET:
                  SINGLE: [ ] # request only
                  LIST: [ ] # request only
                POST:
                  SINGLE:
                    - id
                  LIST: [ ]
                PUT:
                  SINGLE:
                    - id
                  LIST:
                    - id
              api_endpoints:
                PUT: [ SINGLE, LIST ]
                GET: [ SINGLE, LIST ]
                POST: [ SINGLE, LIST ]
                DELETE: [ SINGLE, LIST ]
              extensions:
                audit_logger:
                  package: my_app.audit
                  handler: MyAuditHandler
                  handler_args:
                    name: hello
                soft_delete:
                  enable: True
                  default_field: deleted_at
                on_update_timestamp:
                  enable: True
                  default_field: updated_at
                on_create_timestamp:
                  enable: True
                  default_field: created_at
          tables:
            - name: book_category
              #      alias: ~
              #      id_field: ~ # id by default
              extensions:
                soft_delete:
                  cascade:
                    one_to_many:
                      - table: book
                        column_id: id
                        column_fk: book_category_id
            - name: book
              #      alias: ~
              #      id_field: ~ # id by default
              #      extensions:
              #        soft_delete:
              #          enable: False
              fields_excluded: # extends defaults
                #        all: [ ]
                #        GET:
                #          SINGLE:
                #            - name
                #          LIST: [ ]
                POST:
                  SINGLE:
                    - isin
            #          LIST: [ ]
            #        PUT:
            #          SINGLE:
            #            - name
            #          LIST: [ ]
            #        DELETE:
            #          SINGLE: [ ]
            #          LIST: [ ]
            #      api_endpoints:   #overwrite defaults
            #        GET: [ SINGLE ]
            - name: author
              #      alias: ~
              #      id_field: iso
              extensions:
                after_response:
                  package: my_app.default_events
                  handler: MyAfterResponseEvent
                before_response:
                  package: my_app.default_events
                  handler: MyBeforeResponseEvent
                soft_delete:
                  cascade:
                    many_to_many:
                      - table: author
                        column_id: id
                        join_table: book_has_author
                        join_columns:
                          main: author_id
                          join: book_id
                validators:
                  asin:
                    - package: wtforms.validators
                      handler: Length
                      handler_args:
                        min: 5
                        max: 100
              fields_excluded:
                #        all: []
                GET:
                  SINGLE:
                    - name
              #          LIST: [ ]
              #        POST:
              #          SINGLE: []
              #          LIST: [ ]
              #        PUT:
              #          SINGLE: []
              #          LIST: [ ]
              #        DELETE:
              #          SINGLE: [ ]
              #          LIST: [ ]
              api_endpoints: { }
            - name: dummy
              #      alias: ~
              #      id_field: ~
              extensions:
                soft_delete:
                  enable: False
                on_update_timestamp:
                  enable: False
                on_create_timestamp:
                  enable: False
              #      fields_excluded:
              #        all: [ ]
              #        GET:
              #          SINGLE: [ ]
              #          LIST: [ ]
              #        POST:
              #          SINGLE: [ ]
              #          LIST: [ ]
              #        PUT:
              #          SINGLE: [ ]
              #          LIST: [ ]
              #        DELETE:
              #          SINGLE: [ ]
              #          LIST: [ ]
              api_endpoints: { }
            - name: dummy_create
              #      alias: ~
              #      id_field: ~
              extensions:
                soft_delete:
                  enable: False
                on_update_timestamp:
                  enable: False
                on_create_timestamp:
                  enable: True
                  default_field: creation
              #      fields_excluded:
              #        all: [ ]
              #        GET:
              #          SINGLE: [ ]
              #          LIST: [ ]
              #        POST:
              #          SINGLE: [ ]
              #          LIST: [ ]
              #        PUT:
              #          SINGLE: [ ]
              #          LIST: [ ]
              #        DELETE:
              #          SINGLE: [ ]
              #          LIST: [ ]
              api_endpoints:
                GET: [ SINGLE, LIST ]
          sql:
            - name: tests
              method: GET
              url: /tests/test_sql
              sql: |
                select * from author
              query_parameters: [ ] # swagger schema for url query parameters in sql
              response_schema:
                type: object
            #        parameters:
            #          test:
            #            type: string
            - name: tests 2
              method: GET
              url: /tests/test_sql2
              sql: |
                select c.name as book_name, cr.*
                from book c
                inner join book_category cr ON cr.id = c.book_category_id AND c.name = :name
              query_parameters: # swagger schema for url query parameters in sql
                - in: query
                  name: name
                  #          required: true
                  schema:
                    type: string
            - name: test_params
              method: POST
              url: /test_params_post
              sql: |
                select c.name as book_name, cr.*
                from book c
                inner join book_category cr ON cr.id = c.book_category_id AND c.name = :name
              request_schema: # swagger schema for url query parameters in sql
                type: object
                properties:
                  name:
                    type: string
          #            required: true
          templates:
            - name: tests
              method: GET
              url: /test_template # swagger route format
              template: ./api_sql_templates/test.sql
              query_parameters: [ ] # swagger schema for url query parameters in sql
            - name: test_params
              method: GET
              url: /test_template_params
              template: ./api_sql_templates/test_params.sql
              query_parameters: # swagger schema for url query parameters in sql
                - in: query
                  name: name
                  #          required: true
                  schema:
                    type: string
            - name: test_params
              method: GET
              url: /test_template_params_url/<name>
              template: ./api_sql_templates/test_params.sql
              query_parameters: # swagger schema for url query parameters in sql
                - in: path
                  name: name
                  required: true
            #          schema:
            #            type: string
            - name: test_params
              method: POST
              url: /test_template_params
              template: ./api_sql_templates/test_params.sql
              request_schema: # swagger schema for url query parameters in sql
                type: object
                properties:
                  name:
                    type: string
        ```
        
        Create your app.py file
        ```python
        from chillapi.api import ChillApi
        
        _resources = ChillApi()
        app = _resources.app
        api_config = _resources.api_config
        if __name__ == '__main__':
            app.run(
                debug=api_config['app']['debug'],
                host=api_config['app']['host'],
                port=api_config['app']['port']
            )
        ```
        
        Run your app
        ```shell
        python gunicorn --bind 0.0.0.0:8000 app:app
        ```
        
        # The internals
        
        ## Database
        
        The milestone is support:
        
        - Postgres [x]
        - MySQL/MariDB
        - SQLite
        - Redshift
        
        DB connection and inspection is done using SQLAlchemy
        
        SQL queries are made with: https://github.com/kayak/pypika
        
        ### Special queries
        
        These queries are made to reduce the overhead in some cases such as a bulk delete where we validate if the ids provided are in our db first
        
        see: `chillapi.database.repository._MAGIC_QUERIES`
        
        # Endpoints
        
        Based on the config file.
        
        Extends from: `chillapi.swagger.http.AutomaticResource`
        
        ## Table type
        
        Automatically maps all the table and exposes all the columns.
        
        Exclusion by `excluded_fields` config
        
        As far this a direct map to the columns, the POST/PUT endpoints will require as request body these columns, and the response body will show that columns.
        
        DELETE and POST automatically attach the id the url, this field is mapper ti the `id_field` config
        
        Same way bulk operations will map the `id_field` config to the correspondent field in the request body.
        
        ## SQL Type
        
        This type of endpoint in the simplest case will throw a response with a json that contains the result of the SQl specified.
        
        In addition, you can use placeholders in your query and specify the proper swagger schema in the config.
        
        ## Template type
        
        Works in the same way that the SQL type, but you can specify a path to a template (larger sqls)
        
        # setup development
        
        ```shell
        cd $PROJECT_DIR
        ```
        
        ```shell
        docker-compose up
        ```
        
        ```shell
        make run_dev
        # or install by yourself the venv etc. You will need to have psycopg binary installed
        ```
        
        See `Makefile`
        
        # Other options
        
        https://github.com/dbohdan/automatic-api
        
Keywords: python,api,codeless,data
Platform: UNKNOWN
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Provides-Extra: testing
