feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
This commit is contained in:
Vendored
+35
@@ -0,0 +1,35 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "argparse" for ArgumentParser
|
||||
|
||||
System.print("=== Argparse Module Demo ===")
|
||||
|
||||
System.print("\n--- Basic Usage ---")
|
||||
var parser = ArgumentParser.new("A sample program")
|
||||
parser.prog = "sample"
|
||||
parser.addArgument("input", {"help": "Input file"})
|
||||
parser.addArgument("-o", {"long": "--output", "default": "output.txt", "help": "Output file"})
|
||||
parser.addArgument("-v", {"long": "--verbose", "action": "storeTrue", "help": "Verbose output"})
|
||||
parser.addArgument("-n", {"type": "int", "default": 1, "help": "Number of iterations"})
|
||||
|
||||
System.print("Help message:")
|
||||
parser.printHelp()
|
||||
|
||||
System.print("\n--- Parsing Example Args ---")
|
||||
var args = parser.parseArgs(["data.txt", "-v", "-n", "5", "--output", "result.txt"])
|
||||
System.print("Input: %(args["input"])")
|
||||
System.print("Output: %(args["output"])")
|
||||
System.print("Verbose: %(args["verbose"])")
|
||||
System.print("Iterations: %(args["n"])")
|
||||
|
||||
System.print("\n--- Count Action ---")
|
||||
var parser2 = ArgumentParser.new()
|
||||
parser2.addArgument("-v", {"action": "count"})
|
||||
var args2 = parser2.parseArgs(["-v", "-v", "-v"])
|
||||
System.print("Verbosity level: %(args2["v"])")
|
||||
|
||||
System.print("\n--- Append Action ---")
|
||||
var parser3 = ArgumentParser.new()
|
||||
parser3.addArgument("-i", {"long": "--include", "action": "append"})
|
||||
var args3 = parser3.parseArgs(["-i", "module1", "-i", "module2", "--include", "module3"])
|
||||
System.print("Included modules: %(args3["include"])")
|
||||
Vendored
+39
@@ -0,0 +1,39 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "bytes" for Bytes
|
||||
|
||||
System.print("=== Bytes Module Demo ===\n")
|
||||
|
||||
System.print("--- fromList / toList ---")
|
||||
var list = [72, 101, 108, 108, 111]
|
||||
var str = Bytes.fromList(list)
|
||||
System.print("fromList([72, 101, 108, 108, 111]) = %(str)")
|
||||
System.print("toList(%(str)) = %(Bytes.toList(str))")
|
||||
|
||||
System.print("\n--- length ---")
|
||||
System.print("length('Hello World') = %(Bytes.length("Hello World"))")
|
||||
|
||||
System.print("\n--- concat ---")
|
||||
var a = "Hello"
|
||||
var b = " World"
|
||||
System.print("concat('%(a)', '%(b)') = %(Bytes.concat(a, b))")
|
||||
|
||||
System.print("\n--- slice ---")
|
||||
var data = "Hello World"
|
||||
System.print("slice('%(data)', 0, 5) = %(Bytes.slice(data, 0, 5))")
|
||||
System.print("slice('%(data)', 6, 11) = %(Bytes.slice(data, 6, 11))")
|
||||
|
||||
System.print("\n--- xorMask ---")
|
||||
var payload = Bytes.fromList([1, 2, 3, 4, 5, 6, 7, 8])
|
||||
var mask = Bytes.fromList([0x12, 0x34, 0x56, 0x78])
|
||||
var masked = Bytes.xorMask(payload, mask)
|
||||
System.print("Original: %(Bytes.toList(payload))")
|
||||
System.print("Mask: %(Bytes.toList(mask))")
|
||||
System.print("XOR'd: %(Bytes.toList(masked))")
|
||||
var unmasked = Bytes.xorMask(masked, mask)
|
||||
System.print("Unmasked: %(Bytes.toList(unmasked))")
|
||||
|
||||
System.print("\n--- Binary data handling ---")
|
||||
var binary = Bytes.fromList([0, 127, 128, 255])
|
||||
System.print("Binary data length: %(Bytes.length(binary))")
|
||||
System.print("Binary data bytes: %(Bytes.toList(binary))")
|
||||
Vendored
+52
@@ -0,0 +1,52 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "dataset" for Dataset
|
||||
|
||||
System.print("=== Dataset Module Demo ===")
|
||||
|
||||
var ds = Dataset.memory()
|
||||
|
||||
System.print("\n--- Insert Records ---")
|
||||
var users = ds["users"]
|
||||
var alice = users.insert({"name": "Alice", "age": 30, "email": "alice@example.com"})
|
||||
System.print("Inserted: %(alice["name"]) with uid: %(alice["uid"])")
|
||||
|
||||
var bob = users.insert({"name": "Bob", "age": 25, "email": "bob@example.com"})
|
||||
var charlie = users.insert({"name": "Charlie", "age": 35, "email": "charlie@example.com"})
|
||||
|
||||
System.print("Total users: %(users.count())")
|
||||
|
||||
System.print("\n--- Query Records ---")
|
||||
var all = users.all()
|
||||
System.print("All users:")
|
||||
for (user in all) {
|
||||
System.print(" - %(user["name"]) (%(user["age"]))")
|
||||
}
|
||||
|
||||
System.print("\nUsers older than 28:")
|
||||
var older = users.find({"age__gt": 28})
|
||||
for (user in older) {
|
||||
System.print(" - %(user["name"])")
|
||||
}
|
||||
|
||||
System.print("\n--- Update Record ---")
|
||||
users.update({"uid": alice["uid"], "age": 31})
|
||||
var updated = users.findOne({"uid": alice["uid"]})
|
||||
System.print("Alice's new age: %(updated["age"])")
|
||||
|
||||
System.print("\n--- Delete Record ---")
|
||||
System.print("Before delete: %(users.count()) users")
|
||||
users.delete(bob["uid"])
|
||||
System.print("After delete: %(users.count()) users")
|
||||
|
||||
System.print("\n--- Auto Schema ---")
|
||||
var products = ds["products"]
|
||||
products.insert({"name": "Widget", "price": 9.99})
|
||||
products.insert({"name": "Gadget", "price": 19.99, "stock": 100})
|
||||
System.print("Product columns: %(products.columns.keys.toList)")
|
||||
|
||||
System.print("\n--- Tables ---")
|
||||
System.print("All tables: %(ds.tables)")
|
||||
|
||||
ds.close()
|
||||
System.print("\nDone.")
|
||||
Vendored
+39
@@ -0,0 +1,39 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "html" for Html
|
||||
|
||||
System.print("=== HTML Module Demo ===")
|
||||
|
||||
System.print("\n--- URL Encoding ---")
|
||||
var text = "hello world & special=chars"
|
||||
var encoded = Html.urlencode(text)
|
||||
var decoded = Html.urldecode(encoded)
|
||||
System.print("Original: %(text)")
|
||||
System.print("Encoded: %(encoded)")
|
||||
System.print("Decoded: %(decoded)")
|
||||
|
||||
System.print("\n--- Slugify ---")
|
||||
var titles = [
|
||||
"Hello World",
|
||||
"This is a Test Article!",
|
||||
"Product Name (2024)",
|
||||
"FAQ & Help"
|
||||
]
|
||||
for (title in titles) {
|
||||
System.print("%(title) -> %(Html.slugify(title))")
|
||||
}
|
||||
|
||||
System.print("\n--- HTML Escaping ---")
|
||||
var unsafe = "<script>alert('XSS')</script>"
|
||||
var safe = Html.quote(unsafe)
|
||||
System.print("Unsafe: %(unsafe)")
|
||||
System.print("Safe: %(safe)")
|
||||
System.print("Unescaped: %(Html.unquote(safe))")
|
||||
|
||||
System.print("\n--- Query Parameters ---")
|
||||
var params = {"name": "John Doe", "city": "New York", "age": 30}
|
||||
var queryString = Html.encodeParams(params)
|
||||
System.print("Params: %(params)")
|
||||
System.print("Query string: %(queryString)")
|
||||
var parsed = Html.decodeParams(queryString)
|
||||
System.print("Parsed back: %(parsed)")
|
||||
Vendored
+52
@@ -0,0 +1,52 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "markdown" for Markdown
|
||||
|
||||
System.print("=== Markdown Module Demo ===")
|
||||
|
||||
var markdown = "# Welcome to Markdown
|
||||
|
||||
This is a **bold** statement and this is *italic*.
|
||||
|
||||
## Features
|
||||
|
||||
- Easy to read
|
||||
- Easy to write
|
||||
- Converts to HTML
|
||||
|
||||
### Code Example
|
||||
|
||||
Here is some `inline code`.
|
||||
|
||||
```
|
||||
function hello() {
|
||||
console.log(\"Hello, World!\")
|
||||
}
|
||||
```
|
||||
|
||||
### Links and Images
|
||||
|
||||
Check out [Wren](https://wren.io) for more info.
|
||||
|
||||

|
||||
|
||||
> This is a blockquote.
|
||||
> It can span multiple lines.
|
||||
|
||||
---
|
||||
|
||||
1. First item
|
||||
2. Second item
|
||||
3. Third item
|
||||
|
||||
That's all folks!"
|
||||
|
||||
System.print("\n--- Source Markdown ---")
|
||||
System.print(markdown)
|
||||
|
||||
System.print("\n--- Generated HTML ---")
|
||||
System.print(Markdown.toHtml(markdown))
|
||||
|
||||
System.print("\n--- Safe Mode Example ---")
|
||||
var unsafe = "# Title\n\n<script>alert('xss')</script>\n\nSafe content."
|
||||
System.print(Markdown.toHtml(unsafe, {"safeMode": true}))
|
||||
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "uuid" for Uuid
|
||||
|
||||
System.print("=== UUID Module Demo ===")
|
||||
|
||||
System.print("\n--- Generating UUIDs ---")
|
||||
for (i in 1..5) {
|
||||
System.print("UUID %(i): %(Uuid.v4())")
|
||||
}
|
||||
|
||||
System.print("\n--- UUID Validation ---")
|
||||
var testUuid = Uuid.v4()
|
||||
System.print("Generated: %(testUuid)")
|
||||
System.print("isValid: %(Uuid.isValid(testUuid))")
|
||||
System.print("isV4: %(Uuid.isV4(testUuid))")
|
||||
|
||||
System.print("\n--- Invalid UUID Examples ---")
|
||||
var invalidUuids = [
|
||||
"invalid",
|
||||
"550e8400-e29b-41d4-a716",
|
||||
"550e8400-e29b-41d4-a716-44665544000X",
|
||||
123
|
||||
]
|
||||
for (uuid in invalidUuids) {
|
||||
System.print("%(uuid): isValid = %(Uuid.isValid(uuid))")
|
||||
}
|
||||
Vendored
+72
@@ -0,0 +1,72 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "wdantic" for Validator, Schema, Field
|
||||
|
||||
System.print("=== Wdantic Module Demo ===")
|
||||
|
||||
System.print("\n--- Validators ---")
|
||||
var testEmail = "user@example.com"
|
||||
System.print("Email '%(testEmail)' valid: %(Validator.email(testEmail))")
|
||||
|
||||
var testUrl = "https://example.com/path"
|
||||
System.print("URL '%(testUrl)' valid: %(Validator.url(testUrl))")
|
||||
|
||||
var testUuid = "550e8400-e29b-41d4-a716-446655440000"
|
||||
System.print("UUID '%(testUuid)' valid: %(Validator.uuid(testUuid))")
|
||||
|
||||
System.print("\n--- Schema Validation ---")
|
||||
var userSchema = Schema.new({
|
||||
"name": Field.string({"minLength": 1, "maxLength": 100}),
|
||||
"age": Field.integer({"min": 0, "max": 150}),
|
||||
"email": Field.email(),
|
||||
"active": Field.boolean()
|
||||
})
|
||||
|
||||
var validUser = {
|
||||
"name": "John Doe",
|
||||
"age": 30,
|
||||
"email": "john@example.com",
|
||||
"active": true
|
||||
}
|
||||
|
||||
var result = userSchema.validate(validUser)
|
||||
System.print("Valid user result: %(result.isValid)")
|
||||
if (result.isValid) {
|
||||
System.print("Validated data: %(result.data)")
|
||||
}
|
||||
|
||||
System.print("\n--- Invalid Data ---")
|
||||
var invalidUser = {
|
||||
"name": "",
|
||||
"age": -5,
|
||||
"email": "not-an-email",
|
||||
"active": "yes"
|
||||
}
|
||||
|
||||
var result2 = userSchema.validate(invalidUser)
|
||||
System.print("Invalid user result: %(result2.isValid)")
|
||||
System.print("Errors:")
|
||||
for (error in result2.errors) {
|
||||
System.print(" - %(error)")
|
||||
}
|
||||
|
||||
System.print("\n--- Optional Fields ---")
|
||||
var profileSchema = Schema.new({
|
||||
"username": Field.string(),
|
||||
"bio": Field.optional(Field.string({"maxLength": 500})),
|
||||
"website": Field.optional(Field.string())
|
||||
})
|
||||
|
||||
var minimalProfile = {"username": "alice"}
|
||||
var fullProfile = {"username": "bob", "bio": "Developer", "website": "https://bob.dev"}
|
||||
|
||||
System.print("Minimal profile valid: %(profileSchema.validate(minimalProfile).isValid)")
|
||||
System.print("Full profile valid: %(profileSchema.validate(fullProfile).isValid)")
|
||||
|
||||
System.print("\n--- List Validation ---")
|
||||
var tagsSchema = Schema.new({
|
||||
"tags": Field.list(Field.string())
|
||||
})
|
||||
|
||||
var tagData = {"tags": ["wren", "programming", "cli"]}
|
||||
System.print("Tags valid: %(tagsSchema.validate(tagData).isValid)")
|
||||
Vendored
+122
@@ -0,0 +1,122 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "web" for Application, Response, View
|
||||
import "wdantic" for Schema, Field
|
||||
import "dataset" for Dataset
|
||||
import "uuid" for Uuid
|
||||
import "json" for Json
|
||||
|
||||
var db = Dataset.memory()
|
||||
var messages = db["messages"]
|
||||
|
||||
var messageSchema = Schema.new({
|
||||
"username": Field.string({"minLength": 1, "maxLength": 50}),
|
||||
"content": Field.string({"minLength": 1, "maxLength": 500})
|
||||
})
|
||||
|
||||
class MessagesView is View {
|
||||
get(request) {
|
||||
var allMessages = messages.all()
|
||||
return Response.json(allMessages)
|
||||
}
|
||||
|
||||
post(request) {
|
||||
var data = request.json
|
||||
var result = messageSchema.validate(data)
|
||||
if (!result.isValid) {
|
||||
var r = Response.json({"error": "Validation failed", "details": result.errors.map { |e| e.toString }.toList})
|
||||
r.status = 400
|
||||
return r
|
||||
}
|
||||
var msg = messages.insert({
|
||||
"username": data["username"],
|
||||
"content": data["content"]
|
||||
})
|
||||
return Response.json(msg)
|
||||
}
|
||||
}
|
||||
|
||||
class MessageView is View {
|
||||
get(request) {
|
||||
var id = request.params["id"]
|
||||
var msg = messages.findOne({"uid": id})
|
||||
if (msg == null) {
|
||||
var r = Response.json({"error": "Message not found"})
|
||||
r.status = 404
|
||||
return r
|
||||
}
|
||||
return Response.json(msg)
|
||||
}
|
||||
|
||||
delete(request) {
|
||||
var id = request.params["id"]
|
||||
var deleted = messages.delete(id)
|
||||
if (!deleted) {
|
||||
var r = Response.json({"error": "Message not found"})
|
||||
r.status = 404
|
||||
return r
|
||||
}
|
||||
return Response.json({"status": "deleted"})
|
||||
}
|
||||
}
|
||||
|
||||
var indexHtml = "<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Chat Demo</title>
|
||||
<style>
|
||||
body { font-family: sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
|
||||
#messages { border: 1px solid #ccc; padding: 10px; height: 300px; overflow-y: auto; margin-bottom: 10px; }
|
||||
.message { margin: 5px 0; padding: 5px; background: #f5f5f5; }
|
||||
.message .username { font-weight: bold; }
|
||||
form { display: flex; gap: 10px; }
|
||||
input, button { padding: 8px; }
|
||||
input[name=content] { flex: 1; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Chat Demo</h1>
|
||||
<div id=\"messages\"></div>
|
||||
<form id=\"form\">
|
||||
<input name=\"username\" placeholder=\"Username\" required>
|
||||
<input name=\"content\" placeholder=\"Message\" required>
|
||||
<button type=\"submit\">Send</button>
|
||||
</form>
|
||||
<script>
|
||||
async function loadMessages() {
|
||||
const res = await fetch('/api/messages');
|
||||
const msgs = await res.json();
|
||||
const div = document.getElementById('messages');
|
||||
div.innerHTML = msgs.map(m =>
|
||||
'<div class=\"message\"><span class=\"username\">' + m.username + ':</span> ' + m.content + '</div>'
|
||||
).join('');
|
||||
div.scrollTop = div.scrollHeight;
|
||||
}
|
||||
document.getElementById('form').onsubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
const form = e.target;
|
||||
await fetch('/api/messages', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({
|
||||
username: form.username.value,
|
||||
content: form.content.value
|
||||
})
|
||||
});
|
||||
form.content.value = '';
|
||||
loadMessages();
|
||||
};
|
||||
loadMessages();
|
||||
setInterval(loadMessages, 3000);
|
||||
</script>
|
||||
</body>
|
||||
</html>"
|
||||
|
||||
var app = Application.new()
|
||||
|
||||
app.get("/", Fn.new { |req| Response.html(indexHtml) })
|
||||
app.addView("/api/messages", MessagesView)
|
||||
app.addView("/api/messages/:id", MessageView)
|
||||
|
||||
System.print("Chat demo running on http://localhost:8080")
|
||||
app.run("0.0.0.0", 8080)
|
||||
Vendored
+58
@@ -0,0 +1,58 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "web" for Application, Response, View
|
||||
import "json" for Json
|
||||
|
||||
class HelloView is View {
|
||||
get(request) {
|
||||
return Response.text("Hello, World!")
|
||||
}
|
||||
}
|
||||
|
||||
class ApiView is View {
|
||||
get(request) {
|
||||
var data = {"message": "API response", "method": "GET"}
|
||||
return Response.json(data)
|
||||
}
|
||||
|
||||
post(request) {
|
||||
var body = request.json
|
||||
var data = {"message": "Data received", "received": body}
|
||||
return Response.json(data)
|
||||
}
|
||||
}
|
||||
|
||||
class UserView is View {
|
||||
get(request) {
|
||||
var userId = request.params["id"]
|
||||
return Response.json({"user_id": userId, "action": "get"})
|
||||
}
|
||||
}
|
||||
|
||||
var app = Application.new()
|
||||
|
||||
app.get("/", Fn.new { |req|
|
||||
return Response.html("<h1>Welcome to Wren Web!</h1><p>A simple web framework.</p>")
|
||||
})
|
||||
|
||||
app.addView("/hello", HelloView)
|
||||
app.addView("/api", ApiView)
|
||||
app.addView("/users/:id", UserView)
|
||||
|
||||
app.get("/greet/:name", Fn.new { |req|
|
||||
var name = req.params["name"]
|
||||
return Response.text("Hello, " + name + "!")
|
||||
})
|
||||
|
||||
app.get("/session", Fn.new { |req|
|
||||
var count = req.session["count"]
|
||||
if (count == null) count = 0
|
||||
count = count + 1
|
||||
req.session["count"] = count
|
||||
return Response.json({"visit_count": count})
|
||||
})
|
||||
|
||||
app.static_("/static", "./static")
|
||||
|
||||
System.print("Starting server...")
|
||||
app.run("0.0.0.0", 8080)
|
||||
Reference in New Issue
Block a user