Giter Club home page Giter Club logo

masonite4's People

Contributors

alitokmakci avatar erhuabushuo avatar girardinsamuel avatar josephmancuso avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

masonite4's Issues

Add exception handler feature

Currently the exception handler doesn't really operate like the other features. It's really its own thing. It should follow the same process as the white paper I think

Commands for file scaffolding

Need to create commands to scaffold:

  • Controllers
  • Queue Jobs (maybe should be bound in the queue provider?)
  • Mailables (Maybe should be bound in the mail provider)

Fix tinker command and improve shell

  • Fix tinker command (issue with wrong import)
  • Add ipython option to have an easy to use shell with preloaded helpers and models

Usage would be python craft tinker --ipython.
It would require pip install ipython first.

Add Testcases to quickly test scenarios

Database support should be separate. Possibly even connected to the Masonite ORM. You should be inheriting a class on your test case like:

class TestUsers(TestCase, DatabaseTransactions):
    # ...

File upload behaviour

When uploading a file using LocalDriver class, the store method returns the abs path to the file, but often in database
we want to store the path relative to the project. Then it's the role of e.g. the static template helper to build the path to the file depending on the driver. It's also important for static file serving to work.

For now in my project when I do:

path = self.application.make("storage").disk("local").store(my_file)

path is an absolute path. It was not the behaviour in M3

here is the path:
'/Users/sam/masonite-admin/tests/integrations/storage/uploads/70fc8f283543e77bd4434d00d6694a1dedf89454.png

maybe it should be only tests/integrations/storage/uploads/70fc8f283543e77bd4434d00d6694a1dedf89454.png
then static helper

static("local", "tests/integrations/storage/uploads/70fc8f283543e77bd4434d00d6694a1dedf89454.png") # == "/static/70fc8f283543e77bd4434d00d6694a1dedf89454.png"

and then it can be served by whitenoise if we have this config in Kernel

        storage.add_storage_assets(
            {
                # folder          # template alias
                "tests/integrations/storage/static": "static/",
                "tests/integrations/storage/compiled": "static/",
                "tests/integrations/storage/uploads": "static/",
                "tests/integrations/storage/public": "/",
            }
        )

View and routes registration

I open an issue here to keep in mind some features that Masonite 4 should be able to do.
Just to think about it during the rewrite (and maybe all of this is already possible in M3 ...)

  1. be able to use/load views from packages "masonite.mypackage.app" and so the package should be able to register it
  2. same things for route be able to use/load routes from packages (this I managed to do it with M3) but I guess it will be maybe easier to do it after the rewrite.

