diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
deleted file mode 100644
index ce71f103..00000000
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-contact_links:
- - name: ❓ Questions and Help 🤔
- url: https://discord.gg/tbd (/add your discord channel if applicable)
- about: This issue tracker is not for support questions. Please refer to the community for more help.
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 4562aadc..ba25aa19 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -19,6 +19,8 @@ jobs:
uses: actions/checkout@v3
- name: Init Hermit
uses: cashapp/activate-hermit@v1
+ with:
+ cache: true
- name: Get dependencies
working-directory: ./frontend/mobile
run: flutter pub get
diff --git a/.gitignore b/.gitignore
index 19fd746b..c717a2b5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,9 @@ build/
deploy/
.DS_Store
/logs/
+generated_ftl_module.go
+*.zip
+dist/
+go.work
+go.work.sum
+_ftl/
diff --git a/CODEOWNERS b/CODEOWNERS
index 21ecf13a..b96b6a3b 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -1,24 +1 @@
-# This CODEOWNERS file denotes the project leads
-# and encodes their responsibilities for code review.
-
-# Instructions: At a minimum, replace the '@GITHUB_USER_NAME_GOES_HERE'
-# here with at least one project lead.
-
-# Lines starting with '#' are comments.
-# Each line is a file pattern followed by one or more owners.
-# The format is described: https://github.blog/2017-07-06-introducing-code-owners/
-
-# These owners will be the default owners for everything in the repo.
-* @GITHUB_USER_NAME_GOES_HERE
-
-
-# -----------------------------------------------
-# BELOW THIS LINE ARE TEMPLATES, UNUSED
-# -----------------------------------------------
-# Order is important. The last matching pattern has the most precedence.
-# So if a pull request only touches javascript files, only these owners
-# will be requested to review.
-# *.js @octocat @github/js
-
-# You can also use email addresses if you prefer.
-# docs/* docs@example.com
\ No newline at end of file
+* @alecthomas @wesbillman @worstell
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 95b8a6fa..c58d87fb 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -4,7 +4,7 @@ There are many ways to be an open source contributor, and we're here to help you
* Propose ideas in our
[discord](https://discord.gg/tbd)
-* Raise an issue or feature request in our [issue tracker](LINK_HERE) ___***FIX LINK AND REMOVE THIS NOTICE***___
+* Raise an issue or feature request in [github](https://github.com/TBD54566975/ftl-examples/issues)
* Help another contributor with one of their questions, or a code review
* Suggest improvements to our Getting Started documentation by supplying a Pull Request
* Evangelize our work together in conferences, podcasts, and social media spaces.
@@ -17,167 +17,7 @@ ___***UPDATE TABLE OF PROJECT DEPS AND INSTALLATION NOTES***___
| Requirement | Tested Version | Installation Instructions |
|-------------|----------------|------------------------------------------------------|
-| Go | 1.17.6 |[go.dev](https://go.dev/doc/tutorial/compile-install) |
-| Mage | 1.12.1 |[magefile.org](https://magefile.org/) |
-| Java | 17.0.2 | Below, recommended via [SDKMan](https://sdkman.io) |
-
-### Go
-
-This project is written in Go, a modern, open source programming language.
-
-You may verify your `go` installation via the terminal:
-
-```
-$> go version
-go version go1.17.6 darwin/amd64
-```
-
-If you do not have go, we recommend installing it by:
-
-#### MacOS
-
-##### Homebrew
-```
-$> brew install go
-```
-
-#### Linux
-
-See the [Go Installation Documentation](https://go.dev/doc/install).
-
-### Mage
-
-The build is run by Mage.
-
-You may verify your `mage` installation via the terminal:
-
-```
-$> mage --version
-Mage Build Tool 1.12.1
-Build Date: 2021-12-15T21:00:02Z
-Commit: 2f1ec40
-built with: go1.17.6
-```
-
-#### MacOS
-
-##### Homebrew
-
-```
-$> brew install mage
-```
-
-#### Linux
-
-Installation instructions are on the [Magefile home page](https://magefile.org/).
-
-### Java
-
-This project is written in Java, a typesafe, compiled programming language.
-
-You may verify your `java` installation via the terminal by running `java -version`.
-
-If you do not have Java, we recommend installing it
-via [SDKMan](https://sdkman.io/install). This is a project which will allow you
-to easily install the Java Development Kit (JDK), runtime (JRE), and related frameworks,
-build tools, and runtimes.
-
-After you've installed SDKMan, you may install Java:
-
-#### SDKMan (cross-platform instructions)
-
-```shell
-$> sdk install java
- ...
-Do you want java 17.0.2-open to be set as default? (Y/n): Y
-Setting java 17.0.2-open as default.
-```
-
-You may test your installation:
-
-```shell
-$> java -version
-openjdk version "17.0.2" 2022-01-18
-OpenJDK Runtime Environment (build 17.0.2+8-86)
-OpenJDK 64-Bit Server VM (build 17.0.2+8-86, mixed mode, sharing)
-```
-
----
-**NOTE**
-
-You may additionally look for other Java versions to install by running `sdk list java`:
-
-...or other installation candidates like Apache Ant, Apache Maven, etc, by running `sdk list`.
-
-Consult the SDKMan documentation for more info.
-
----
-
-## Build (Mage)
-
-```
-$> mage build
-```
-
-## Build (Java / Gradle)
-
-### macOS / Linux
-```shell
-$> ./gradlew build
-```
-
-### Windows
-```shell
-$> gradlew.bat build
-```
-
-## Test (Mage)
-
-```
-$> mage test
-```
-
-## Test (Java / Gradle)
-
-### macOS / Linux
-```shell
-$> ./gradlew test
-```
-
-### Windows
-```shell
-$> gradlew.bat test
-```
-
----
-**NOTE**
-
-You may also combine Gradle build targets in one call, like:
-
-```shell
-$> ./gradlew clean build test
-```
-
----
-
-## Communications
-
-### Issues
-
-Anyone from the community is welcome (and encouraged!) to raise issues via
-[GitHub Issues](LINK_HERE) ___***FIX LINK AND REMOVE THIS NOTICE***___.
-
-### Discussions
-
-Design discussions and proposals take place in our [discord](https://discord.gg/tbd).
-
-We advocate an asynchronous, written debate model - so write up your thoughts and invite the community to join in!
-
-### Continuous Integration
-
-Build and Test cycles are run on every commit to every branch on [CircleCI](LINK_HERE).
-
- ___***FIX LINK ABOVE AND REMOVE THIS NOTICE***___
+| Hermit | v0.38.1 |[hermit](https://cashapp.github.io/hermit/usage/get-started/) |
## Contribution
diff --git a/Justfile b/Justfile
new file mode 100644
index 00000000..a120fc55
--- /dev/null
+++ b/Justfile
@@ -0,0 +1,7 @@
+# Start the FTL backend with hot-reloading
+dev:
+ watchexec -r -e sql -- goreman -logtime=false -f Procfile.dev start
+
+# Start the example web frontend for online-boutique
+web:
+ cd frontend/web && npm install && npm run dev
diff --git a/Procfile.dev b/Procfile.dev
new file mode 100644
index 00000000..339c347c
--- /dev/null
+++ b/Procfile.dev
@@ -0,0 +1,4 @@
+ftl: ftl serve --recreate --allow-origins '*'
+backend: ftl dev backend/online-boutique/services
+mobile_code_gen: ftl schema generate frontend/mobile/templates/ frontend/mobile/lib/api --watch=5s
+web_code_gen: ftl schema generate frontend/web/templates/ frontend/web/src/api --watch=5s
diff --git a/README.md b/README.md
index c8ba3b38..e404e02d 100644
--- a/README.md
+++ b/README.md
@@ -1,31 +1,32 @@
-# $PROJECT_NAME README
+# FTL examples
-Congrats, project leads! You got a new project to grow!
+## Introduction
-This stub is meant to help you form a strong community around your work. It's yours to adapt, and may
-diverge from this initial structure. Just keep the files seeded in this repo, and the rest is yours to evolve!
+This repo is designed to show how to use FTL to build an online boutique backend with a mobile (Flutter) app and React frontend.
-## Introduction
+## Running
+
+* Install [Hermit](https://cashapp.github.io/hermit/usage/get-started/) and related [shell_hooks]([shell hooks](https://cashapp.github.io/hermit/usage/shell/)).
+
+>[NOTE] This will install [Just](https://github.com/casey/just) for you.
+
+To see a list of commands that can be run, run `just --list` in the root of the project.
+
+### Start FTL, code gen, and backend services with hot-reloading
-Orient users to the project here. This is a good place to start with an assumption
-that the user knows very little - so start with the Big Picture and show how this
-project fits into it. It may be good to reference/link the broader architecture in the
-`collaboration` repo or the developer site here.
+```bash
+just dev
+```
-Then maybe a dive into what this project does.
+### Start the React web app
-Diagrams and other visuals are helpful here. Perhaps code snippets showing usage.
+```bash
+just web
+```
-Project leads should complete, alongside this `README`:
-* [CODEOWNERS](./CODEOWNERS) - set project lead(s)
-* [CONTRIBUTING.md](./CONTRIBUTING.md) - Fill out how to: install prereqs, build, test, run, access CI, chat, discuss, file issues
-* [Bug-report.md](.github/ISSUE_TEMPLATE/bug-report.md) - Fill out `Assignees` add codeowners @names
-* [config.yml](.github/ISSUE_TEMPLATE/config.yml) - remove "(/add your discord channel..)" and replace the url with your Discord channel if applicable
+### Flutter app
-The other files in this template repo may be used as-is:
-* [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md)
-* [GOVERNANCE.md](./GOVERNANCE.md)
-* [LICENSE](./LICENSE)
+Flutter is better run via an [IDE](https://docs.flutter.dev/get-started/editor?tab=vscode) like VSCode or Android Studio.
## Project Resources
diff --git a/backend/online-boutique/common/money/money.go b/backend/online-boutique/common/money/money.go
index 6c8deb81..50592b83 100644
--- a/backend/online-boutique/common/money/money.go
+++ b/backend/online-boutique/common/money/money.go
@@ -16,6 +16,8 @@ package money
import (
"errors"
+
+ "ftl/currency"
)
const (
@@ -29,66 +31,49 @@ var (
ErrMismatchingCurrency = errors.New("mismatching currency codes")
)
-// Money represents an amount of money along with the currency type.
-type Money struct {
- // The 3-letter currency code defined in ISO 4217.
- CurrencyCode string `json:"currencyCode"`
-
- // The whole units of the amount.
- // For example if `currencyCode` is `"USD"`, then 1 unit is one US dollar.
- Units int `json:"units"`
-
- // Number of nano (10^-9) units of the amount.
- // The value must be between -999,999,999 and +999,999,999 inclusive.
- // If `units` is positive, `nanos` must be positive or zero.
- // If `units` is zero, `nanos` can be positive, zero, or negative.
- // If `units` is negative, `nanos` must be negative or zero.
- // For example $-1.75 is represented as `units`=-1 and `nanos`=-750,000,000.
- Nanos int `json:"nanos"`
-}
-
// IsValid checks if specified value has a valid units/nanos signs and ranges.
-func IsValid(m Money) bool {
+func IsValid(m currency.Money) bool {
return signMatches(m) && validNanos(m.Nanos)
}
-func signMatches(m Money) bool {
+func signMatches(m currency.Money) bool {
return m.Nanos == 0 || m.Units == 0 || (m.Nanos < 0) == (m.Units < 0)
}
func validNanos(nanos int) bool { return nanosMin <= nanos && nanos <= nanosMax }
// IsZero returns true if the specified money value is equal to zero.
-func IsZero(m Money) bool { return m.Units == 0 && m.Nanos == 0 }
+func IsZero(m currency.Money) bool { return m.Units == 0 && m.Nanos == 0 }
// IsPositive returns true if the specified money value is valid and is
// positive.
-func IsPositive(m Money) bool {
+func IsPositive(m currency.Money) bool {
return IsValid(m) && m.Units > 0 || (m.Units == 0 && m.Nanos > 0)
}
// IsNegative returns true if the specified money value is valid and is
// negative.
-func IsNegative(m Money) bool {
+func IsNegative(m currency.Money) bool {
return IsValid(m) && m.Units < 0 || (m.Units == 0 && m.Nanos < 0)
}
// AreSameCurrency returns true if values l and r have a currency code and
// they are the same values.
-func AreSameCurrency(l, r Money) bool {
+func AreSameCurrency(l, r currency.Money) bool {
return l.CurrencyCode == r.CurrencyCode && l.CurrencyCode != ""
}
// AreEquals returns true if values l and r are the equal, including the
-// currency. This does not check validity of the provided values.
-func AreEquals(l, r Money) bool {
+//
+// This does not check validity of the provided values.
+func AreEquals(l, r currency.Money) bool {
return l.CurrencyCode == r.CurrencyCode &&
l.Units == r.Units && l.Nanos == r.Nanos
}
// Negate returns the same amount with the sign negated.
-func Negate(m Money) Money {
- return Money{
+func Negate(m currency.Money) currency.Money {
+ return currency.Money{
Units: -m.Units,
Nanos: -m.Nanos,
CurrencyCode: m.CurrencyCode}
@@ -96,7 +81,7 @@ func Negate(m Money) Money {
// Must panics if the given error is not nil. This can be used with other
// functions like: "m := Must(Sum(a,b))".
-func Must(v Money, err error) Money {
+func Must(v currency.Money, err error) currency.Money {
if err != nil {
panic(err)
}
@@ -106,11 +91,11 @@ func Must(v Money, err error) Money {
// Sum adds two values. Returns an error if one of the values are invalid or
// currency codes are not matching (unless currency code is unspecified for
// both).
-func Sum(l, r Money) (Money, error) {
+func Sum(l, r currency.Money) (currency.Money, error) {
if !IsValid(l) || !IsValid(r) {
- return Money{}, ErrInvalidValue
+ return currency.Money{}, ErrInvalidValue
} else if l.CurrencyCode != r.CurrencyCode {
- return Money{}, ErrMismatchingCurrency
+ return currency.Money{}, ErrMismatchingCurrency
}
units := l.Units + r.Units
nanos := l.Nanos + r.Nanos
@@ -130,7 +115,7 @@ func Sum(l, r Money) (Money, error) {
}
}
- return Money{
+ return currency.Money{
Units: units,
Nanos: nanos,
CurrencyCode: l.CurrencyCode}, nil
@@ -138,7 +123,7 @@ func Sum(l, r Money) (Money, error) {
// MultiplySlow is a slow multiplication operation done through adding the value
// to itself n-1 times.
-func MultiplySlow(m Money, n uint32) Money {
+func MultiplySlow(m currency.Money, n uint32) currency.Money {
out := m
for n > 1 {
out = Must(Sum(out, m))
diff --git a/backend/online-boutique/go.mod b/backend/online-boutique/go.mod
index 6f115d2f..12eaee17 100644
--- a/backend/online-boutique/go.mod
+++ b/backend/online-boutique/go.mod
@@ -1,44 +1,3 @@
module github.com/TBD54566975/ftl/examples/online-boutique
-go 1.21.3
-
-replace github.com/TBD54566975/ftl => ../..
-
-require (
- github.com/TBD54566975/ftl v0.0.0-00010101000000-000000000000
- github.com/alecthomas/errors v0.4.0
- github.com/google/uuid v1.4.0
- github.com/hashicorp/golang-lru/v2 v2.0.5
- golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63
-)
-
-require (
- connectrpc.com/connect v1.11.1 // indirect
- connectrpc.com/grpcreflect v1.2.0 // indirect
- connectrpc.com/otelconnect v0.5.0 // indirect
- github.com/alecthomas/concurrency v0.0.2 // indirect
- github.com/alecthomas/participle/v2 v2.0.0 // indirect
- github.com/alecthomas/types v0.7.1 // indirect
- github.com/alessio/shellescape v1.4.1 // indirect
- github.com/danieljoos/wincred v1.1.0 // indirect
- github.com/go-logr/logr v1.2.4 // indirect
- github.com/go-logr/stdr v1.2.2 // indirect
- github.com/godbus/dbus/v5 v5.1.0 // indirect
- github.com/iancoleman/strcase v0.2.0 // indirect
- github.com/jpillora/backoff v1.0.0 // indirect
- github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
- github.com/mattn/go-isatty v0.0.17 // indirect
- github.com/oklog/ulid/v2 v2.1.0 // indirect
- github.com/rs/cors v1.9.0 // indirect
- github.com/swaggest/jsonschema-go v0.3.62 // indirect
- github.com/swaggest/refl v1.3.0 // indirect
- github.com/zalando/go-keyring v0.2.1 // indirect
- go.opentelemetry.io/otel v1.19.0 // indirect
- go.opentelemetry.io/otel/metric v1.19.0 // indirect
- go.opentelemetry.io/otel/trace v1.19.0 // indirect
- golang.org/x/net v0.17.0 // indirect
- golang.org/x/sync v0.3.0 // indirect
- golang.org/x/sys v0.13.0 // indirect
- golang.org/x/text v0.13.0 // indirect
- google.golang.org/protobuf v1.31.0 // indirect
-)
+go 1.21.6
diff --git a/backend/online-boutique/go.sum b/backend/online-boutique/go.sum
index 0321db76..e69de29b 100644
--- a/backend/online-boutique/go.sum
+++ b/backend/online-boutique/go.sum
@@ -1,142 +0,0 @@
-connectrpc.com/connect v1.11.1 h1:dqRwblixqkVh+OFBOOL1yIf1jS/yP0MSJLijRj29bFg=
-connectrpc.com/connect v1.11.1/go.mod h1:3AGaO6RRGMx5IKFfqbe3hvK1NqLosFNP2BxDYTPmNPo=
-connectrpc.com/grpcreflect v1.2.0 h1:Q6og1S7HinmtbEuBvARLNwYmTbhEGRpHDhqrPNlmK+U=
-connectrpc.com/grpcreflect v1.2.0/go.mod h1:nwSOKmE8nU5u/CidgHtPYk1PFI3U9ignz7iDMxOYkSY=
-connectrpc.com/otelconnect v0.5.0 h1:K7xQKFbgeaHx563B+IIbd1EJe856AanueIYtGEtdnH8=
-connectrpc.com/otelconnect v0.5.0/go.mod h1:cjBMmtJmTokg4/k/3iDjLOjfNVM4qSVfIWz/qWQ8FNw=
-github.com/alecthomas/assert/v2 v2.3.0 h1:mAsH2wmvjsuvyBvAmCtm7zFsBlb8mIHx5ySLVdDZXL0=
-github.com/alecthomas/assert/v2 v2.3.0/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ=
-github.com/alecthomas/concurrency v0.0.2 h1:Q3kGPtLbleMbH9lHX5OBFvJygfyFw29bXZKBg+IEVuo=
-github.com/alecthomas/concurrency v0.0.2/go.mod h1:GmuQb/iHX7mbNtPlC/WDzEFxDMB0HYFer2Qda9QTs7w=
-github.com/alecthomas/errors v0.4.0 h1:zDIapqdw7gVx2BrQpw3Ll5YRGFuaiB0ywcjesqT0RIE=
-github.com/alecthomas/errors v0.4.0/go.mod h1:0DQf6/xQp3f9rv+k72g2NmeTW2lC74kXA6b/8dN9BwY=
-github.com/alecthomas/participle/v2 v2.0.0 h1:Fgrq+MbuSsJwIkw3fEj9h75vDP0Er5JzepJ0/HNHv0g=
-github.com/alecthomas/participle/v2 v2.0.0/go.mod h1:rAKZdJldHu8084ojcWevWAL8KmEU+AT+Olodb+WoN2Y=
-github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk=
-github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
-github.com/alecthomas/types v0.7.1 h1:zU49e5jp0MS4sVDq0yEX4uX/jX7aVpvwd+Rm632ZpEQ=
-github.com/alecthomas/types v0.7.1/go.mod h1:t7PnU03TVweFpbPVKaeLtFykjJD8rqiBJ7gfkp6UvLQ=
-github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0=
-github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30=
-github.com/bool64/dev v0.2.31 h1:OS57EqYaYe2M/2bw9uhDCIFiZZwywKFS/4qMLN6JUmQ=
-github.com/bool64/dev v0.2.31/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg=
-github.com/bool64/shared v0.1.5 h1:fp3eUhBsrSjNCQPcSdQqZxxh9bBwrYiZ+zOKFkM0/2E=
-github.com/bool64/shared v0.1.5/go.mod h1:081yz68YC9jeFB3+Bbmno2RFWvGKv1lPKkMP6MHJlPs=
-github.com/danieljoos/wincred v1.1.0 h1:3RNcEpBg4IhIChZdFRSdlQt1QjCp1sMAPIrOnm7Yf8g=
-github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg=
-github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
-github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
-github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
-github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
-github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
-github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
-github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
-github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
-github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
-github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
-github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
-github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4=
-github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
-github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
-github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
-github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc=
-github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJDkXXS7VoV7XGE=
-github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0=
-github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
-github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
-github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
-github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
-github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
-github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
-github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
-github.com/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU=
-github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
-github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
-github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
-github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
-github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE=
-github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
-github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
-github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
-github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
-github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
-github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
-github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/swaggest/assertjson v1.9.0 h1:dKu0BfJkIxv/xe//mkCrK5yZbs79jL7OVf9Ija7o2xQ=
-github.com/swaggest/assertjson v1.9.0/go.mod h1:b+ZKX2VRiUjxfUIal0HDN85W0nHPAYUbYH5WkkSsFsU=
-github.com/swaggest/jsonschema-go v0.3.62 h1:eIE0aRklWa2eLJg2L/zqyWpKvgUPbq2oKOtrJGJkPH0=
-github.com/swaggest/jsonschema-go v0.3.62/go.mod h1:DYuKqdpms/edvywsX6p1zHXCZkdwB28wRaBdFCe3Duw=
-github.com/swaggest/refl v1.3.0 h1:PEUWIku+ZznYfsoyheF97ypSduvMApYyGkYF3nabS0I=
-github.com/swaggest/refl v1.3.0/go.mod h1:3Ujvbmh1pfSbDYjC6JGG7nMgPvpG0ehQL4iNonnLNbg=
-github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA=
-github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
-github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M=
-github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
-github.com/zalando/go-keyring v0.2.1 h1:MBRN/Z8H4U5wEKXiD67YbDAr5cj/DOStmSga70/2qKc=
-github.com/zalando/go-keyring v0.2.1/go.mod h1:g63M2PPn0w5vjmEbwAX3ib5I+41zdm4esSETOn9Y6Dw=
-go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs=
-go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY=
-go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE=
-go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8=
-go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o=
-go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A=
-go.opentelemetry.io/otel/sdk/metric v1.19.0 h1:EJoTO5qysMsYCa+w4UghwFV/ptQgqSL/8Ni+hx+8i1k=
-go.opentelemetry.io/otel/sdk/metric v1.19.0/go.mod h1:XjG0jQyFJrv2PbMvwND7LwCEhsJzCzV5210euduKcKY=
-go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg=
-go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo=
-golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ=
-golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8=
-golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
-golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
-golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
-golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
-golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
-golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
-golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
-golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E=
-golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
-google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
-google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
-gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
-gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
-lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
-modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw=
-modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0=
-modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw=
-modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY=
-modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE=
-modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY=
-modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
-modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
-modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
-modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
-modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
-modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
-modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM=
-modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk=
-modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
-modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
-modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
-modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
diff --git a/backend/online-boutique/services/ad-kotlin/pom.xml b/backend/online-boutique/services/ad-kotlin/pom.xml
deleted file mode 100644
index d873ce92..00000000
--- a/backend/online-boutique/services/ad-kotlin/pom.xml
+++ /dev/null
@@ -1,198 +0,0 @@
-
-
- 4.0.0
- xyz.block
- ad-kotlin
- 1.0-SNAPSHOT
-
-
- 1.0-SNAPSHOT
- 11
- 1.9.0
- true
- ${java.version}
- ${java.version}
-
-
-
-
- org.jetbrains.kotlin
- kotlin-stdlib
- ${kotlin.version}
-
-
- ${project.groupId}
- ftl-runtime
- ${ftl.version}
-
-
- ${project.groupId}
- ftl-generator
- ${ftl.version}
-
-
-
-
-
-
- kotlin-maven-plugin
- org.jetbrains.kotlin
- ${kotlin.version}
-
-
- compile
-
- compile
-
-
-
- ${project.basedir}/src/main/kotlin
-
-
-
-
- test-compile
-
- test-compile
-
-
-
- ${project.basedir}/src/test/kotlin
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-dependency-plugin
- 3.2.0
-
-
- initialize
-
- copy
-
-
-
-
- xyz.block
- ftl-generator
- ${ftl.version}
- jar-with-dependencies
- ftl-generator.jar
-
-
- xyz.block
- ftl-runtime
- ${ftl.version}
- jar-with-dependencies
- ftl-runtime.jar
-
-
-
-
-
- copy-dependencies
- compile
-
- copy-dependencies
-
-
- ${project.build.directory}/dependency
- runtime
-
-
-
- build-classpath
- compile
-
- build-classpath
-
-
- ${project.build.directory}/classpath.txt
- generated.classpath
- ${project.build.directory}/dependency
-
-
-
-
-
-
- org.codehaus.mojo
- exec-maven-plugin
- 3.0.0
-
-
- initialize
-
- exec
-
-
- java
-
- -jar
- target/dependency/ftl-generator.jar
- --endpoint=http://127.0.0.1:8892
- --dest=${project.build.directory}
- --module=ad
-
-
-
-
-
-
- org.codehaus.mojo
- build-helper-maven-plugin
- 3.2.0
-
-
- generate-sources
-
- add-source
-
-
-
-
-
-
-
-
-
-
- com.github.ozsie
- detekt-maven-plugin
- 1.23.3
-
- true
- ${generated.classpath}
- ${java.version}
- ${project.build.directory}/detekt.yml
-
-
- ${project.build.directory}/dependency/ftl-runtime-${ftl.version}.jar
-
-
-
-
-
- compile
-
- check-with-type-resolution
-
-
-
-
-
- xyz.block
- ftl-runtime
- ${ftl.version}
-
-
-
-
-
-
\ No newline at end of file
diff --git a/backend/online-boutique/services/ad-kotlin/src/main/kotlin/ftl/ad/Ad.kt b/backend/online-boutique/services/ad-kotlin/src/main/kotlin/ftl/ad/Ad.kt
deleted file mode 100644
index ea57769f..00000000
--- a/backend/online-boutique/services/ad-kotlin/src/main/kotlin/ftl/ad/Ad.kt
+++ /dev/null
@@ -1,78 +0,0 @@
-package ftl.ad
-
-import com.google.gson.Gson
-import com.google.gson.annotations.SerializedName
-import com.google.gson.reflect.TypeToken
-import xyz.block.ftl.Context
-import xyz.block.ftl.Ingress
-import xyz.block.ftl.Method
-import xyz.block.ftl.Verb
-import xyz.block.ftl.serializer.makeGson
-import java.util.*
-
-data class Ad(@SerializedName("RedirectURL") val redirectUrl: String, @SerializedName("Text") val text: String)
-data class AdRequest(val contextKeys: List)
-data class AdResponse(val ads: List)
-
-class AdModule {
- private val database: Map = loadDatabase()
-
- @Throws(Exception::class)
- @Verb
- @Ingress(Method.GET, "/get")
- fun get(context: Context, req: AdRequest): AdResponse {
- return when {
- req.contextKeys.isNotEmpty() -> AdResponse(ads = contextualAds(req.contextKeys))
- else -> AdResponse(ads = randomAds())
- }
- }
-
- private fun contextualAds(contextKeys: List): List {
- return contextKeys.map { database[it] ?: throw Exception("no ad registered for this context key") }
- }
-
- private fun randomAds(): List {
- val ads = mutableListOf()
- val random = Random()
- repeat(MAX_ADS_TO_SERVE) {
- ads.add(database.entries.elementAt(random.nextInt(database.size)).value)
- }
- return ads
- }
-
- companion object {
- private const val MAX_ADS_TO_SERVE = 2
- private const val DATABASE_JSON = "{\n" +
- " \"hair\": {\n" +
- " \"RedirectURL\": \"/product/2ZYFJ3GM2N\",\n" +
- " \"Text\": \"Hairdryer for sale. 50% off.\"\n" +
- " },\n" +
- " \"clothing\": {\n" +
- " \"RedirectURL\": \"/product/66VCHSJNUP\",\n" +
- " \"Text\": \"Tank top for sale. 20% off.\"\n" +
- " },\n" +
- " \"accessories\": {\n" +
- " \"RedirectURL\": \"/product/1YMWWN1N4O\",\n" +
- " \"Text\": \"Watch for sale. Buy one, get second kit for free\"\n" +
- " },\n" +
- " \"footwear\": {\n" +
- " \"RedirectURL\": \"/product/L9ECAV7KIM\",\n" +
- " \"Text\": \"Loafers for sale. Buy one, get second one for free\"\n" +
- " },\n" +
- " \"decor\": {\n" +
- " \"RedirectURL\": \"/product/0PUK6V6EV0\",\n" +
- " \"Text\": \"Candle holder for sale. 30% off.\"\n" +
- " },\n" +
- " \"kitchen\": {\n" +
- " \"RedirectURL\": \"/product/9SIQT8TOJO\",\n" +
- " \"Text\": \"Bamboo glass jar for sale. 10% off.\"\n" +
- " }\n" +
- "}"
-
- private fun loadDatabase(): Map {
- return makeGson().fromJson