From cb705f3db03001646172c8f690b24eec68057d07 Mon Sep 17 00:00:00 2001 From: David Boyne Date: Tue, 5 Nov 2024 16:04:28 +0000 Subject: [PATCH] chore(docs): moved api lang docs into the learn by docs (#7217) Fixed for #7216 This merges the https://www.winglang.io/docs/api/language and https://www.winglang.io/docs/learn sections together. The information from https://www.winglang.io/docs/api/language was duplicated in the wing learn by sections, and some stuff was missing all together. This just cleans it up. Next phase it actually reviewing the "Getting Started" and "Learn" sections and stream lining into stuff that makes more sense for people learning Wing. I like have rust have done it (https://www.rust-lang.org/learn) with install and learn, with learn forking off into courses, books, learn by, and examples... I think there is much we can learn from here. This PR is a small step to that direction. --- docs/api/01-api.md | 4 +- .../03-language/01-variable-declaration.md | 44 ------ docs/api/03-language/02-primitives.md | 78 ---------- docs/api/03-language/03-functions.md | 51 ------- docs/api/03-language/04-flow-controls.md | 107 -------------- docs/api/03-language/05-optionality.md | 97 ------------- docs/api/03-language/06-json.md | 131 ----------------- docs/api/03-language/07-structs.md | 76 ---------- docs/api/03-language/13-api-gateway.md | 76 ---------- docs/api/03-language/_category_.yml | 7 - docs/by-example/03-values.md | 96 ++++++++++--- docs/by-example/04-variables.md | 49 ++++--- docs/by-example/06-ifelse.md | 32 +++-- docs/by-example/07-while.md | 24 +++- docs/by-example/08-optionality.md | 91 +++++++++++- docs/by-example/12-structs.md | 35 +++-- docs/by-example/14-functions.md | 19 ++- ...-functions.md => 14-variadic-functions.md} | 2 +- .../15-classes.md} | 64 ++++----- .../15-singletons.md} | 16 ++- docs/by-example/23-Json.md | 134 +++++++++++++----- docs/by-example/34-http-server.md | 81 +++++++++++ .../37-extern.md} | 21 ++- 23 files changed, 509 insertions(+), 826 deletions(-) delete mode 100644 docs/api/03-language/01-variable-declaration.md delete mode 100644 docs/api/03-language/02-primitives.md delete mode 100644 docs/api/03-language/03-functions.md delete mode 100644 docs/api/03-language/04-flow-controls.md delete mode 100644 docs/api/03-language/05-optionality.md delete mode 100644 docs/api/03-language/06-json.md delete mode 100644 docs/api/03-language/07-structs.md delete mode 100644 docs/api/03-language/13-api-gateway.md delete mode 100644 docs/api/03-language/_category_.yml rename docs/by-example/{15-variadic-functions.md => 14-variadic-functions.md} (95%) rename docs/{api/03-language/08-classes.md => by-example/15-classes.md} (52%) rename docs/{api/03-language/14-singletons.md => by-example/15-singletons.md} (75%) rename docs/{api/03-language/10-using-javascript.md => by-example/37-extern.md} (66%) diff --git a/docs/api/01-api.md b/docs/api/01-api.md index ab45f57c655..d3924ef6044 100644 --- a/docs/api/01-api.md +++ b/docs/api/01-api.md @@ -12,8 +12,8 @@ keywords: [Wing language, api] - [CLI User Manual](/docs/api/cli) - Learn and explore the Wing Cli -- [Wing Language](/docs/api/language/variable-declaration) - - Dive deeper into the Wing Language, learn how to [declare variables](/docs/api/language/variable-declaration), [functions](/docs/api/language/functions-example), [structs](/docs/api/language/structs) and much more. +- [Wing Language](/docs/learn) + - Dive deeper into the Wing Language, learn how to [declare variables](/docs/learn/Variables), [functions](/docs/learn/functions), [structs](/docs/learn/structs) and much more. - [Standard Library](/docs/api/standard-library) - API references for the Wing standard library and supported modules - [Language Reference](/docs/api/language-reference) diff --git a/docs/api/03-language/01-variable-declaration.md b/docs/api/03-language/01-variable-declaration.md deleted file mode 100644 index 3a8cfd48233..00000000000 --- a/docs/api/03-language/01-variable-declaration.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Variable declaration -id: variable-declaration -keywords: [Wing example] ---- - -### Assignment - -```ts example{valid: false} -let x = 12; -x = 77; // error: Variable is not reassignable -``` - -```ts example -let var y = "hello"; -y = "world"; // OK (y is reassignable) -``` - -### Inferred typing -```ts playground example -let x1 = 12; -let x2: num = 12; // equivalent -``` - -### Optionals -```ts playground example{valid: false} -let var x1 = "Hello"; // type str, value "Hello" -let var x2: str = "Hello"; // same as above -let var x3: str? = "Hello"; // type str? (optional), value "Hello" -let var x4: str? = nil; // type str? (optional), value nil - -x1 = nil; // ERROR: Expected type to be "str", but got "nil" instead -x3 = nil; // OK (x3 is optional) -``` -### Scopes -```ts example -let s = "parent"; -log(s); // prints parent -if true { - let s = "inner"; - log(s); // prints inner -} -log(s); // prints parent -``` diff --git a/docs/api/03-language/02-primitives.md b/docs/api/03-language/02-primitives.md deleted file mode 100644 index b6208d69c91..00000000000 --- a/docs/api/03-language/02-primitives.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -title: Primitives -id: primitives -keywords: [Wing example] ---- - - -## Str -### Concat and Interpolate -```ts example -let s1 = "Hello Wing String"; -log(s1); // prints Hello Wing String -let s2 = "Interpolate: {s1}"; // string interpolation -log(s2); // prints Interpolate Hello Wing String -let s3 = "Concat: " + s1; // string concatenation -log(s3); // prints Concat: Hello Wing String -``` - -### Str methods -```ts example -let s = "Hello to a new Wing world"; - -// lets start with split -for w in s.split(" ") { - if w.startsWith("H") { - log(w); // 'Hello' starts with H - } - if w.length > 3 && w.lowercase() == w { - log(w); // 'world' is lowercased with more then 3 chars - } - if w.contains("in") && w.endsWith("g") { - log(w); // 'Wing' has in and end with g - } - if s.indexOf(w) == 6 { - log(w); // 'to' position is 6 - } - if s.at(9) == w { - log(w); // 'a' is a single char - } - if s.substring(11,14) == w { - log(w); // 'new' position is 11-14 - } -} -``` - -## Num - -```ts example -let n1 = 10; -log("{n1}"); // 10 - -let n2 = n1 - 10 / 10 + 1 * 10 ; // arithmetic -log("{n2}"); // 1 - -let n3 = 10 % 7; // modulo -log("{n3}"); // 3 - -let n4 = 10 \ 7; // FloorDiv -log("{n4}"); // 1 - -let n5 = 2 ** 10; // power of -log("{n5}"); // 1024 - -let n6 = (10 + 1) / (12 - 1) + (20 / 2) * 2 + 10 * 2**10 / 512 + 1; -log("{n6}"); // The meaning of the universe -``` - - -## Bool - -```ts example -let b1 = true; -let b2 = false; - -if b1 && !b2 { - log("b1:{b1},b2:{b2}"); // prints b1:true, b2:false -} -``` diff --git a/docs/api/03-language/03-functions.md b/docs/api/03-language/03-functions.md deleted file mode 100644 index 77830f153df..00000000000 --- a/docs/api/03-language/03-functions.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -title: Functions -id: functions-example -keywords: [Wing example] ---- - - -### Preflight function - -```ts playground example -// preflight function - when declared in preflight context -let dup = (s: str, count: num) => { - // code -}; -``` - -### Inflight functions - -Inflight functions are Wing's distributed computing primitive. They are isolated code blocks which can be packaged and executed on compute platforms in the cloud (such as containers, Lambda/Cloud Function, etc..). - -```ts playground example - -let handler = inflight (message: str): void => { - // using the inflight modifier - let dup = inflight (s: str, count: num) => { - // code - }; - // inflight modifier is not required when function is declared in inflight context - let sup = (s: str, count: num) => { - // code - }; -}; -``` -### Struct Expansion -```ts playground example -struct Options { - prefix: str?; - delim: str; -} - -let join_str = (a: Array, opts: Options):str => { - let prefix = opts.prefix ?? ""; - return prefix + a.join(opts.delim); -}; - -log(join_str(["hello", "world"], delim: ", ")); // "!hello.world" - -// also OK to pass an object -let opts = Options { delim: "/" , prefix: "!!" }; -log(join_str(["hello", "world"], opts)); // "!!hello/world"); -``` diff --git a/docs/api/03-language/04-flow-controls.md b/docs/api/03-language/04-flow-controls.md deleted file mode 100644 index ce8c63e45c4..00000000000 --- a/docs/api/03-language/04-flow-controls.md +++ /dev/null @@ -1,107 +0,0 @@ ---- -title: Flow control -id: flow-control -keywords: [Wing example] ---- - -### For in - -```ts playground example -let iterable = ["a", "b", "c", "d", "e", "f", "g", "h"]; -for value in iterable { - if value == "g" { - // stopping at g - break; - } - if value == "b" { - // skipping b - continue; - } - log(value); -} -/** - * prints - a - c - d - e - f -**/ -``` - -### For through a range - -```ts playground example -// print numbers from 0 to 9 -for value in 0..10 { - log("{value}"); -} - -// prints numbers in reverse order from 10 to 0 -for value in 10..-1 { - log("{value}"); -} - -// include end -for value in 1..=5 { - log("{value}"); -} -``` - -### If / else if / else - -```ts playground example -let grade = (score: num): str => { - // Parentheses are optional in conditions. - // However, curly braces are required in `if/else` statements. - if 0 < score && score < 55 { - return "F"; - } else if 55 <= score && score < 65 { - return "C"; - } else if 65 <= score && score < 75 { - return "B"; - } else if 75 <= score && score <= 100 { - return "A"; - } else { - return "Invalid grade"; - } -}; - -log("54 is {grade(54)}"); // 54 is F -log("62 is {grade(62)}"); // 62 is C -log("68 is {grade(68)}"); // 68 is B -log("99 is {grade(99)}"); // 99 is A -log("101 is {grade(101)}"); // 101 is Invalid grade -``` - -### While - -```ts playground example -let var i = 0; -while i < 100 { - i = i + 1; - if i == 20 { - // although the while loop goes to 100, we break it at 20 - break; - } - if i % 2 == 0 { - // continue for even numbers - continue; - } - log("{i}"); -} -/** - * prints - 1 - 3 - 5 - 7 - 9 - 11 - 13 - 15 - 17 - 19 -**/ -``` - diff --git a/docs/api/03-language/05-optionality.md b/docs/api/03-language/05-optionality.md deleted file mode 100644 index 33b819c8748..00000000000 --- a/docs/api/03-language/05-optionality.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: Optionality -id: optionality -keywords: [Wing example] ---- - -## Definition - -```ts playground example -let s1: str? = "Hello"; // type str? (optional), value "Hello" -let s2: str? = nil; // type str? (optional), value nil -``` - -## Testing existence -```ts playground example -let s1: str? = "Hello"; // type str? (optional), value "Hello" -let s2: str? = nil; // type str? (optional), value nil - -if s1 != nil { - log("x1 is not nil"); -} -if s2 == nil { - log("x2 is nil"); -} -``` - -## Using if let -```ts playground example -let s1: str? = "Hello"; // type str? (optional), value "Hello" - -// unwrap optional s1 and create s from type str -if let s = s1 { - log("s is not optional, value {s}"); -} else { - log("s1 was nil, s doesn't exists in this scope"); -} - -// same as above but shadowing s1 variable -if let s1 = s1 { - log("s1 type is str, value {s1}"); -} else { - log("s1 was nil"); -} -log("s1 type is optional str"); -``` - -## Using ?? - -```ts playground example -let s1: str? = nil; // type str? (optional), value nil -let s2 = s1 ?? "default value"; // s2 is of type str -log(s2); // prints default value -``` - -## Optional Chaining - -```ts playground example -let j = Json { - working: { - a: { - b: "value" - } - }, - broken: {} -}; - -if let value = j.tryGet("working")?.tryGet("a")?.tryGet("b")?.tryAsStr() { - log("value is {value}"); -} - -if let value = j.tryGet("broken")?.tryGet("a")?.tryGet("b")?.tryAsStr() { - // not reachable -} else { - log("value was not found"); -} -``` - -## Optional bool - -```ts playground example -let b3: bool? = false; - -if let b3 = b3 { // unboxing b3 and shadowing original b3 - if b3 { - log("b3 is true"); - } else { - log("b3 is false"); - } -} else { - log("b3 is nil"); -} - -/** - * prints: - b3 is false -**/ -``` diff --git a/docs/api/03-language/06-json.md b/docs/api/03-language/06-json.md deleted file mode 100644 index 6a591d97913..00000000000 --- a/docs/api/03-language/06-json.md +++ /dev/null @@ -1,131 +0,0 @@ ---- -title: Json -id: json -keywords: [Wing example] ---- -## Create Json values - -### Using Json literal -```js playground example -let j = Json { - k1: 1, - k2: "hello", - k3: true, - k4: { - k1: [1, "a", true, {} ] - } -}; -log("{j}"); - -let jsonStrValue = Json "Hello"; -log("{jsonStrValue}"); - -let jsonNumValue = Json 42; -log("{jsonNumValue}"); - -let jsonBoolValue = Json true; -log("{jsonBoolValue}"); - -let jsonHomogeneousArrayValue = Json ["a", "b"]; -log("{jsonHomogeneousArrayValue}"); -``` - -### From existing variables - -```js playground example -let x: num = 42; -let jsonNum = Json x; -log("{jsonNum}"); // 42 - -let chars = Array["a", "b"]; -let jsonChars = Json chars; -log("{jsonChars}"); // ["a","b"] - -let jsonComplex = Json { "first": x, "second": chars }; -log("{jsonComplex}"); // {"first": 42, "second": ["a","b"]} -``` - -### Parsing `str` -```js playground -let jsonFromParse = Json.parse("{\"k1\":\"v\"}"); -log("{jsonFromParse}"); - -if let jsonFromTryParse = Json.tryParse("{\"k1\":\"v\"}") { - log("{jsonFromTryParse}"); -} else { - log("failed to parse string to JSON"); -} -``` - -## Enumerating -### Over keys -```js playground example -let j = Json { - k1: "v1", - k2: "v2" -}; -for k in Json.keys(j) { - let value = j.get(k); - log("found key {k} with value {value}"); -} -``` -### Over values -```js playground example -let j = Json { - k1: "v1", - k2: "v2" -}; -for value in Json.values(j) { - log("found value {value}"); -} -``` - -### Over a json array -```js playground example -let arrayValue = Json ["a", "b", "c"]; -for v in Json.values(arrayValue) { - log(str.fromJson(v)); -} -``` - -## Safely convert to primitives -### To `str` -```js playground example -let j = Json { - k: "hello" -}; - -log(j.get("k").asStr()); -``` - -### To `num` -```js playground example -let j = Json { - k: 12 -}; -log("{j.get("k").asNum()}"); -``` - -### To `bool` - -```js playground example -let j = Json { - k:true -}; -log("{j.get("k").asBool()}"); -``` - -## Safely convert to structs -```js playground example -struct Foo { - val1: str; - val2: num; -} - -let jFoo = { - val1: "cool", - val2: 21 -}; - -let foo = Foo.fromJson(jFoo); -``` \ No newline at end of file diff --git a/docs/api/03-language/07-structs.md b/docs/api/03-language/07-structs.md deleted file mode 100644 index ae11c380d0e..00000000000 --- a/docs/api/03-language/07-structs.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: Structs -id: structs -keywords: [Wing example] ---- - -## Deceleration and Initialization - -### Required fields -```ts playground example -struct Example { - a: str; - b: num; - c: bool; -} - -let example = Example { a: "a", b: 0, c: false }; -log(example.a); // prints "a" -``` - -### Optional fields -```ts playground example -struct Example { - a: str?; - b: num?; - c: bool?; -} - -let example = Example { }; -if example.a == nil { - log("a is nil"); -} -``` - -### Composition -```ts playground example -struct Another { - hello: str; -} - -struct MyData { - a: str; - b: num?; - c: Another; -} - -let data = MyData { - a: "hello", - c: Another { - hello: "two" - } -}; - -log(data.a); // prints hello -log(data.c.hello); // prints two -``` - - -## Struct expansion in function calls -```ts playground example -struct Options { - prefix: str?; - delim: str; -} - -let join_str = (a: Array, opts: Options):str => { - let prefix = opts.prefix ?? ""; - return prefix + a.join(opts.delim); -}; - -log(join_str(["hello", "world"], delim: ", ")); // "!hello.world" - -// also OK to pass an object -let opts = Options { delim: "," }; -log(join_str(["hello", "world"], opts)); // "!!hello/world"); -``` diff --git a/docs/api/03-language/13-api-gateway.md b/docs/api/03-language/13-api-gateway.md deleted file mode 100644 index f1083192e2a..00000000000 --- a/docs/api/03-language/13-api-gateway.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: API gateway -id: api-gateway -keywords: [Wing example] ---- - -### Creating routes -```js playground example -bring cloud; - -let api = new cloud.Api(); - -api.get("/", inflight (request: cloud.ApiRequest): cloud.ApiResponse => { - return cloud.ApiResponse { - status: 200, - body: "Hello GET" - }; -}); -api.post("/", inflight (request: cloud.ApiRequest): cloud.ApiResponse => { - return cloud.ApiResponse { - status: 200, - body: "Hello POST" - }; -}); -api.put("/", inflight (request: cloud.ApiRequest): cloud.ApiResponse => { - return cloud.ApiResponse { - status: 200, body: - "Hello PUT" - }; -}); -api.delete("/", inflight (request: cloud.ApiRequest): cloud.ApiResponse => { - return cloud.ApiResponse { - status: 200, - body: "Hello DELETE" - }; -}); -``` - -### Path parameters -```js playground example -bring cloud; - -let api = new cloud.Api(); - -api.get("/items/:id/:value", inflight (req: cloud.ApiRequest): cloud.ApiResponse => { - let itemId = req.vars.get("id"); - let itemValue = req.vars.get("value"); - log("Received itemId:{itemId}, itemValue:{itemValue}"); - return cloud.ApiResponse { - status: 200, - body: "Received itemId:{itemId}, itemValue:{itemValue}" - }; -}); - -``` - -### Json body -```js playground example -bring cloud; - -let api = new cloud.Api(); - -api.put("/items/:id", inflight (req: cloud.ApiRequest): cloud.ApiResponse => { - let itemId = req.vars.get("id"); - if let itemBody = Json.tryParse(req.body ?? "") { - return cloud.ApiResponse { - status: 200, - body: "Received id {itemId} with body {itemBody}" - }; - } - return cloud.ApiResponse { - status: 400, - body: "Missing body" - }; -}); -``` \ No newline at end of file diff --git a/docs/api/03-language/_category_.yml b/docs/api/03-language/_category_.yml deleted file mode 100644 index ddfc32c787e..00000000000 --- a/docs/api/03-language/_category_.yml +++ /dev/null @@ -1,7 +0,0 @@ -label: Wing Language -collapsible: true -collapsed: false -link: - type: generated-index - slug: language - title: Wing Language \ No newline at end of file diff --git a/docs/by-example/03-values.md b/docs/by-example/03-values.md index b09225f73ec..74395890a5f 100644 --- a/docs/by-example/03-values.md +++ b/docs/by-example/03-values.md @@ -11,29 +11,89 @@ custom_edit_url: https://github.com/winglang/wing/blob/main/docs/by-example/03-v Wing has primitive types including strings, integers, floats, booleans, etc. Here are a few basic examples. -- Strings, which can be added together with + -- Integers and floats -- Booleans, with boolean operators as you'd expect +- [Strings](#str), which can be added together with + +- [Integers and floats](#num) +- [Booleans](#bool), with boolean operators as you'd expect ```js playground title="main.w" -log("Hello " + "Wing"); +log("Hello " + "Wing"); // Hello Wing -log("1+1 = {1+1}"); -log("7.0/3.0 = {7.0/3.0}"); +log("1+1 = {1+1}"); // 1+1 = 2 +log("7.0/3.0 = {7.0/3.0}"); // 7.0/3.0 = 2.3333333333333335 -log(true && true); -log(true || false); -log(!true); +log(true && true); // true +log(true || false); // true +log(!true); // false ``` -```bash title="Wing console output" -# Run locally with wing console -wing it +## Str +### Concat and Interpolate +```ts example +let s1 = "Hello Wing String"; +log(s1); // prints Hello Wing String +let s2 = "Interpolate: {s1}"; // string interpolation +log(s2); // prints Interpolate Hello Wing String +let s3 = "Concat: " + s1; // string concatenation +log(s3); // prints Concat: Hello Wing String +``` + +### Str methods +```ts example +let s = "Hello to a new Wing world"; + +// lets start with split +for w in s.split(" ") { + if w.startsWith("H") { + log(w); // 'Hello' starts with H + } + if w.length > 3 && w.lowercase() == w { + log(w); // 'world' is lowercased with more then 3 chars + } + if w.contains("in") && w.endsWith("g") { + log(w); // 'Wing' has in and end with g + } + if s.indexOf(w) == 6 { + log(w); // 'to' position is 6 + } + if s.at(9) == w { + log(w); // 'a' is a single char + } + if s.substring(11,14) == w { + log(w); // 'new' position is 11-14 + } +} +``` + +## Num + +```ts example +let n1 = 10; +log("{n1}"); // 10 + +let n2 = n1 - 10 / 10 + 1 * 10 ; // arithmetic +log("{n2}"); // 1 + +let n3 = 10 % 7; // modulo +log("{n3}"); // 3 + +let n4 = 10 \ 7; // FloorDiv +log("{n4}"); // 1 + +let n5 = 2 ** 10; // power of +log("{n5}"); // 1024 + +let n6 = (10 + 1) / (12 - 1) + (20 / 2) * 2 + 10 * 2**10 / 512 + 1; +log("{n6}"); // The meaning of the universe +``` + + +## Bool + +```ts example +let b1 = true; +let b2 = false; -Hello Wing -1+1 = 2 -7.0/3.0 = 2.3333333333333335 -true -true -false +if b1 && !b2 { + log("b1:{b1},b2:{b2}"); // prints b1:true, b2:false +} ``` \ No newline at end of file diff --git a/docs/by-example/04-variables.md b/docs/by-example/04-variables.md index 1b9b02137e3..de2dee0b562 100644 --- a/docs/by-example/04-variables.md +++ b/docs/by-example/04-variables.md @@ -6,7 +6,6 @@ sidebar_label: Variables description: Using variables with Wing keywords: [Wing language, example] image: /img/wing-by-example.png -custom_edit_url: https://github.com/winglang/wing/blob/main/docs/by-example/04-variables.md --- Variables are declared with the `let` keyword. The type of most variables can be inferred automatically, but you can also add an explicit type annotation if needed. @@ -14,33 +13,37 @@ Variables are declared with the `let` keyword. The type of most variables can be By default, Wing doesn't let you reassign to variables, unless you add the `var` modifier. See [this blog post](https://www.winglang.io/blog/2023/02/02/good-cognitive-friction) for more details. ```js title="main.w" - -// var delcares a varaible. Wing infers the type +// Inferred typing, wing infers the types let a = "initial"; -log(a); - +let a2: string = "initial"; // equivalent +log(a); // prints initial -// type can also be declared +// types can also be declared let b: num = 1; let c: num = 2; -log("{b}, {c}"); +log("{b}, {c}"); // prints 1, 2 -// variables cannot be changed using let without var +// Variable assignment let d: str = "Hello"; -// d = "Test"; // error: Variable is not reassignable - -// makes variable reassignable -let var s = "hello"; -s = "hello world"; // compiles -log(s); - -``` - -```bash title="Wing console output" -# Run locally with wing console -wing it +d = "Test"; // error: Variable is not reassignable +let var s = "hello"; // use "var" to make variable reassignable +s = "hello world"; // OK (s is reassignable) + +// Optionals +let var x1 = "Hello"; // type str, value "Hello" +let var x2: str = "Hello"; // same as above +let var x3: str? = "Hello"; // type str? (optional), value "Hello" +let var x4: str? = nil; // type str? (optional), value nil +x1 = nil; // ERROR: Expected type to be "str", but got "nil" instead +x3 = nil; // OK (x3 is optional) + +// Scoped variables +let s = "parent"; +log(s); // prints parent +if true { + let s = "inner"; + log(s); // prints inner +} +log(s); // prints parent -initial -1, 2 -hello world ``` \ No newline at end of file diff --git a/docs/by-example/06-ifelse.md b/docs/by-example/06-ifelse.md index 04ce13d2035..338e278c2bf 100644 --- a/docs/by-example/06-ifelse.md +++ b/docs/by-example/06-ifelse.md @@ -37,12 +37,28 @@ if value < 0 { ``` -```bash title="Wing console output" -# Run locally with wing console -wing it - -7 is odd -8 is divisble by 4 -either 8 or 7 are even -9 has 1 digit + +### If / else if / else +```js playground title="main.w" +let grade = (score: num): str => { + // Parentheses are optional in conditions. + // However, curly braces are required in `if/else` statements. + if 0 < score && score < 55 { + return "F"; + } else if 55 <= score && score < 65 { + return "C"; + } else if 65 <= score && score < 75 { + return "B"; + } else if 75 <= score && score <= 100 { + return "A"; + } else { + return "Invalid grade"; + } +}; + +log("54 is {grade(54)}"); // 54 is F +log("62 is {grade(62)}"); // 62 is C +log("68 is {grade(68)}"); // 68 is B +log("99 is {grade(99)}"); // 99 is A +log("101 is {grade(101)}"); // 101 is Invalid grade ``` \ No newline at end of file diff --git a/docs/by-example/07-while.md b/docs/by-example/07-while.md index 78a200eb84d..8ed93764fb9 100644 --- a/docs/by-example/07-while.md +++ b/docs/by-example/07-while.md @@ -14,9 +14,17 @@ While loops repeatedly check a condition and run a block of code until the condi ```js playground title="main.w" let var i = 0; -while i < 2 { - log("while {i}"); +while i < 100 { i = i + 1; + if i == 20 { + // although the while loop goes to 100, we break it at 20 + break; + } + if i % 2 == 0 { + // continue for even numbers + continue; + } + log("{i}"); } ``` @@ -24,6 +32,14 @@ while i < 2 { # Run locally with wing console wing it -while 0 -while 1 +1 +3 +5 +7 +9 +11 +13 +15 +17 +19 ``` \ No newline at end of file diff --git a/docs/by-example/08-optionality.md b/docs/by-example/08-optionality.md index f7871cfccac..c9a5c2e4d70 100644 --- a/docs/by-example/08-optionality.md +++ b/docs/by-example/08-optionality.md @@ -16,17 +16,94 @@ An optional value can be either "nil" or a non-nil value. The type of an optiona ```js playground title="main.w" let monday: str = "doctor"; let tuesday: str? = nil; - // Set next to tuesday if there is a value otherwise use monday value let next = tuesday ?? monday; -log(next); +log(next); // doctor +``` + + +## Testing existence +```ts playground example +let s1: str? = "Hello"; // type str? (optional), value "Hello" +let s2: str? = nil; // type str? (optional), value nil + +if s1 != nil { + log("x1 is not nil"); +} +if s2 == nil { + log("x2 is nil"); +} +``` + +## Using if let +```ts playground example +let s1: str? = "Hello"; // type str? (optional), value "Hello" + +// unwrap optional s1 and create s from type str +if let s = s1 { + log("s is not optional, value {s}"); +} else { + log("s1 was nil, s doesn't exists in this scope"); +} +// same as above but shadowing s1 variable +if let s1 = s1 { + log("s1 type is str, value {s1}"); +} else { + log("s1 was nil"); +} +log("s1 type is optional str"); ``` -```bash title="Wing console output" -# Run locally with wing console -wing it +## Using ?? + +```ts playground example +let s1: str? = nil; // type str? (optional), value nil +let s2 = s1 ?? "default value"; // s2 is of type str +log(s2); // prints default value +``` -doctor -``` \ No newline at end of file +## Optional Chaining + +```ts playground example +let j = Json { + working: { + a: { + b: "value" + } + }, + broken: {} +}; + +if let value = j.tryGet("working")?.tryGet("a")?.tryGet("b")?.tryAsStr() { + log("value is {value}"); +} + +if let value = j.tryGet("broken")?.tryGet("a")?.tryGet("b")?.tryAsStr() { + // not reachable +} else { + log("value was not found"); +} +``` + +## Optional bool + +```ts playground example +let b3: bool? = false; + +if let b3 = b3 { // unboxing b3 and shadowing original b3 + if b3 { + log("b3 is true"); + } else { + log("b3 is false"); + } +} else { + log("b3 is nil"); +} + +/** + * prints: + b3 is false +**/ +``` diff --git a/docs/by-example/12-structs.md b/docs/by-example/12-structs.md index 627953e30ff..35d62edb2a6 100644 --- a/docs/by-example/12-structs.md +++ b/docs/by-example/12-structs.md @@ -35,16 +35,33 @@ let data = MyData { } }; -log(data.a); -log(data.c.a); -log(data.c.b); +log(data.a); // prints hello +log(data.c.a); //prints world +log(data.c.b); //prints 42 ``` -```bash title="Wing console output" -# Run locally with wing console -wing it -hello -world -42 + + +## Struct expansion in function calls + +```js playground example title="main.w" +struct Options { + // optional + prefix: str?; + // required + delim: str; +} + +let join_str = (a: Array, opts: Options):str => { + let prefix = opts.prefix ?? ""; + return prefix + a.join(opts.delim); +}; + +// pass options directly +log(join_str(["hello", "world"], delim: ", ")); // "hello, world" + +// also OK to pass an object +let opts = Options { delim: "/" , prefix: "!!" }; +log(join_str(["hello", "world"], opts)); // "!!hello/world"); ``` \ No newline at end of file diff --git a/docs/by-example/14-functions.md b/docs/by-example/14-functions.md index 34f7fe588b0..068899a2d66 100644 --- a/docs/by-example/14-functions.md +++ b/docs/by-example/14-functions.md @@ -33,12 +33,19 @@ let func = new cloud.Function(inflight (payload:Json?) => { let value = plus(1, 2); -log(value); +log(value); // 3 ``` -```bash title="Wing console output" -# Run locally with wing console -wing it - -3 +### Inflight modifiers +```js playground example title="main.w" +let handler = inflight (message: str): void => { + // using the inflight modifier + let dup = inflight (s: str, count: num) => { + // code + }; + // inflight modifier is not required when function is declared in inflight context + let sup = (s: str, count: num) => { + // code + }; +}; ``` \ No newline at end of file diff --git a/docs/by-example/15-variadic-functions.md b/docs/by-example/14-variadic-functions.md similarity index 95% rename from docs/by-example/15-variadic-functions.md rename to docs/by-example/14-variadic-functions.md index 844bbea9f8d..2ee6666d0ab 100644 --- a/docs/by-example/15-variadic-functions.md +++ b/docs/by-example/14-variadic-functions.md @@ -6,7 +6,7 @@ sidebar_label: Variadic Functions description: Using variadic functions with Wing keywords: [Wing language, variadic] image: /img/wing-by-example.png -custom_edit_url: https://github.com/winglang/wing/blob/main/docs/by-example/15-variadic-functions.md +custom_edit_url: https://github.com/winglang/wing/blob/main/docs/by-example/14-variadic-functions.md --- diff --git a/docs/api/03-language/08-classes.md b/docs/by-example/15-classes.md similarity index 52% rename from docs/api/03-language/08-classes.md rename to docs/by-example/15-classes.md index 02ae51ad50b..4e27f5abd3a 100644 --- a/docs/api/03-language/08-classes.md +++ b/docs/by-example/15-classes.md @@ -1,10 +1,23 @@ --- title: Classes id: classes -keywords: [Wing example] +slug: /classes +sidebar_label: Classes +description: Using classes with Wing +keywords: [Wing language, classes] +image: /img/wing-by-example.png +custom_edit_url: https://github.com/winglang/wing/blob/main/docs/by-example/15-classes.md --- +Wing Classes are fundamental building blocks for creating reusable, structured code in Wing applications. Similar to other object-oriented languages, Wing classes allow you to define custom types with their own properties and methods. + +Classes in Wing can represent both traditional application logic and cloud resources, making them a powerful tool for modeling your cloud architecture in code. + ### Preflight class + +This is a [preflight](/docs/concepts/inflights#preflight-code) class. +This preflight class as [inflight methods](/docs/concepts/inflights#inflight-code), these methods can be called within your inflight functions. + ```ts playground example bring cloud; bring util; @@ -23,11 +36,13 @@ class Foo { this.field2 = value; } + // private inflight function, only accessible during inflight inflight new() { this.field3 = ["value created on inflight init"]; log("at inflight init"); } + // public inflight function, only accessible during inflight pub inflight doStuff() { // all code is async and runs on the cloud log("field3[0]='{this.field3.at(0)}'"); @@ -40,26 +55,37 @@ let f = new Foo(); log("field1={f.field1}"); log("field2={f.field2}"); +// inflight example for a cloud function new cloud.Function(inflight () => { + // calling the public inflight function (doStuff) of the Foo class. + // This function is not accessible during preflight. f.doStuff(); }); ``` ### Inflight interface + +Inflight interfaces define contracts that classes can implement. When a class implements (impl) an interface, it must provide concrete implementations of all the methods defined in that interface. + ```js playground example bring cloud; +// define the interface inflight interface IProfile { + // inflight function inflight name(): str; } +// new class that implements the interface inflight class WingPerson impl IProfile { + // custom definition of the name function pub inflight name(): str { return "Fairy Wing"; } } +// inflight function that accepts the interface let logName = inflight(profile: IProfile): void => { log(profile.name()); }; @@ -93,38 +119,4 @@ class BucketBasedKeyValueStore impl IKVStore { } } -``` - -### Complete IKVStore -```js playground example -bring cloud; - -interface IKVStore extends std.IResource { - inflight get(key: str): Json; - inflight set(key: str, value: Json): void; -} - -class BucketBasedKeyValueStore impl IKVStore { - bucket: cloud.Bucket; - new() { - this.bucket = new cloud.Bucket(); - } - pub inflight get(key: str): Json { - return this.bucket.getJson(key); - } - pub inflight set(key: str, value: Json): void { - this.bucket.putJson(key, value); - } -} - -let bucketBased: IKVStore = new BucketBasedKeyValueStore(); - -test "bucketBased KVStore" { - bucketBased.set("k", Json { - value: "v" - }); - let result = bucketBased.get("k"); - log("{result.get("value")}"); - assert("v" == str.fromJson(result.get("value"))); -} -``` +``` \ No newline at end of file diff --git a/docs/api/03-language/14-singletons.md b/docs/by-example/15-singletons.md similarity index 75% rename from docs/api/03-language/14-singletons.md rename to docs/by-example/15-singletons.md index b4f5f8a6317..2a0092df2ac 100644 --- a/docs/api/03-language/14-singletons.md +++ b/docs/by-example/15-singletons.md @@ -1,16 +1,22 @@ --- title: Singletons id: singletons -keywords: [singleton] +slug: /singletons +sidebar_label: Singletons +description: Using singletons with Wing +keywords: [Wing language, singletons] +image: /img/wing-by-example.png +custom_edit_url: https://github.com/winglang/wing/blob/main/docs/by-example/15-singletons.md --- -Sometimes, it makes sense for a resource to be defined only once per application. This example shows -a pattern for how to implement singletons in Wing. +Singletons let you define a resource only once per application. + +This example shows a pattern for how to implement singletons in Wing. As an example, say we want to maintain a central bucket that can be accessed from any part of the application: -```js playground example +```js title="main.w" playground example bring cloud; class SingletonBucket { @@ -46,4 +52,4 @@ And we will always get the same bucket. ```js let bucket = SingletonBucket.of(unsafeCast(this)); -``` +``` \ No newline at end of file diff --git a/docs/by-example/23-Json.md b/docs/by-example/23-Json.md index 5cfbc89adc7..8ef18d9117a 100644 --- a/docs/by-example/23-Json.md +++ b/docs/by-example/23-Json.md @@ -18,40 +18,125 @@ let person = Json { }; // stringify -log(Json.stringify(person)); +log(Json.stringify(person)); // {"firstName":"John","lastName":"Smith"} // parse -log(Json.parse("\{\"firstName\":\"John\",\"lastName\":\"Smith\"}")); +log(Json.parse("\{\"firstName\":\"John\",\"lastName\":\"Smith\"}")); // { firstName: 'John', lastName: 'Smith' } // Try and parse if let jsonFromTryParse = Json.tryParse("\{\"firstName\":\"John\",\"lastName\":\"Smith\"}") { - log("{jsonFromTryParse}"); + log("{jsonFromTryParse}"); // {"firstName":"John","lastName":"Smith"} } else { log("failed to parse string to JSON"); } // Deep copy of Json let newPerson = Json.deepCopy(person); -log(Json.stringify(person)); +log(Json.stringify(person)); // {"firstName":"John","lastName":"Smith"} -// iterate over keys -for k in Json.keys(person) { - let value = person.get(k); + +``` + +## Using Json literals +```js playground example title="main.w" +let j = Json { + k1: 1, + k2: "hello", + k3: true, + k4: { + k1: [1, "a", true, {} ] + } +}; +log("{j}"); // {"k1":1,"k2":"hello","k3":true,"k4":{"k1":[1,"a",true,{}]}} + +let jsonStrValue = Json "Hello"; +log("{jsonStrValue}"); // "Hello" + +let jsonNumValue = Json 42; +log("{jsonNumValue}"); // 42 + +let jsonBoolValue = Json true; +log("{jsonBoolValue}"); // true + +let jsonHomogeneousArrayValue = Json ["a", "b"]; +log("{jsonHomogeneousArrayValue}"); // ["a","b"] +``` + +## From existing variables +```js playground example title="main.w" +let x: num = 42; +let jsonNum = Json x; +log("{jsonNum}"); // 42 + +let chars = Array["a", "b"]; +let jsonChars = Json chars; +log("{jsonChars}"); // ["a","b"] + +let jsonComplex = Json { "first": x, "second": chars }; +log("{jsonComplex}"); // {"first": 42, "second": ["a","b"]} +``` + +## Enumerating +### Over keys +```js playground example +let j = Json { + k1: "v1", + k2: "v2" +}; +for k in Json.keys(j) { + let value = j.get(k); log("found key {k} with value {value}"); } - -// iterate over values -for value in Json.values(person) { +``` +### Over values +```js playground example +let j = Json { + k1: "v1", + k2: "v2" +}; +for value in Json.values(j) { log("found value {value}"); } +``` -// iterate over array +### Over a json array +```js playground example let arrayValue = Json ["a", "b", "c"]; for v in Json.values(arrayValue) { log(str.fromJson(v)); } +``` + + +## Safely convert to primitives +### To `str` +```js playground example +let j = Json { + k: "hello" +}; + +log(j.get("k").asStr()); +``` + +### To `num` +```js playground example +let j = Json { + k: 12 +}; +log("{j.get("k").asNum()}"); +``` + +### To `bool` -// Convert to structs +```js playground example +let j = Json { + k:true +}; +log("{j.get("k").asBool()}"); +``` + +## Safely convert to structs +```js playground example struct Foo { val1: str; val2: num; @@ -63,27 +148,4 @@ let jFoo = { }; let foo = Foo.fromJson(jFoo); -log(Json.stringify(foo)); -``` - -```bash title="Wing console output" -# Run locally with wing console -wing it - -{"firstName":"John","lastName":"Smith"} -{ firstName: 'John', lastName: 'Smith' } -{"firstName":"John","lastName":"Smith"} -{"firstName":"John","lastName":"Smith"} -found key firstName with value "John" -found key lastName with value "Smith" -found value "John" -found value "Smith" -a -b -c -{"val1":"cool","val2":21} -``` - - - - +``` \ No newline at end of file diff --git a/docs/by-example/34-http-server.md b/docs/by-example/34-http-server.md index 42b27618914..fdca9827fc4 100644 --- a/docs/by-example/34-http-server.md +++ b/docs/by-example/34-http-server.md @@ -72,6 +72,87 @@ new cloud.Function(inflight (event: Json?) => { }) as "Consumer-GET"; ``` +## API Gateway + +### Creating routes + +Defining a new API with routes. + +```js playground example +bring cloud; + +let api = new cloud.Api(); + +api.get("/", inflight (request: cloud.ApiRequest): cloud.ApiResponse => { + return cloud.ApiResponse { + status: 200, + body: "Hello GET" + }; +}); +api.post("/", inflight (request: cloud.ApiRequest): cloud.ApiResponse => { + return cloud.ApiResponse { + status: 200, + body: "Hello POST" + }; +}); +api.put("/", inflight (request: cloud.ApiRequest): cloud.ApiResponse => { + return cloud.ApiResponse { + status: 200, body: + "Hello PUT" + }; +}); +api.delete("/", inflight (request: cloud.ApiRequest): cloud.ApiResponse => { + return cloud.ApiResponse { + status: 200, + body: "Hello DELETE" + }; +}); +``` + +### Path parameters + +Using path parameters with your API routes. + +```js playground example +bring cloud; + +let api = new cloud.Api(); + +api.get("/items/:id/:value", inflight (req: cloud.ApiRequest): cloud.ApiResponse => { + let itemId = req.vars.get("id"); + let itemValue = req.vars.get("value"); + log("Received itemId:{itemId}, itemValue:{itemValue}"); + return cloud.ApiResponse { + status: 200, + body: "Received itemId:{itemId}, itemValue:{itemValue}" + }; +}); + +``` + +### Json body + +Parsing request body as Json. + +```js playground example +bring cloud; + +let api = new cloud.Api(); + +api.put("/items/:id", inflight (req: cloud.ApiRequest): cloud.ApiResponse => { + let itemId = req.vars.get("id"); + if let itemBody = Json.tryParse(req.body ?? "") { + return cloud.ApiResponse { + status: 200, + body: "Received id {itemId} with body {itemBody}" + }; + } + return cloud.ApiResponse { + status: 400, + body: "Missing body" + }; +}); +``` diff --git a/docs/api/03-language/10-using-javascript.md b/docs/by-example/37-extern.md similarity index 66% rename from docs/api/03-language/10-using-javascript.md rename to docs/by-example/37-extern.md index 812d8f6a830..704d21449dd 100644 --- a/docs/api/03-language/10-using-javascript.md +++ b/docs/by-example/37-extern.md @@ -1,10 +1,23 @@ --- -title: Using JavaScript/TypeScript -id: using-javascript -keywords: [example, javascript, extern, typescript, js, ts] +title: Externs +id: extern +slug: /extern +sidebar_label: Using JavaScript with Wing +description: Type reflection +keywords: [Wing language, Type reflection] +image: /img/wing-by-example.png +custom_edit_url: https://github.com/winglang/wing/blob/main/docs/by-example/36-reflection.md --- -## Using `extern` to expose JavaScript/TypeScript functions in preflight and inflight +Externs let you use JavaScript/TypeScript files within Wing. You can expose these functions and call them in Wing. + +Using externs give you the ability to use the JavaScript eco-system directly in Wing. + +:::tip Creating custom libraries +Want to create your own library? You can use externs to help. Externs give you the ability to pull in code from NPM directly into your custom Wing libraries. You can see some [examples on GitHub](https://github.com/winglang/winglibs). +::: + +## Exposing JavaScript functions in preflight and inflight When you want to use a JavaScript/TypeScript file anywhere in Wing, you can use the `extern` keyword to expose functions from that file.