Skip to content

Add Cask tutorials #3056

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Oct 1, 2024
Merged

Add Cask tutorials #3056

merged 6 commits into from
Oct 1, 2024

Conversation

gkepka
Copy link
Contributor

@gkepka gkepka commented Aug 12, 2024

The scala-cli part needs some attention. While code compiles and starts without any problems, the process end immediately after being started. In SBT the same problem can be solved by setting fork := true, but I wasn't able to find any similar solution for scala-cli.

@sjrd
Copy link
Member

sjrd commented Aug 13, 2024

The scala-cli part needs some attention. While code compiles and starts without any problems, the process end immediately after being started. In SBT the same problem can be solved by setting fork := true, but I wasn't able to find any similar solution for scala-cli.

In order to troubleshoot and isolate the problem: have you tried adding a while (true) {} loop at the end of main?

Copy link
Member

@sjrd sjrd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall the structure and amount of details seem good to me. Here are some localized comments.

@@ -0,0 +1,146 @@
---
title: How to serve a static file?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
title: How to serve a static file?
title: A minimal Cask server

See my other comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to preserve the "How to [do X]" title convention, used in all the other tutorials. I imagine that's what a person in a need for guidance would search for.

@gkepka
Copy link
Contributor Author

gkepka commented Aug 26, 2024

The problem with scala-cli turned out to be caused by the difference between how files with .sc and .scala extensions are handled. It turns out that while the .scala files are executed as written, the contents of .sc files are wrapped in an auto-generated main function, ignoring all main functions defined in the code. The documentation for scala-cli makes a very good job at hiding that distinction, I managed to find it descibed here.

Copy link
Member

@sjrd sjrd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks much better now, IMO!

There are a number of English grammar issues that we should fix. Let's discuss offline how you prefer me to report them.

@@ -65,17 +71,17 @@ In the terminal, the following command will start the server:
{% endtab %}
{% endtabs %}

Access the endpoint at [http://localhost:8080/time](http://localhost:8080/time). You should see a result similar to the
one below.
Access [the endpoint](http://localhost:8080/time). You should see a result similar to the one below.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO the previous text, with the link appearing in the text, was better here. We should actively show the user that we're sending them to a localhost URL.

@gkepka gkepka marked this pull request as ready for review September 9, 2024 09:17
Copy link
Member

@sjrd sjrd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Final English grammar and style comments.

{% tabs cask-install class=tabs-build-tool %}

{% tab 'Scala CLI' %}
You can declare dependency on Cask with `using` directive:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
You can declare dependency on Cask with `using` directive:
You can declare a dependency on Cask with the following `using` directive:

Comment on lines 16 to 18
In this example, we are building a rudimentary authentication service. The `getLogin` method provides a form where
username and password can be inputted. The `postLogin` reads the credentials and, if they match the expected ones, a session
identifier is generated, saved in the application state, and sends back a cookie with the identifier.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In this example, we are building a rudimentary authentication service. The `getLogin` method provides a form where
username and password can be inputted. The `postLogin` reads the credentials and, if they match the expected ones, a session
identifier is generated, saved in the application state, and sends back a cookie with the identifier.
In this example, we are building a rudimentary authentication service. The `getLogin` method provides a form where
the user can enter their username and password. The `postLogin` method reads the credentials. If they match the expected ones, it generates a session
identifier, saves it in the application state, and sends back a cookie with the identifier.

username and password can be inputted. The `postLogin` reads the credentials and, if they match the expected ones, a session
identifier is generated, saved in the application state, and sends back a cookie with the identifier.

Cookies can be read either with a method parameter of `cask.Cookie` type or by accessing `cask.Request` directly.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Cookies can be read either with a method parameter of `cask.Cookie` type or by accessing `cask.Request` directly.
Cookies can be read either with a method parameter of `cask.Cookie` type or by accessing the `cask.Request` directly.

## Using decorators

Decorators can be used for extending endpoints functionality with validation or new parameters. They are defined by extending
`cask.RawDecorator` class and then used as annotations.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
`cask.RawDecorator` class and then used as annotations.
the `cask.RawDecorator` class. They are then used as annotations.


## Serving dynamically generated content

You can create an endpoint returning dynamically generated content with `@cask.get` annotation.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
You can create an endpoint returning dynamically generated content with `@cask.get` annotation.
You can create an endpoint returning dynamically generated content with the `@cask.get` annotation.

`src/main/resources` directory. Cask will match any subpath coming after `/static` and append it to the directory path.
If you access the `/static/hello.html` file, it will serve the file available at `src/main/resources/hello.html`.
The directory path can be any path available to the server, relative or not. If the requested file cannot be found in the
specified location, a 404 response with an error message will be returned instead.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
specified location, a 404 response with an error message will be returned instead.
specified location, the server will return a 404 response with an error message.

The directory path can be any path available to the server, relative or not. If the requested file cannot be found in the
specified location, a 404 response with an error message will be returned instead.

The `Example` object inherits from the `cask.MainRoutes` class, providing the main function that starts the server. The `initialize()`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The `Example` object inherits from the `cask.MainRoutes` class, providing the main function that starts the server. The `initialize()`
The `Example` object inherits from the `cask.MainRoutes` class. It provides the main function that starts the server. The `initialize()`

{% endtabs %}

In the endpoint method, the location is set to `"."`, telling the server that the files are available directly in the
resources directory. In general, you can use any nested location within the resources directory, for instance you could opt
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
resources directory. In general, you can use any nested location within the resources directory, for instance you could opt
resources directory. In general, you can use any nested location within the resources directory. For instance, you could opt

Comment on lines 12 to 14
You can create a WebSocket endpoint by using the `@cask.websocket` annotation. The endpoint method can return either a
`cask.WsHandler` instance defining how the communication should take place, or a `cask.Response`, which rejects the
attempt at forming a WebSocket connection.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
You can create a WebSocket endpoint by using the `@cask.websocket` annotation. The endpoint method can return either a
`cask.WsHandler` instance defining how the communication should take place, or a `cask.Response`, which rejects the
attempt at forming a WebSocket connection.
You can create a WebSocket endpoint with the `@cask.websocket` annotation. The endpoint method should return a
`cask.WsHandler` instance defining how the communication should take place. It can also return a `cask.Response`, which rejects the
attempt at forming a WebSocket connection.

Comment on lines 116 to 118
In the `cask.WsHandler` we define a `cask.WsActor` which reacts to events (of `cask.util.Ws.Event` type) and uses
WebSocket channel to send messages. In this example, we receive the name of a city and return the current time there. If server
receives an empty message, the connection is closed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In the `cask.WsHandler` we define a `cask.WsActor` which reacts to events (of `cask.util.Ws.Event` type) and uses
WebSocket channel to send messages. In this example, we receive the name of a city and return the current time there. If server
receives an empty message, the connection is closed.
In the `cask.WsHandler` we define a `cask.WsActor`. It reacts to events (of type `cask.util.Ws.Event`) and uses the
WebSocket channel to send messages. In this example, we receive the name of a city and return the current time there. If the server
receives an empty message, the connection is closed.

@sjrd sjrd merged commit 02c00cc into scala:main Oct 1, 2024
1 check passed
fResult pushed a commit to fResult/docs.scala-lang that referenced this pull request Oct 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants