mirror of
https://github.com/vlang/v.git
synced 2025-09-08 23:07:19 -04:00
veb: deprecate x.vweb in favor of veb; checker: show missing variants in the sumtype error
This commit is contained in:
parent
ceac4baf87
commit
ae1b9ed571
@ -1,5 +1,5 @@
|
||||
import time
|
||||
import x.vweb
|
||||
import veb
|
||||
|
||||
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
||||
// and https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#preflighted_requests
|
||||
@ -7,24 +7,26 @@ import x.vweb
|
||||
// > a server to indicate any origins (domain, scheme, or port) other than its own from
|
||||
// > which a browser should permit loading resources...
|
||||
|
||||
// Usage: do `./v run examples/xvweb/cors/` to start the app,
|
||||
// Usage: do `./v run examples/xveb/cors/` to start the app,
|
||||
// then check the headers in another shell:
|
||||
//
|
||||
// 1) `curl -vvv -X OPTIONS http://localhost:45678/time`
|
||||
// 2) `curl -vvv -X POST http://localhost:45678/time`
|
||||
|
||||
pub struct Context {
|
||||
vweb.Context
|
||||
veb.Context
|
||||
}
|
||||
|
||||
pub struct App {
|
||||
vweb.Middleware[Context]
|
||||
veb.Middleware[Context]
|
||||
}
|
||||
|
||||
// time is a simple POST request handler, that returns the current time. It should be available
|
||||
// to JS scripts, running on arbitrary other origins/domains.
|
||||
|
||||
// pub fn (app &App) time() veb.Result {
|
||||
@[post]
|
||||
pub fn (app &App) time(mut ctx Context) vweb.Result {
|
||||
pub fn (app &App) time(mut ctx Context) veb.Result {
|
||||
return ctx.json({
|
||||
'time': time.now().format_ss_milli()
|
||||
})
|
||||
@ -32,9 +34,8 @@ pub fn (app &App) time(mut ctx Context) vweb.Result {
|
||||
|
||||
fn main() {
|
||||
println("
|
||||
To test, if CORS works, copy this JS snippet, then go to for example https://stackoverflow.com/ ,
|
||||
press F12, then paste the snippet in the opened JS console. You should see the vweb server's time:
|
||||
|
||||
To test, if CORS works, copy this JS snippet, then go to for example https://stackoverflow.com/ ,
|
||||
press F12, then paste the snippet in the opened JS console. You should see the veb server's time:
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.onload = function(data) {
|
||||
console.log('xhr loaded');
|
||||
@ -46,13 +47,13 @@ xhr.send();
|
||||
|
||||
mut app := &App{}
|
||||
|
||||
// use vweb's cors middleware to handle CORS requests
|
||||
app.use(vweb.cors[Context](vweb.CorsOptions{
|
||||
// use veb's cors middleware to handle CORS requests
|
||||
app.use(veb.cors[Context](veb.CorsOptions{
|
||||
// allow CORS requests from every domain
|
||||
origins: ['*']
|
||||
// allow CORS requests with the following request methods:
|
||||
allowed_methods: [.get, .head, .patch, .put, .post, .delete]
|
||||
}))
|
||||
|
||||
vweb.run[App, Context](mut app, 45678)
|
||||
veb.run[App, Context](mut app, 45678)
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
// Simple TODO app using x.vweb
|
||||
// Simple TODO app using veb
|
||||
// Run from this directory with `v run main.v`
|
||||
// You can also enable vwebs livereload feature with
|
||||
// `v watch -d vweb_livereload run main.v`
|
||||
// You can also enable vebs livereload feature with
|
||||
// `v watch -d veb_livereload run main.v`
|
||||
module main
|
||||
|
||||
import x.vweb
|
||||
import veb
|
||||
import db.sqlite
|
||||
import os
|
||||
import time
|
||||
@ -21,14 +21,14 @@ pub mut:
|
||||
}
|
||||
|
||||
pub struct Context {
|
||||
vweb.Context
|
||||
veb.Context
|
||||
pub mut:
|
||||
// we can use this field to check whether we just created a TODO in our html templates
|
||||
created_todo bool
|
||||
}
|
||||
|
||||
pub struct App {
|
||||
vweb.StaticHandler
|
||||
veb.StaticHandler
|
||||
pub:
|
||||
// we can access the SQLITE database directly via `app.db`
|
||||
db sqlite.DB
|
||||
@ -36,16 +36,16 @@ pub:
|
||||
|
||||
// This method will only handle GET requests to the index page
|
||||
@[get]
|
||||
pub fn (app &App) index(mut ctx Context) vweb.Result {
|
||||
pub fn (app &App) index(mut ctx Context) veb.Result {
|
||||
todos := sql app.db {
|
||||
select from Todo
|
||||
} or { return ctx.server_error('could not fetch todos from database!') }
|
||||
return $vweb.html()
|
||||
return $veb.html()
|
||||
}
|
||||
|
||||
// This method will only handle POST requests to the index page
|
||||
@['/'; post]
|
||||
pub fn (app &App) create_todo(mut ctx Context, name string) vweb.Result {
|
||||
pub fn (app &App) create_todo(mut ctx Context, name string) veb.Result {
|
||||
// We can receive form input fields as arguments in a route!
|
||||
// we could also access the name field by doing `name := ctx.form['name']`
|
||||
|
||||
@ -78,7 +78,7 @@ pub fn (app &App) create_todo(mut ctx Context, name string) vweb.Result {
|
||||
}
|
||||
|
||||
@['/todo/:id/complete'; post]
|
||||
pub fn (app &App) complete_todo(mut ctx Context, id int) vweb.Result {
|
||||
pub fn (app &App) complete_todo(mut ctx Context, id int) veb.Result {
|
||||
// first check if there exist a TODO record with `id`
|
||||
todos := sql app.db {
|
||||
select from Todo where id == id
|
||||
@ -99,7 +99,7 @@ pub fn (app &App) complete_todo(mut ctx Context, id int) vweb.Result {
|
||||
}
|
||||
|
||||
@['/todo/:id/delete'; post]
|
||||
pub fn (app &App) delete_todo(mut ctx Context, id int) vweb.Result {
|
||||
pub fn (app &App) delete_todo(mut ctx Context, id int) veb.Result {
|
||||
// first check if there exist a TODO record with `id`
|
||||
todos := sql app.db {
|
||||
select from Todo where id == id
|
||||
@ -141,5 +141,5 @@ fn main() {
|
||||
}!
|
||||
|
||||
// start our app at port 8080
|
||||
vweb.run[App, Context](mut app, 8080)
|
||||
veb.run[App, Context](mut app, 8080)
|
||||
}
|
@ -1,14 +1,14 @@
|
||||
module main
|
||||
|
||||
import x.vweb
|
||||
import veb
|
||||
import os
|
||||
|
||||
pub struct Context {
|
||||
vweb.Context
|
||||
veb.Context
|
||||
}
|
||||
|
||||
pub struct App {
|
||||
vweb.StaticHandler
|
||||
veb.StaticHandler
|
||||
}
|
||||
|
||||
fn main() {
|
||||
@ -17,5 +17,5 @@ fn main() {
|
||||
os.chdir(os.dir(os.executable()))!
|
||||
mut app := &App{}
|
||||
app.handle_static('dist', true)!
|
||||
vweb.run[App, Context](mut app, 8080)
|
||||
veb.run[App, Context](mut app, 8080)
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ pub fn (app &App) before_request() {
|
||||
|
||||
@['/users/:user']
|
||||
pub fn (mut app App) user_endpoint(mut ctx Context, user string) veb.Result {
|
||||
// pub fn (mut app App) user_endpoint(user string) veb.Result {
|
||||
id := rand.intn(100) or { 0 }
|
||||
return ctx.json({
|
||||
user: id
|
||||
|
@ -940,6 +940,14 @@ pub fn (s string) rsplit_once(delim string) ?(string, string) {
|
||||
return result[1], result[0]
|
||||
}
|
||||
|
||||
// split_n splits the string based on the passed `delim` substring.
|
||||
// It returns the first Nth parts. When N=0, return all the splits.
|
||||
// The last returned element has the remainder of the string, even if
|
||||
// the remainder contains more `delim` substrings.
|
||||
pub fn (s string) split_n(delim string, n int) []string {
|
||||
return s.split_nth(delim, n)
|
||||
}
|
||||
|
||||
// split_nth splits the string based on the passed `delim` substring.
|
||||
// It returns the first Nth parts. When N=0, return all the splits.
|
||||
// The last returned element has the remainder of the string, even if
|
||||
|
@ -533,12 +533,11 @@ pub fn (t &Table) find_field(s &TypeSymbol, name string) !StructField {
|
||||
}
|
||||
SumType {
|
||||
t.resolve_common_sumtype_fields(mut ts)
|
||||
if field := ts.info.find_field(name) {
|
||||
if field := ts.info.find_sum_type_field(name) {
|
||||
return field
|
||||
}
|
||||
// mut info := ts.info as SumType
|
||||
// TODO: a more detailed error so that it's easier to fix?
|
||||
return error('field `${name}` does not exist or have the same type in all sumtype variants')
|
||||
missing_variants := t.find_missing_variants(ts.info, name)
|
||||
return error('field `${name}` does not exist or have the same type in these sumtype `${ts.name}` variants: ${missing_variants}')
|
||||
}
|
||||
else {}
|
||||
}
|
||||
|
@ -1748,7 +1748,7 @@ pub fn (t &TypeSymbol) find_field(name string) ?StructField {
|
||||
Aggregate { return t.info.find_field(name) }
|
||||
Struct { return t.info.find_field(name) }
|
||||
Interface { return t.info.find_field(name) }
|
||||
SumType { return t.info.find_field(name) }
|
||||
SumType { return t.info.find_sum_type_field(name) }
|
||||
else { return none }
|
||||
}
|
||||
}
|
||||
@ -1811,7 +1811,7 @@ pub fn (s Struct) get_field(name string) StructField {
|
||||
panic('unknown field `${name}`')
|
||||
}
|
||||
|
||||
pub fn (s &SumType) find_field(name string) ?StructField {
|
||||
pub fn (s &SumType) find_sum_type_field(name string) ?StructField {
|
||||
for mut field in unsafe { s.fields } {
|
||||
if field.name == name {
|
||||
return field
|
||||
@ -1820,6 +1820,34 @@ pub fn (s &SumType) find_field(name string) ?StructField {
|
||||
return none
|
||||
}
|
||||
|
||||
// For the 'field does not exist or have the same type in all sumtype variants' error.
|
||||
// To print all sumtype variants the developer has to fix.
|
||||
pub fn (t &Table) find_missing_variants(s &SumType, field_name string) string {
|
||||
mut res := []string{cap: 5}
|
||||
for variant in s.variants {
|
||||
ts := t.sym(variant)
|
||||
if ts.kind != .struct_ {
|
||||
continue
|
||||
}
|
||||
mut found := false
|
||||
struct_info := ts.info as Struct
|
||||
for field in struct_info.fields {
|
||||
if field.name == field_name {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
res << ts.name
|
||||
}
|
||||
}
|
||||
// println('!!!!! field_name=${field_name}')
|
||||
// print_backtrace()
|
||||
// println(res)
|
||||
str := res.join(', ')
|
||||
return str.replace("'", '`')
|
||||
}
|
||||
|
||||
pub fn (i Interface) defines_method(name string) bool {
|
||||
if i.methods.any(it.name == name) {
|
||||
return true
|
||||
|
@ -953,7 +953,7 @@ fn (mut c Checker) fail_if_immutable(mut expr ast.Expr) (string, token.Pos) {
|
||||
}
|
||||
.sum_type {
|
||||
sumtype_info := typ_sym.info as ast.SumType
|
||||
mut field_info := sumtype_info.find_field(expr.field_name) or {
|
||||
mut field_info := sumtype_info.find_sum_type_field(expr.field_name) or {
|
||||
type_str := c.table.type_to_str(expr.expr_type)
|
||||
c.error('unknown field `${type_str}.${expr.field_name}`', expr.pos)
|
||||
return '', expr.pos
|
||||
@ -1596,6 +1596,12 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type {
|
||||
node.from_embed_types = embed_types
|
||||
if sym.kind in [.aggregate, .sum_type] {
|
||||
unknown_field_msg = err.msg()
|
||||
// TODO need a better way to check that we need to display sum type variants info
|
||||
if unknown_field_msg.contains('does not exist or have the same type in all sumtype') {
|
||||
info := sym.info as ast.SumType
|
||||
missing_variants := c.table.find_missing_variants(info, field_name)
|
||||
unknown_field_msg += missing_variants
|
||||
}
|
||||
}
|
||||
}
|
||||
if !c.inside_unsafe {
|
||||
@ -2598,6 +2604,9 @@ fn (mut c Checker) hash_stmt(mut node ast.HashStmt) {
|
||||
}
|
||||
|
||||
fn (mut c Checker) import_stmt(node ast.Import) {
|
||||
if node.mod == 'x.vweb' {
|
||||
println('`x.vweb` is now `veb`. The module is no longer experimental. Simply `import veb` instead of `import x.vweb`.')
|
||||
}
|
||||
c.check_valid_snake_case(node.alias, 'module alias', node.pos)
|
||||
for sym in node.syms {
|
||||
name := '${node.mod}.${sym.name}'
|
||||
|
@ -215,6 +215,7 @@ fn (mut c Checker) deprecate(kind string, name string, attrs []ast.Attr, pos tok
|
||||
c.warn(semicolonize('${start_message} has been deprecated since ${after_time.ymmdd()}, it will be an error after ${error_time.ymmdd()}',
|
||||
deprecation_message), pos)
|
||||
} else if after_time == now {
|
||||
// print_backtrace()
|
||||
c.warn(semicolonize('${start_message} has been deprecated', deprecation_message),
|
||||
pos)
|
||||
// c.warn(semicolonize('${start_message} has been deprecated!11 m=${deprecation_message}',
|
||||
|
@ -433,6 +433,36 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||
}
|
||||
}
|
||||
c.fn_scope = node.scope
|
||||
// Register implicit context var
|
||||
typ_veb_result := c.table.find_type_idx('veb.Result')
|
||||
if node.return_type == typ_veb_result {
|
||||
typ_veb_context := c.table.find_type_idx('veb.Context')
|
||||
// No `ctx` param? Add it
|
||||
if !node.params.any(it.name == 'ctx') && node.params.len > 1 {
|
||||
params := node.params.clone()
|
||||
ctx_param := ast.Param{
|
||||
name: 'ctx'
|
||||
typ: typ_veb_context
|
||||
is_mut: true
|
||||
}
|
||||
node.params = [node.params[0], ctx_param]
|
||||
node.params << params[1..]
|
||||
println('new params ${node.name}')
|
||||
// println(node.params)
|
||||
}
|
||||
// sym := c.table.sym(typ_veb_context)
|
||||
// println('reging ${typ_veb_context} ${sym}')
|
||||
// println(c.fn_scope)
|
||||
// println(node.params)
|
||||
c.fn_scope.register(ast.Var{
|
||||
name: 'ctx'
|
||||
typ: typ_veb_context
|
||||
pos: node.pos
|
||||
is_used: true
|
||||
is_mut: true
|
||||
is_stack_obj: false // true
|
||||
})
|
||||
}
|
||||
c.stmts(mut node.stmts)
|
||||
node_has_top_return := has_top_return(node.stmts)
|
||||
node.has_return = c.returns || node_has_top_return
|
||||
@ -1058,6 +1088,7 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.
|
||||
}
|
||||
}
|
||||
|
||||
// XTODO document
|
||||
if typ != 0 {
|
||||
generic_vts := c.table.final_sym(typ)
|
||||
if generic_vts.info is ast.FnType {
|
||||
@ -1902,7 +1933,7 @@ fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
|
||||
}
|
||||
left_type := c.expr(mut node.left)
|
||||
if left_type == ast.void_type {
|
||||
c.error('cannot call a method using an invalid expression', node.pos)
|
||||
// c.error('cannot call a method using an invalid expression', node.pos)
|
||||
return ast.void_type
|
||||
}
|
||||
c.expected_type = left_type
|
||||
@ -2726,7 +2757,8 @@ fn (mut c Checker) post_process_generic_fns() ! {
|
||||
for concrete_types in gtypes {
|
||||
c.table.cur_concrete_types = concrete_types
|
||||
c.fn_decl(mut node)
|
||||
if node.name in ['x.vweb.run', 'x.vweb.run_at', 'vweb.run', 'vweb.run_at'] {
|
||||
if node.name in ['veb.run', 'veb.run_at', 'x.vweb.run', 'x.vweb.run_at', 'vweb.run',
|
||||
'vweb.run_at'] {
|
||||
for ct in concrete_types {
|
||||
if ct !in c.vweb_gen_types {
|
||||
c.vweb_gen_types << ct
|
||||
|
@ -67,6 +67,7 @@ fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
|
||||
cond_typ := c.table.unaliased_type(c.unwrap_generic(c.expr(mut branch.cond)))
|
||||
if (cond_typ.idx() != ast.bool_type_idx || cond_typ.has_flag(.option)
|
||||
|| cond_typ.has_flag(.result)) && !c.pref.translated && !c.file.is_translated {
|
||||
//&& cond_typ.idx() != ast.void_type_idx { TODO bring back after the void split
|
||||
c.error('non-bool type `${c.table.type_to_str(cond_typ)}` used as if condition',
|
||||
branch.cond.pos())
|
||||
}
|
||||
|
@ -799,9 +799,12 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
||||
}
|
||||
.and, .logical_or {
|
||||
if !c.pref.translated && !c.file.is_translated {
|
||||
// TODO Bring back once I split void into void and bad
|
||||
// if left_final_sym.kind !in [.bool, .void] {
|
||||
if left_final_sym.kind != .bool {
|
||||
c.error('left operand for `${node.op}` is not a boolean', node.left.pos())
|
||||
}
|
||||
// if right_final_sym.kind !in [.bool, .void] {
|
||||
if right_final_sym.kind != .bool {
|
||||
c.error('right operand for `${node.op}` is not a boolean', node.right.pos())
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ vlib/v/checker/tests/incorrect_smartcast2_err.vv:24:9: notice: smartcast can onl
|
||||
| ~~~
|
||||
25 | Left[int] {
|
||||
26 | println(v[0].error)
|
||||
vlib/v/checker/tests/incorrect_smartcast2_err.vv:26:17: error: field `error` does not exist or have the same type in all sumtype variants
|
||||
vlib/v/checker/tests/incorrect_smartcast2_err.vv:26:17: error: field `error` does not exist or have the same type in these sumtype `Either[int, int]` variants: Right[int]
|
||||
24 | match v[0] {
|
||||
25 | Left[int] {
|
||||
26 | println(v[0].error)
|
||||
|
@ -1,4 +1,4 @@
|
||||
vlib/v/checker/tests/sum_type_common_fields_alias_error.vv:35:14: error: field `name` does not exist or have the same type in all sumtype variants
|
||||
vlib/v/checker/tests/sum_type_common_fields_alias_error.vv:35:14: error: field `name` does not exist or have the same type in these sumtype `Main` variants:
|
||||
33 | }
|
||||
34 | println(m)
|
||||
35 | assert m[0].name == 'abc'
|
||||
@ -12,7 +12,7 @@ vlib/v/checker/tests/sum_type_common_fields_alias_error.vv:35:9: error: assert c
|
||||
| ~~~~~~~~~~~~~~~~~~
|
||||
36 | assert m[1].name == 'def'
|
||||
37 | assert m[2].name == 'xyz'
|
||||
vlib/v/checker/tests/sum_type_common_fields_alias_error.vv:36:14: error: field `name` does not exist or have the same type in all sumtype variants
|
||||
vlib/v/checker/tests/sum_type_common_fields_alias_error.vv:36:14: error: field `name` does not exist or have the same type in these sumtype `Main` variants:
|
||||
34 | println(m)
|
||||
35 | assert m[0].name == 'abc'
|
||||
36 | assert m[1].name == 'def'
|
||||
@ -26,7 +26,7 @@ vlib/v/checker/tests/sum_type_common_fields_alias_error.vv:36:9: error: assert c
|
||||
| ~~~~~~~~~~~~~~~~~~
|
||||
37 | assert m[2].name == 'xyz'
|
||||
38 | }
|
||||
vlib/v/checker/tests/sum_type_common_fields_alias_error.vv:37:14: error: field `name` does not exist or have the same type in all sumtype variants
|
||||
vlib/v/checker/tests/sum_type_common_fields_alias_error.vv:37:14: error: field `name` does not exist or have the same type in these sumtype `Main` variants:
|
||||
35 | assert m[0].name == 'abc'
|
||||
36 | assert m[1].name == 'def'
|
||||
37 | assert m[2].name == 'xyz'
|
||||
|
@ -1,4 +1,4 @@
|
||||
vlib/v/checker/tests/sum_type_common_fields_error.vv:53:14: error: field `val` does not exist or have the same type in all sumtype variants
|
||||
vlib/v/checker/tests/sum_type_common_fields_error.vv:53:14: error: field `val` does not exist or have the same type in these sumtype `Main` variants:
|
||||
51 | assert m[2].name == '64bit integer'
|
||||
52 | assert m[3].name == 'string'
|
||||
53 | assert m[0].val == 123
|
||||
|
@ -1,5 +1,5 @@
|
||||
vlib/v/checker/tests/void_method_call.vv:5:17: error: cannot call a method using an invalid expression
|
||||
3 |
|
||||
vlib/v/checker/tests/void_method_call.vv:5:17: cgen error: checker bug; CallExpr.left_type is 0 in method_call
|
||||
3 |
|
||||
4 | fn main() {
|
||||
5 | simple_fn().method()
|
||||
| ~~~~~~~~
|
||||
|
@ -109,7 +109,7 @@ pub fn (f &Fmt) type_to_str_using_aliases(typ ast.Type, import_aliases map[strin
|
||||
println('${s}')
|
||||
}
|
||||
if s.starts_with('x.vweb') {
|
||||
s = s.replace_once('x.vweb', 'veb.')
|
||||
s = s.replace_once('x.vweb.', 'veb.')
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
@ -168,11 +168,11 @@ fn (mut g Gen) comptime_call(mut node ast.ComptimeCall) {
|
||||
} else {
|
||||
if !has_decompose {
|
||||
// do not generate anything if the argument lengths don't match
|
||||
g.writeln('/* skipping ${sym.name}.${m.name} due to mismatched arguments list */')
|
||||
g.writeln('/* skipping ${sym.name}.${m.name} due to mismatched arguments list: node.args=${node.args.len} m.params=${m.params.len} */')
|
||||
// g.writeln('println(_SLIT("skipping ${node.sym.name}.$m.name due to mismatched arguments list"));')
|
||||
// eprintln('info: skipping ${node.sym.name}.$m.name due to mismatched arguments list\n' +
|
||||
//'method.params: $m.params, args: $node.args\n\n')
|
||||
// verror('expected ${m.params.len-1} arguments to method ${node.sym.name}.$m.name, but got $node.args.len')
|
||||
// verror('expected ${m.params.len - 1} arguments to method ${node.sym.name}.${m.name}, but got ${node.args.len}')
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -704,6 +704,20 @@ fn (mut g Gen) fn_decl_params(params []ast.Param, scope &ast.Scope, is_variadic
|
||||
// in C, `()` is untyped, unlike `(void)`
|
||||
g.write('void')
|
||||
}
|
||||
/// mut is_implicit_ctx := false
|
||||
// Veb actions defined by user can have implicit context
|
||||
/*
|
||||
if g.cur_fn != unsafe { nil } && g.cur_fn.is_method && g.cur_mod.name != 'veb' {
|
||||
typ_veb_result := g.table.find_type_idx('veb.Result')
|
||||
// if params.len == 3 {
|
||||
// println(g.cur_fn)
|
||||
//}
|
||||
if g.cur_fn.return_type == typ_veb_result {
|
||||
// is_implicit_ctx = true
|
||||
g.write('/*veb*/')
|
||||
}
|
||||
}
|
||||
*/
|
||||
for i, param in params {
|
||||
mut caname := if param.name == '_' {
|
||||
g.new_tmp_declaration_name()
|
||||
@ -756,6 +770,11 @@ fn (mut g Gen) fn_decl_params(params []ast.Param, scope &ast.Scope, is_variadic
|
||||
g.write(', ')
|
||||
g.definitions.write_string(', ')
|
||||
}
|
||||
|
||||
// if is_implicit_ctx && i == 0 && params[1].name != 'ctx' {
|
||||
// g.writeln('veb__Context* ctx,')
|
||||
// g.definitions.write_string('veb__Context* ctx,')
|
||||
//}
|
||||
}
|
||||
if (g.pref.translated && is_variadic) || is_c_variadic {
|
||||
g.write(', ... ')
|
||||
|
@ -306,6 +306,7 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||
|
||||
handle_vweb(mut table, mut all_fn_root_names, 'vweb.Result', 'vweb.filter', 'vweb.Context')
|
||||
handle_vweb(mut table, mut all_fn_root_names, 'x.vweb.Result', 'x.vweb.filter', 'x.vweb.Context')
|
||||
handle_vweb(mut table, mut all_fn_root_names, 'veb.Result', 'veb.filter', 'veb.Context')
|
||||
|
||||
// handle ORM drivers:
|
||||
orm_connection_implementations := table.iface_types['orm.Connection'] or { []ast.Type{} }
|
||||
|
@ -591,6 +591,16 @@ run them via `v file.v` instead',
|
||||
language: language
|
||||
})
|
||||
}
|
||||
/*
|
||||
// Register implicit context var
|
||||
p.scope.register(ast.Var{
|
||||
name: 'ctx'
|
||||
typ: ast.error_type
|
||||
pos: p.tok.pos()
|
||||
is_used: true
|
||||
is_stack_obj: true
|
||||
})
|
||||
*/
|
||||
// Body
|
||||
p.cur_fn_name = name
|
||||
mut stmts := []ast.Stmt{}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import x.vweb
|
||||
import veb
|
||||
import time
|
||||
|
||||
pub struct App {}
|
||||
|
||||
pub struct Context {
|
||||
vweb.Context
|
||||
veb.Context
|
||||
}
|
||||
|
||||
fn main() {
|
||||
@ -15,10 +15,10 @@ fn main() {
|
||||
}()
|
||||
time.sleep(10 * time.second)
|
||||
mut app := &App{}
|
||||
vweb.run_at[App, Context](mut app, port: 38090)!
|
||||
veb.run_at[App, Context](mut app, port: 38090)!
|
||||
}
|
||||
|
||||
@['/']
|
||||
pub fn (app &App) index(mut ctx Context) vweb.Result {
|
||||
pub fn (app &App) index(mut ctx Context) veb.Result {
|
||||
return ctx.text('Hello World')
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import net.http
|
||||
import time
|
||||
import x.sessions
|
||||
import x.vweb
|
||||
import veb
|
||||
import x.sessions.vweb2_middleware
|
||||
|
||||
const port = 13010
|
||||
@ -24,12 +24,12 @@ const default_user = User{
|
||||
}
|
||||
|
||||
pub struct Context {
|
||||
vweb.Context
|
||||
veb.Context
|
||||
sessions.CurrentSession[User]
|
||||
}
|
||||
|
||||
pub struct App {
|
||||
vweb.Middleware[Context]
|
||||
veb.Middleware[Context]
|
||||
pub mut:
|
||||
sessions &sessions.Sessions[User]
|
||||
started chan bool
|
||||
@ -39,11 +39,11 @@ pub fn (mut app App) before_accept_loop() {
|
||||
app.started <- true
|
||||
}
|
||||
|
||||
pub fn (app &App) session_data(mut ctx Context) vweb.Result {
|
||||
pub fn (app &App) session_data(mut ctx Context) veb.Result {
|
||||
return ctx.text(ctx.session_data.str())
|
||||
}
|
||||
|
||||
pub fn (app &App) protected(mut ctx Context) vweb.Result {
|
||||
pub fn (app &App) protected(mut ctx Context) veb.Result {
|
||||
if user := ctx.session_data {
|
||||
return ctx.json(user)
|
||||
} else {
|
||||
@ -52,12 +52,12 @@ pub fn (app &App) protected(mut ctx Context) vweb.Result {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut app App) save_session(mut ctx Context) vweb.Result {
|
||||
pub fn (mut app App) save_session(mut ctx Context) veb.Result {
|
||||
app.sessions.save(mut ctx, default_user) or { return ctx.server_error(err.msg()) }
|
||||
return ctx.ok('')
|
||||
}
|
||||
|
||||
pub fn (mut app App) update_session(mut ctx Context) vweb.Result {
|
||||
pub fn (mut app App) update_session(mut ctx Context) veb.Result {
|
||||
if mut user := ctx.session_data {
|
||||
user.age++
|
||||
app.sessions.save(mut ctx, user) or { return ctx.server_error(err.msg()) }
|
||||
@ -72,7 +72,7 @@ pub fn (mut app App) update_session(mut ctx Context) vweb.Result {
|
||||
return ctx.ok('')
|
||||
}
|
||||
|
||||
pub fn (mut app App) destroy_session(mut ctx Context) vweb.Result {
|
||||
pub fn (mut app App) destroy_session(mut ctx Context) veb.Result {
|
||||
app.sessions.destroy(mut ctx) or { return ctx.server_error(err.msg()) }
|
||||
// sessions module should also update the context
|
||||
assert ctx.session_data == none
|
||||
@ -100,7 +100,7 @@ fn testsuite_begin() {
|
||||
|
||||
app.use(vweb2_middleware.create[User, Context](mut app.sessions))
|
||||
|
||||
spawn vweb.run_at[App, Context](mut app, port: port, timeout_in_seconds: 2)
|
||||
spawn veb.run_at[App, Context](mut app, port: port, timeout_in_seconds: 2)
|
||||
// app startup time
|
||||
_ := <-app.started
|
||||
}
|
||||
|
@ -1,15 +1,15 @@
|
||||
module vweb2_middleware
|
||||
|
||||
import x.sessions
|
||||
import x.vweb
|
||||
import veb
|
||||
|
||||
// middleware can be used to add session middleware to your vweb app to ensure
|
||||
// a valid session always exists. If a valid session exists the session data will
|
||||
// be loaded into `session_data`, else a new session id will be generated.
|
||||
// You have to pass the Context type as the generic type
|
||||
// Example: app.use(app.sessions.middleware[Context]())
|
||||
pub fn create[T, X](mut s sessions.Sessions[T]) vweb.MiddlewareOptions[X] {
|
||||
return vweb.MiddlewareOptions[X]{
|
||||
pub fn create[T, X](mut s sessions.Sessions[T]) veb.MiddlewareOptions[X] {
|
||||
return veb.MiddlewareOptions[X]{
|
||||
handler: fn [mut s] [T, X](mut ctx X) bool {
|
||||
// a session id is retrieved from the client, so it must be considered
|
||||
// untrusted and has to be verified on every request
|
||||
|
@ -1,4 +1,4 @@
|
||||
//@[deprecated: '`x.vweb` is now `veb`. The module is no longer experimental.']
|
||||
@[deprecated: '`x.vweb` is now `veb`. The module is no longer experimental. Simply import veb instead of x.vweb']
|
||||
module vweb
|
||||
|
||||
import io
|
||||
|
Loading…
x
Reference in New Issue
Block a user