Note: I am not talking about publishing files which can be done right now (and that's useful too).
That's the the two things I have been struggling with when trying to build a cool way to register packages to Masonite

Add Helpers

This issue is easy. This is really just porting over the Helpers Provider from Masonite

Add back session assertions

These recently broke because of a change in how cookies are encrypted and decrypted. the failing tests are just commented out in the tests/tests/test_testcase.py file

Add DotEnv

Need to add support again for the dotenv for .env files

Fix inputs when using array based inputs

In html we can do something like:

<input type="text" name="comments[]" value="1">
<input type="text" name="comments[]" value="2">

When it submits it is currently submitting as 1 value:

{
   "comments": 2
}

It should be submitting like:

{
   "comments": [1,2]
}

When you submit an input like this:

<input type="text" name="comments[description]" value="1">
<input type="text" name="comments[name]" value="2">

It should look like this:

{
    "comments": {
        "description": 1,
        "name": 2
    }
}

and lastly it could get more advanced:

<input type="text" name="comments[options][description]" value="1">
<input type="text" name="comments[options][name]" value="2">

should compile down to:

{
    "comments": {
        "options": {
            "description": 1,
            "name": 2
        }
    }
}

Currently this advanced input doesn't work

Add Uploading support back (File system feature)

In Masonite M3 we can upload files to various places. Supported are local storage and Amazon S3..

The feature is extremely simple though and doesn't really support anything else.

We also have a Storage class which is a half-baked feature that tried to bridge the gap between storage and uploading.

I think we can take this and run with it and make it more similar to this Laravel https://laravel.com/docs/8.x/filesystem

Add way to override configuration during tests

I would like to be able to update configuration during unit tests.

(It could be handy to be able to do it outside of tests too ? (or maybe not))

What do we currently have to do now?
Now we can get config with config() helper but not set it.

Solutions I have in mind:
Solution 1/

from masonite.helpers import set_config
set_config("application.name", "Brand new name !")

Solution 2/
We can change environment loaded during tests, but changing env vars during a unit test does not change the config and the config() function still returns the same value.

Solution 3/
Create a Configuration provider, load it early in the app lifecycle and load in it configuration settings defined in config/,
the config helper would fetch settings from the configuration provider instead. settings would be maybe cached inside it to avoid accessing params from config files again.
Then it would be possible to set a config value because values would be hold inside this provider.

make("Configuration").update("app.name", "Masonite 4")
make("Configuration").get("app.name") #== config("app.name")

Solution 4/
As this would be mostly used during unit tests, maybe we can call "something" in setUp() to load a different configuration ?

Temporary workaround

from unittest.mock import patch

@patch("config.application.APP_NAME", "Masonite 4.0")   # patch one config value
@patch.dict("config.broadcast.DRIVERS", {"pusher": {"app_id": None, "client": None} })   # patch a whole config dict
def my_unit_test(self):
     pass

Totally open about this !

The idea is to be able to as in Laravel
https://laravel.com/docs/master/configuration#accessing-configuration-values
and Django
https://docs.djangoproject.com/en/3.1/topics/testing/tools/#overriding-settings

Add Mail Support

This is one of the features we will need to rethink. We need to structure the classes differently I think and add better support for things like Mailables and other type classes

Fix Routing

One of the issues with routing is that there is really no good encapsulation with the current structure.

Meaning that there are a lot of side effects, setting routing in 1 file could change routing in another file

Add utilities to ease creating packages

I started this for M3 and I would like to migrate it to M4. Two possibilities: either in M4 core or as an external package. For me it makes sense to have this into the core.

Different approachs can be used here to provide utilities to developers wanting to create a package. In this issue I am going down the road of the provider approach. This is a first draft proposal to explain how this could work with M4.
It's inspired from https://github.com/spatie/laravel-package-tools

Of course this might not be the best approach but that's a try ๐Ÿ˜…

Specifications

M4 could provide a PackageProvider that you can use in your packages, to easily:

  • register package configuration (and publish it if you want to override it)
  • register routes (and publish them if you want to override them)
  • register views (and publish them if you want to override them)
  • register migrations (and publish them if you want to override them)
  • register tests assertions
  • register assets (that the local project can find and serve => register a location.) (and publish them if you want to override them)
  • register commands

All files could be published by default under a configurable "vendor/package-name" namespace in locations defined in Kernel.py of project. So we would use what is defined in the container to build correct locations.

This is how it could look like:

from masonite.providers import PackageProvider

package_root_path = "path/to/package/root"

class MyPackageProvider(PackageProvider):

    def configure(self):
        self.name("my-package")
        self.add_config("test")
        self.add_command(MyCommand())
        self.add_routes("admin", "public", tag="my-routes")
        self.add_migrations("create_my_table", "create_my_other_package_table", tag="db")
        self.add_assets(
                {
                    "package.js": "app.js",
                    "package.css": None,
                    "sub/admin.js": "admin.js",
                }
       )
       seld.add_tests_assertions(CustomTestResponse)
       self.add_command(OtherCommand(), "DemoCommand")

M3 PackageProvider code for reference https://github.com/MasoniteFramework/masonite/pull/411/files#diff-26aa7ccb08af6962c9fcb17624445040dc5fefb313ff32a4ab939e8e2c7c0ed9 that could be used to rewrite that from scratch for M4. Here the PackageProvider, call configure method behind the scenes in the register() method. And add stuff in the boot method also.

Small details in API

  • Naming of methods could also be: self.routes(), self.register_routes(),
  • Each time we could add one element or several : what should be preferred ? add_commands(Command1, Command2), add_command(Command1)
  • For each kind of element we want to register it's important IMO to distinguish that the element is registered and available in the project but not copied over. If we wanted to override or extend the element then we can publish it to copy it into our projects. Example: I registered some routes from an external package. Those don't appear in my route files and it's ok. I want to customize route names or more, I will publish those routes into my project. This PackageProvider should handle both: register stuff in register() and in boot() make stuff available to be published.

Upgrade hupper to last version

I guess this major release might be the time to upgrade hupper and rewrite dev server if needed ? I did not really looked into how it was handled for M4. Is it a copy fof what's done in M3 ?

MasoniteFramework/masonite#369

still have the warning

======================================= warnings summary =======================================
../../../.pyenv/versions/3.9.1/lib/python3.9/site-packages/hupper/compat.py:2
  /Users/craggeek/.pyenv/versions/3.9.1/lib/python3.9/site-packages/hupper/compat.py:2: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
    import imp

-- Docs: https://docs.pytest.org/en/stable/warnings.html
================================= 2 passed, 1 warning in 0.73s =================================

Add back auth scaffolding

Need to relook at all the authentication scaffolding. Early days had a lot of rewrites in this.

We need to support controllers and routes for:

  • Login
  • Registration
  • Forgot password / Password resets (possibly need a new table for this called password_resets)
  • A generic home page when the user logs in.

Bring in Masonite essentials package

The Masonite essentials package is just a small package that has basically 1 middleware so can just bring that into M4 and archive that package

Add additional test assertions

@girardinsamuel

Before we dive too far into the framework I think it would be important to make sure that some of this stuff is testable. Some things with the request and response I was building out by testing it in the browser but it really should be testable first.

Also its important to test it in a way where a user can test it too. It's not just important to test core aspects of the framework but also important that a user can test their application too.

So because of that we need to be able to have as many assertions as possible. How the request works is we have a response_handler. this is largely the same handler as M3. Nothing really to discuss there. This response handler is bound to the container in the Kernel. This response handler is a WSGI standard and it runs through the framework and returns an iterable byte string and returns that to the browser.

BUT for testing purposes I added a testcase_handler which does the exact same thing as the normal handler but instead it returns the request and response as a tuple and accepts more parameters like the application.

Because of this we should now be able to assert things on the response, request and route. We just need those things built out which is what this ticket is for.

At a minimum we should be able to do all the assertions that Masonite had and we can explore other frameworks for anymore assertions they have.

Add priority to mailable classes

Can either do something like this or this when building mails:

.subject("Password Reset").priority(1)
.subject("Password Reset").high_priority()

or both and high_priority is just an alias for priority(1)

Deploy masonite4-template to 4.X branch of cookie-cutter

Update

https://github.com/girardinsamuel/masonite4-template needs to be deployed as a 4.X branch in the cookie-cutter repo
so that we can craft new project with M4.


The title is a bit wrong as we should not enforce a project layout, but what I meant was that we need at least a configuration file like the Kernel.py file.

  • We should first define how it will work
  • Then add the default project layout in cookie-cutter 4 that craft new will use. (Are we still going to need this ?)

Remove dependency between signing cookies and unsigning cookies

Right now the request class needs the sign dependency. But I think we can remove the dependency if we just don't encrypt cookies on the request class but we have a middleware between requests that encrypts and decrypts them between request and response ..

Add exception listeners

This is a feature of Masonite where we can listen to multiple exceptions. But maybe this should tie into the Masonite events system ..

Add static file serving

I played with file uploads for masonite-admin ๐Ÿ˜‰ . It's working great. But then I tried to display a user avatar (e.g to serve an image from masonite) it did not work => I did not found static files handling feature. It was there in M3.

I guess it have to be implemented, the same way ?

  • static helpers for view
  • static url path
  • binding to multiple dirs
  • interaction with storage ? For now disk().store(...) return the full path to the file. In database we want to store a relative path that the static helper will be able to resolve later I guess ?

Suggestion for Masonite 4 APIs

I worked quite a lot with Masonite when it was at version 2.3.20 or so, since I really liked the framework. The only bad thing was that I found it quite troublesome to get it fully working for pure REST APIs, and attempts to remove folders such as resources and storage which contained templates and javascript/css etc.

The reason I wanted to remove these folders and everything related to Views was because a pure REST API will never use Views to return any HTML-formatted code (like Laravel blades). It will only return raw JSON blobs/data.

When reading the White Paper for Masonite 4, I noticed the following statements under Kernel Classes:

"Kernel classes is really just a service provider that only registers things to the application class that is crucial to making the framework work. For example, we need to know where the config directories are, the view directories, controller directories, bind middleware, etc."

The view directory (similar to Laravel blades) seems to be considered a core part of the framework (which it obviously is for MVC), which makes me worried that it again will be troublesome to use Masonite for APIs (since an API should return data, NOT a View.)

Considering we are in 2021 and web development is going further and further in the direction of only using REST/CRUD/Graph APIs, my suggestion is to keep this in mind when developing Masonite once again from scratch. I truly believe that a clean and simple way to create APIs with Masonite will attract a lot of new users.

Lastly, the paragraph above is not meant to be critical or negative. It is more that I really would like this project to be as good as possible, because I really believe it has the potential.

It would be nice to see this out of the box in M4, allowing new users to create APIs with just a few commands and defining their routes exactly like its done today.

Ability to mock services

I played with this for M3 here
MasoniteFramework/masonite#406
In short, the idea is to swap the provider with a testing one which is mocking the "external" part (sending an email for Mail class, pushing on a real queue for Queue class ...). On this mocked provider, some handy assertions are available.

If you think it's in the spirit of M4/the way to go to add some good testing capabilities, I would be glad to integrate this into M4

Password is not hashed automatically when saved to database

But maybe it should be done manually and it's a not bug.

user = User.create({..."password": "secret"})
user.password #== secret

I guess we should be able to hash it before storing it in database, and it should be taken care of automatically for Users ?

Need to delay queue jobs

One requirement I missed on the queue jobs was the ability to delay a job for later. For example if we want to send a welcome email 1 hour after a user signed up:

self.app.make('queue').push(SendWelcomeJob(), delay="1 hour")

Something like this. For the async driver I think we can ignore it but for the database driver we have an available_at field we need to populate

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.