deploy open-saas on Google Cloud Platform (firebase + cloud run)

Hello, I've recently gone through the steps to deploy open-saas on GCP and I believe it could be useful to document it here for now.
This could be added to the real documentation in the future, for now I'll just detail what I did to make it work.
A few prerequisites:
• Have a GCP account & project with billing enabled (you might succeed without, but that's what I had).
• Successfully run the open-saas template locally with, the appropriate env variable and an emailSender not send to Dummy.
Step 1 - GCP & firebase setup:
First, login to GCP and populate the default credentials. This step is important, it will ensure you don't get access issues.
Run the 2 command separately and login each time:
gcloud auth login
gcloud auth application-default login
In your GPC project, enable the needed APIs:
# Enable the Artifact Registry API - storing docker images
gcloud services enable artifactregistry.googleapis.com

# Enable the Cloud Run API - running serverless containers for the backend
gcloud services enable run.googleapis.com

We will be building our Docker image and storing it in GCP, therefore we need to create an artifact registry where we will push the image:
# REMEMBER THE NAME AND REGION, IN LATER STEPS YOU WILL USE THEM
gcloud artifacts repositories create open-saas \
    --repository-format=docker \
    --location=europe-west1 \
    --description="Docker repository for Open SaaS"

For the firebase setup:

Go to https://console.firebase.google.com/
Click on Add project and select your GCP project
Just click continue untill your at the firebase console

Step 2 - Deploy the frontend with firebase hosting
Follow the step 1 and 3 to get the build of the frontend (give a fake REACT_APP_API_URL for now, since we don't have it yet) --> https://wasp-lang.dev/docs/0.11.8/advanced/deployment/manually#1-generating-deployable-code
Add this firebase.json and .firebashrc at the root of your repo, optionally you can put them elsewhere but you need to adapt the paths and where you will run the firebase commands:
firebase.json
{
  "hosting": {
    "public": "app/.wasp/build/web-app/build",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ]
  }
}

.firebaserc
{
  "projects": {
    "default": {FILL_YOUR_FULL__GCP_PROJECT_NAME}
  }
}

Now you are ready to deploy the frontend:

Install the firebase cli npm install -g firebase-tools
login with firebase login
deploy with firebase deploy --only hosting --> Do this from the root of the repo if you did place the firebase.json at root and didn't change any path
Your front should be available at something like : https://{FILL_YOUR_FULL__GCP_PROJECT_NAME}.web.app

Step 3 - Deploy the backend with cloud run
Cloud run expects the container service to be exposed on port 8080, this cannot be changed. So we need to find a way to do this, luckily the wasp team enabled us to overwrite the Dockerfile server entry point and add any steps ! See the doc --> https://wasp-lang.dev/docs/advanced/deployment/overview#customizing-the-dockerfile
Create a Dockerfile at ./app/Dockerfile
ENV PORT=8080
EXPOSE 8080

ENTRYPOINT ["npm", "run", "start-production"]

Now you need to do a wasp build again with this setup to update the Dockerfile under .wasp/build/Dockerfile.
After the wasp build command, you can check that the new Dockerfile has indeed your added steps in it.
Build the image and push it to Artifact Registry. I will use the Docker Artifact Registry I created in step 1 but adapt it to the one you created:
docker build -t backend-image -f Dockerfile .
# Adapt name and region to the one created earlier
docker tag backend-image europe-west1-docker.pkg.dev/{FILL_YOUR_FULL__GCP_PROJECT_NAME}/backend/backend-image
docker push europe-west1-docker.pkg.dev/{FILL_YOUR_FULL__GCP_PROJECT_NAME}/backend/backend-image

Once the image is successfully uploaded to artifact registry, you can deploy your backlend with:
          gcloud run deploy backend \
            --image europe-west1-docker.pkg.dev/{FILL_YOUR_FULL__GCP_PROJECT_NAME}/backend/backend-image \
            --project {FILL_YOUR_FULL__GCP_PROJECT_NAME} \
            --platform managed \
            --region europe-west1 \
            --max-instances 2 \ # This limit auto scaling, if you have a lot of traffic you can increase this
            --allow-unauthenticated \
            --set-env-vars "DATABASE_URL=fake_database_url" \
            --set-env-vars "STRIPE_KEY=fake_stripe_key" \
            --set-env-vars "GOOGLE_CLIENT_ID=fake_google_client_id" \
            --set-env-vars "GOOGLE_CLIENT_SECRET=fake_google_client_secret" \
            --set-env-vars "HOBBY_SUBSCRIPTION_PRICE_ID=fake_hobby_subscription_price_id" \
            --set-env-vars "PRO_SUBSCRIPTION_PRICE_ID=fake_pro_subscription_price_id" \
            --set-env-vars "SENDGRID_API_KEY=fake_sendgrid_api_key" \
            --set-env-vars "STRIPE_WEBHOOK_SECRET=fake_stripe_webhook_secret" \
            --set-env-vars "WASP_SERVER_URL=fake_wasp_server_url" \ # <--- You don't know it for now, but change it after the first deployment to the real one
            --set-env-vars "WASP_WEB_CLIENT_URL=fake_wasp_web_client_url" \ # <--- Use the value you got at the end of step 2 that looks like https://{FILL_YOUR_FULL__GCP_PROJECT_NAME}.web.app
            --set-env-vars "ADMIN_EMAILS=fake_admin_emails" \
            --set-env-vars "JWT_SECRET=fake_jwt_secret"

You will receive a made up backend URL, for example https://backend-feiufeaoa-ew.a.run.app
Step 4 - Link the frontend and backend
You now have all the elements, you just need to piece it together:

Re-do step 2, this time with the real REACT_APP_API_URL set to your backend URL (https://backend-feiufeaoa-ew.a.run.app)
Change the WASP_SERVER_URL env variable of your backend to the real one (https://backend-feiufeaoa-ew.a.run.app)

You can go back to your frontend under https://{FILL_YOUR_FULL__GCP_PROJECT_NAME}.web.app and check that everything works.
The backend URL is a bit ugly, additionally it is not under the same domain so you might run under CORS issues. Firebase offers automatic redirect to the cloud run backend directly from your website, I still need to crack that part !

Optional, but if you need to see every steps as one big script I've made github actions for my CD. This might give a global overview of the steps to follow:
backend-cd.yml
name: Deploy to Cloud Run on merge

on:
  push:
    branches:
      - main

jobs:
  build_and_deploy_backend:
    runs-on: ubuntu-latest

    env:
      # Env variables
      GCP_PROJECT_ID: ${{ vars.GCP_PROJECT_ID }}
      WASP_SERVER_URL_DEV: ${{ vars.WASP_SERVER_URL_DEV }}
      WASP_WEB_CLIENT_URL_DEV: ${{ vars.WASP_WEB_CLIENT_URL_DEV }}
      ADMIN_EMAILS_DEV: ${{ vars.ADMIN_EMAILS_DEV }}
      # Secrets
      DATABASE_URL_DEV: ${{ secrets.DATABASE_URL_DEV }}
      SERVICE_ACCOUNT: ${{ secrets.SERVICE_ACCOUNT }}
      GOOGLE_CLIENT_ID_DEV: ${{ secrets.GOOGLE_CLIENT_ID_DEV }}
      GOOGLE_CLIENT_SECRET_DEV: ${{ secrets.GOOGLE_CLIENT_SECRET_DEV }}
      HOBBY_SUBSCRIPTION_PRICE_ID_DEV: ${{ secrets.HOBBY_SUBSCRIPTION_PRICE_ID_DEV }}
      PRO_SUBSCRIPTION_PRICE_ID_DEV: ${{ secrets.PRO_SUBSCRIPTION_PRICE_ID_DEV }}
      SENDGRID_API_KEY_DEV: ${{ secrets.SENDGRID_API_KEY_DEV }}
      STRIPE_KEY_DEV: ${{ secrets.STRIPE_KEY_DEV }}
      STRIPE_WEBHOOK_SECRET_DEV: ${{ secrets.STRIPE_WEBHOOK_SECRET_DEV }}
      JWT_SECRET_DEV: ${{ secrets.JWT_SECRET}}

    steps:
      - uses: actions/checkout@v4

      - name: Build Docker Image
        run: |
          curl -sSL https://get.wasp-lang.dev/installer.sh | sh
          cd app
          wasp build
          cd .wasp/build
          docker build -t backend-image -f Dockerfile .
          docker tag backend-image europe-west1-docker.pkg.dev/${{ env.GCP_PROJECT_ID }}/backend/backend-image:${{ github.sha }}

      - name: Authenticate to GCP
        uses: google-github-actions/auth@v1
        with:
          credentials_json: ${{ secrets.SERVICE_ACCOUNT }}

      - name: Configure Docker
        run: |
          gcloud auth configure-docker europe-west1-docker.pkg.dev

      - name: Push Docker Image
        run: |
          docker push europe-west1-docker.pkg.dev/${{ env.GCP_PROJECT_ID }}/backend/backend-image:${{ github.sha }}

      - name: Deploy to Cloud Run
        run: |
          gcloud run deploy backend \
            --image europe-west1-docker.pkg.dev/${{ env.GCP_PROJECT_ID }}/backend/backend-image:${{ github.sha }} \
            --project ${{ env.GCP_PROJECT_ID }} \
            --platform managed \
            --region europe-west1 \
            --max-instances 2 \
            --min-instances 0 \
            --allow-unauthenticated \
            --set-env-vars "DATABASE_URL=${{ env.DATABASE_URL_DEV }}" \
            --set-env-vars "STRIPE_KEY=${{ env.STRIPE_KEY_DEV }}" \
            --set-env-vars "GOOGLE_CLIENT_ID=${{ env.GOOGLE_CLIENT_ID_DEV }}" \
            --set-env-vars "GOOGLE_CLIENT_SECRET=${{ env.GOOGLE_CLIENT_SECRET_DEV }}" \
            --set-env-vars "HOBBY_SUBSCRIPTION_PRICE_ID=${{ env.HOBBY_SUBSCRIPTION_PRICE_ID_DEV }}" \
            --set-env-vars "PRO_SUBSCRIPTION_PRICE_ID=${{ env.PRO_SUBSCRIPTION_PRICE_ID_DEV }}" \
            --set-env-vars "SENDGRID_API_KEY=${{ env.SENDGRID_API_KEY_DEV }}" \
            --set-env-vars "STRIPE_WEBHOOK_SECRET=${{ env.STRIPE_WEBHOOK_SECRET_DEV }}" \
            --set-env-vars "WASP_SERVER_URL=${{ env.WASP_SERVER_URL_DEV }}" \
            --set-env-vars "WASP_WEB_CLIENT_URL=${{ env.WASP_WEB_CLIENT_URL_DEV }}" \
            --set-env-vars "ADMIN_EMAILS=${{ env.ADMIN_EMAILS_DEV }}" \
            --set-env-vars "JWT_SECRET=${{ env.JWT_SECRET_DEV }}"

frontend-cd.yml
name: Deploy to Firebase Hosting on merge
on:
  push:
    branches:
      - main

jobs:
  build_and_deploy_frontend:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: |
          curl -sSL https://get.wasp-lang.dev/installer.sh | sh
          cd app
          wasp build
          cd .wasp/build/web-app
          npm install
          REACT_APP_API_URL=${{ vars.WASP_SERVER_URL_DEV }}
          npm run build
      - uses: FirebaseExtended/action-hosting-deploy@v0
        with:
          repoToken: ${{ secrets.GITHUB_TOKEN }}
          firebaseServiceAccount: ${{ secrets.SERVICE_ACCOUNT }}
          channelId: live
          projectId: ${{ vars.GCP_PROJECT_ID }}

This is awesome, thanks @TomDarmon !
We can use this as a good foundation for writing the docs for deploying to GCP.
CI action is also quite useful!

Is this just for the hosting? I am currently trying to link up an existing project that uses firebase as DB to use open-saas to add payments, but there doesnt seem to be an easy way to replace the prism stuff with firebase.

@avetise yes correct, it says above firebase is used for static hosting. I can update the github issue to make that clearer.
Using firebase instead of Prisma -> Wasp is currently heavly relying on Prisma, and while you can use firebase on the side as additional db, replacing Prisma with Firebase at this point wouldn't make much sense I think.


autopilot md: Fix typo

Fix typo.
,it's

should be
, it's

@rmandvikar : Thanks for your contribution! The author(s) have been notified to review your proposed change.

Verified.
@rmandvikar Thanks for submitting the typo fix.


Do not generate redundant decompositions

Was it a straight mistake?

It seems so. @csiki2 found that the decomposer was creating duplicated combinations when it was supposed to be impossible but it resulted it was called multiple times.


Support for polymer

Hi,
Is there any support for javascript library like polymer?

@Sam2243 Hello! At the moment not, but we will think about it.

Hi,
Thank you. Actually I really liked this component so for now I will use it through jquery and embedding it in my polymer project :P hopefully no conflicts :D

@Sam2243, for web components, you can try to implement this approach (https://github.com/MrCheater/habrahabr-universal-component) based on preact(https://preactjs.com/). We' ve used it for jQuery and Angular versions.


Update documentation with "how to debug"

Describe the feature
Nuxt now has a page called "Debugging" (https://nuxt.com/docs/guide/going-further/debugging#example-jetbrains-ides-debug-configuration)
It would be nice to add a support page for nitro.
Both https://github.com/unjs/nitro/discussions/2141 and https://github.com/unjs/nitro/discussions/2057 already mention how to do this for vscode and jetbrains.
I would be able to add an initial page if helped in what to add to the page and where to put it.
Additional information

[X] Would you be willing to help implement this feature?

Neither of those solutions works on Windows though :< Getting this error with the base nitro project:
C:\Repos\Sandbox\nitro-debug-test\node_modules\.bin\nitropack:2
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
          ^^^^^^^

SyntaxError: missing ) after argument list
    at wrapSafe (node:internal/modules/cjs/loader:1515:18)
    at Module._compile (node:internal/modules/cjs/loader:1537:20)
    at Object..js (node:internal/modules/cjs/loader:1708:10)
    at Module.load (node:internal/modules/cjs/loader:1318:32)
    at Function._load (node:internal/modules/cjs/loader:1128:12)
    at TracingChannel.traceSync (node:diagnostics_channel:322:14)
    at wrapModuleLoad (node:internal/modules/cjs/loader:219:24)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:170:5)
    at node:internal/main/run_main_module:36:49

Node.js v22.12.0

Here is my config:
{
            "type": "node",
            "request": "launch",
            "name": "backend: users",
            "outputCapture": "std",
            "program": "${workspaceFolder}/backend/users-service/node_modules/.bin/nitropack",
            "args": [
                "dev"
            ],
            "restart": true,
            "console": "integratedTerminal",
            "skipFiles": [
                "<node_internals>/**"
            ]
        }

In fact, I couldn't get Nuxt debug to work either, but different error.


Search is endless looping with Sphinx 3.4.1

Describe the bug
Search is endless looping with Sphinx 3.4.1.
To Reproduce

Create a minimal Sphinx 3.4.1 documentation with:

as conf.py, the same as default, except of course html_theme = 'furo' instead of html_theme = 'alabaster':

# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Path setup --------------------------------------------------------------

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))

# -- Project information -----------------------------------------------------

project = 'Test 3.4.1'
copyright = '2020, Denis Bitouzé'
author = 'Denis Bitouzé'

# -- General configuration ---------------------------------------------------

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
]

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = []

# -- Options for HTML output -------------------------------------------------

# The theme to use for HTML and HTML Help pages.  See the documentation for
# a list of builtin themes.
#
# html_theme = 'alabaster'
html_theme = 'furo'

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']

as index.rst, almost the default one:

.. Test 3.4.1 documentation master file, created by
   sphinx-quickstart on Sat Dec 26 14:09:47 2020.
   You can adapt this file completely to your liking, but it should at least
   contain the root `toctree` directive.

Welcome to Test 3.4.1's documentation!
======================================

.. toctree::
   :maxdepth: 2
   :caption: Contents:

This a title
============

Indices and tables
==================

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

Run make html.
Open the index.html resulting file in any Web browser.
Search e.g. "title".

The searching will endless loop on: "Searching", "Searching.", "Searching..", "Searching...".
Expected behavior
Search works as expected.
Desktop (please complete the following information):

OS: Linux Mageia 7
Browsers: Firefox, Chromium, GNOME Web, Midori
Version: furo 2020.11.27.beta19 or furo 2020.12.9b21

Additional context
Search is working as expected with:

Sphinx 3.3.1 and Furo,
Sphinx 3.4.1 and Alabaster.

Same issue confirmed with 3.4.1, and the "Stemmer is not defined" error appears again.

Can you try with the current master branch, and confirm if this is still an issue?

Can you try with the current master branch, and confirm if this is still an issue?

I installed furo thanks to pip3 and also cloned locally its GitHub cloned repository. But could you explain how to tell Sphinx to use not the former but the latter?

BTW, I guess the current master branch is the one called main, isn't it?

Yea, sorry, the current main branch, yea.

To install furo from the git repository, from the root of the git repository, you'll want to do:
npm install
gulp build
pip install .

That should install it in the current pip environment.

To install furo from the git repository, from the root of the git repository, you'll want to do:
npm install
gulp build
pip install .

That should install it in the current pip environment.

I had to install gulp independently (and as root). Otherwise, it was correctly installed.

Can you try with the current master branch, and confirm if this is still an issue?

It looks like it works nicely, now: thanks!
When could we expect a new (at least furo-2020.12.9.dev22) release fixing this issue?

Once my new monitor arrives later today, to so that I can use my laptop-with-a-broken-display again. :)


ajaxToolkit:AutoCompleteExtender version 3.5.7

I have AjaxControlToolkit version <IP_ADDRESS>3 and VS 2013 an am having issues with ajaxToolkit:AutoCompleteExtender (not firing). I suspect a higher version of AjaxControlToolkit may resolve the issue but wanted another pair of eyes or thoughts that may help to figure this out.
Here is snip from code...
see updates below.

Let me clarify: this code never fired an event or it stopped to fire it after you added AutoCompleteExtender?

Sorry, I was not clear. The issue at hand is that when I type in the textbox named "AutoComplete_PartFooter" I expected it to fire off the autocompleteextender and the servicemethod to run, but it is not. When I type in a character in the textbox, it does not even fire the OnTextChanged. When I type in the textbox and then click outside of the textbox on the form somewhere else, then the OnTextChanged fires but the service method is never executed.

@eldridgegl Thank you for your reply.
Would you please provide a project with the code you provided earlier?
In that case we can check if the service method is declared properly.

I can provide the relevant snips.
The servicemethod shown earlier is
ServiceMethod="GetPartsAndDescriptions" ServicePath="~/Admin/AutoComplete.asmx"

and in that path the file has
<%@ WebService Language="C#" CodeBehind="~/Support_Code/WebMethods/AutoComplete.cs" Class="AutoComplete" %>

and in that AutoComplete.cs it includes this snip
public string[] GetPartsAndDescriptions(string prefixText, int count, string contextKey)
	{ does stuff here}

but the service method is never reached.

I have upgraded to version 16.1 (latest). It seems that maybe there is some issue with the dynamic generation attempt of scripts. Please see the attached image.

Here is  also my web.config.
web.config.help.txt
Here is the top of the page registration..
<%@ Page Title="Purchasing Manager" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" Inherits="PurchasingManager" CodeBehind="PurchasingManager.aspx.cs" %>

<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ajaxToolkit" %>
<%@ Register Assembly="DevExpress.Web.v14.2, Version=<IP_ADDRESS>, Culture=neutral, PublicKeyToken=b88d1754d700e49a" Namespace="DevExpress.Web" TagPrefix="dx" %>

<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">

    <style type="text/css">
        .RowStyle {
            height: 50px;
        }

        .removeFromView {
            display: none;
        }

        .style1 {
            width: 200px;
        }

        .auto-style1 {
            width: 52%;
        }
    </style>
</asp:Content>

<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent" ViewStateMode="Enabled">
    <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true"
        EnablePageMethods="true" LoadScriptsBeforeUI="False" ScriptMode="Release">
        <CompositeScript>
            <Scripts>
                <asp:ScriptReference Path="~/Scripts/MyScripts.js" />
            </Scripts>
        </CompositeScript>

    </asp:ScriptManager>

The error is coming from the "tb_filter" Textbox.
    <div id="SearchControl" runat="server">
        <asp:Label ID="Label3" runat="server" Font-Size="12pt" Text="Filter Search:" Width="200px"
            Font-Bold="True"></asp:Label>
        <asp:TextBox ID="tb_Filter" runat="server" autocomplete="off" AutoPostBack="true" OnTextChanged="txtSearch_TextChanged" onkeyup="return true;" ClientIDMode="Static"
            Width="245px"></asp:TextBox>
        <script type="text/javascript">
            function clearTextBox() {
                document.getElementById('<%= tb_Filter.ClientID %>').value = "";
            }
        </script>
        <asp:LinkButton ID="lb_clearText" runat="server" Font-Size="12pt"
            OnClientClick="clearTextBox()"><--Clear Text</asp:LinkButton>
    </div>
    <ajaxToolkit:AutoCompleteExtender ID="tb_Filter_AutoCompleteExtender" runat="server"
        CompletionInterval="220" CompletionSetCount="1" CompletionListCssClass="AutoCompleteExtender_CompletionList"
        CompletionListHighlightedItemCssClass="AutoCompleteExtender_HighlightedItem"
        CompletionListItemCssClass="AAutoCompleteExtender_CompletionListItem" DelimiterCharacters=""
        Enabled="True" MinimumPrefixLength="1" ServiceMethod="GetPartsAndDescriptions" ServicePath="~/Admin/AutoComplete.asmx"
        TargetControlID="tb_Filter">
    </ajaxToolkit:AutoCompleteExtender>

Any help would really be appreciated.

@eldridgegl
Please check if setting ScriptManager.LoadScriptsBeforeUI to True helps.

AlekseyMartynov  thanks for your reply.
When I changed that to True, I get the below  issue. Since this posting I also upgraded to v16.1 ajaxtoolkit. Let me show you the current failures when value is True then update this posting with current configuration info.
//----------------------------------------------------------
// Copyright (C) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------
// MicrosoftAjaxWebForms.js
Type._registerScript("MicrosoftAjaxWebForms.js",["MicrosoftAjaxCore.js","MicrosoftAjaxSerialization.js","MicrosoftAjaxNetwork.js","MicrosoftAjaxComponentModel.js"]);Type.registerNamespace("Sys.WebForms");
... (lots more output)
...
Type.registerNamespace('Sys.WebForms');Sys.WebForms.Res={"PRM_UnknownToken":"Unknown token: \u0027{0}\u0027.","PRM_MissingPanel":"Could not find UpdatePanel with ID \u0027{0}\u0027. If it is being updated dynamically then it must be inside another UpdatePanel.","PRM_ServerError":"An unknown error occurred while processing the request on the server. The status code returned from the server was: {0}","PRM_ParserError":"The message received from the server could not be parsed. Common causes for this error are when the response is modified by calls to Response.Write(), response filters, HttpModules, or server trace is enabled.\r\nDetails: {0}","PRM_TimeoutError":"The server request timed out.","PRM_ParserErrorDetails":"Error parsing near \u0027{0}\u0027.","PRM_CannotRegisterTwice":"The PageRequestManager cannot be initialized more than once."};

Opened new ticket. Closing this one since I have upgraded and changed web.config to fix the Extender  issues. Please see https://github.com/DevExpress/AjaxControlToolkit/issues/164


ComboBox is not selectable on small screen or frame

Provide a general summary of the issue here
When screen is not tall enough to fit all options in ComboBox popover it is almost impossible to select value using arrow keys or mouse
🤔 Expected Behavior?
Options should be selectable on any screen size
😯 Current Behavior
Popover disappear on arrow keys
💁 Possible Solution
Potentially will be fixed if https://github.com/adobe/react-spectrum/issues/6760 and/or https://github.com/adobe/react-spectrum/issues/6609 fixed
🔦 Context
The problem appears when we have form iframed, it also challenging to select value on landscape mobile as it is hard to scroll list very precisely to not accidentally scroll page and loose popover
🖥 Steps to Reproduce
open https://react-spectrum.adobe.com/react-spectrum/ComboBox.html make screen small (Pixel 7 landscape, this will have issue, but not always, depends on how deep you scroll) or to easier reproduce set screen to 800x250 and open first example using keyboard and try to select the first or the last item.
Version
1.5
What browsers are you seeing the problem on?
Firefox, Chrome
If other, please specify.
No response
What operating system are you using?
Windows / Android
🧢 Your Company/Team
No response
🕷 Tracking Issue
No response

Since this is about keyboard mostly, probably it worth to add that ComboBox doesn't work with Windows Narrator, if you type a character in the field you can't use arrow keys to select value, but I don't report it as a bug because it looks like Narrator problem and not working well on native input + dataset combination without holding Alt key. Maybe just something to consider in future or in docs.


Mirroring Vendored Crates

Args for #71 appear to be inconsistent with the readme documentation regarding synchronization of vendored crates. Maybe I am missing something.

Sync Select Dependencies
Optionally, panamax can be told to only grab crates needed to build a singular project. cargo vendor is used to create a folder with all needed dependencies, then a panamax command can parse the created directory and only grab those crates and versions.
Only grab crates needed for panamax, as an example
$ cargo vendor
$ panamax sync my-mirror vendor

Non-working option:
$panamax sync offline-mirror vendor
error: unexpected argument 'vendor' found

Usage: panamax sync [OPTIONS] <PATH>

Working option:
$panamax sync --vendor-path ./vendor offline-mirror
Syncing Rustup repositories...

The documentation appears to be correct, as far as I can tell. Where did you get your copy of panamax from?


Improving salvo-cli

Seems like salvo-cli is quite basic. Every time I write a new salvo project I copy paste lot of existing code. loco looks pretty great but is for Axum. It is inspired by Rails so has lot of ideas figured out already.
Would be more than happy to help out as necessary.

Here a few things I suggest could help improve the salvo-cli in random order.

use cargo workspace
add support for SPA so client side apps can be written.
Add support for surrealdb. It can be embedded as well as run in clusters, supports vector embeddings
use yaml for config, as this allows other folks in the team not familiar with rust or toml.
generate README.md so we know what the next step is. for now it probably doesn't matter as it just cargo run. For example I had to read the code to understand where the swagger ui is.
add support for background jobs. I think this is very important to enable rich responsive servers.
add support for cron jobs
instead of rand_utils.rs considering using specific files such as password.rs.
Considering using traits for Services. This would allow us to change the implementation via config.
consider consistent naming for routes such as get_user_page_router (for html), get_user_route (for apis), delete_user_route and so on.
remove demo.rs
considering using sub folders for templates.
Add support for sending emails. Emails usually have html templates too.
Add support for 2fa auth.
Add support for App passwords.
Add support for updating/reseting passwords.
call it open api instead of swagger.
add support for login, logout and register in homepage.
Add generic pagination concept.
add CSRF
add localization
add systemic and watch support so saving .rs files would automatically build
add support for server errors. might be even show stack traces in debug mode?
socket.io with https://github.com/Totodore/socketioxide for real time communication
in memory as well as distributed caching
generic storage using https://opendal.apache.org. Allowing to easily swap files from files system to cloud storages.

Probably worth having something like https://pocketbase.io  or https://staticbackend.com and build upon it or just use their schema.

Thank you for every suggestion, you have made a lot of valuable comments from an experienced programmer's perspective, I will prioritize them by my perspective and send them out to be done and optimized little by little.
I have some questions for you.

Is it necessary to maintain multiple orm templates after splitting into workspaces, or should I choose one of them? Because maintaining multiple orm will have a lot of extra tasks and testing work.
My current thinking is to keep the option of multiple orm for single crate and optimize the maintenance. Choose a single orm to continue with some deeper functionality.
On the database side, I use surrealdb less, but it looks very cool and has a lot of features that are necessary for apps nowadays. In your opinion, can surrealdb replace traditional pgsql, MySQL?

By the way, I'm a bit busy at work right now, even working 13 hours a day! I'll keep updating quickly when I can. It's a long way to go. Thanks again for the advice!

My thoughts on sql/db/orm is that salvo-cli only supports one but allows us to bring our own. Here is how I would do it. I will give an example on how one could implement sign up in a generic way. (Pasting code from my old project for reference)

Introduce traits allowing easy change of implementations.

#[async_trait]
pub trait UserService: Sync + Send {
    async fn signup(&self, new_user: &CreateUserRequest) -> AppResult<CreateUserResponse>;
}

If I choose bring your own, replace with todo!(). I can use this with surrealdb or any other implantation.

#[async_trait]
impl UserService for MyUserService {
    async fn signup(&self, new_user: &CreateUserRequest) -> AppResult<CreateUserResponse> {
        todo!();
    }
}

As for database I suggest to go with sqlx but use AnyPool and sea-query-binder. This will allow you to write sql once but use it for sqlite, mysql or Postgres.

sqlx = { version = "0.6.1", default-features = false, features = ["any", "sqlite", "mysql", "postgres"] }
sea-query = "0.27.1"
sea-query-binder = { version = "0.2.1", features = ["sqlx-any", "sqlx-postgres", "sqlx-mysql", "sqlx-sqlite"] }

DB using `AnyPool`
pub struct Db {
    pool: AnyPool,
}

impl Db {
    pub async fn new(config: Arc<Config>) -> AppResult<Self> {
        let (pool_options, pool_max_connections) = if config.database.url.starts_with("sqlite:") {
            let pool_options = config
                .database
                .url
                .parse::<SqliteConnectOptions>()?
                .create_if_missing(true)
                .foreign_keys(true)
                .journal_mode(sqlx::sqlite::SqliteJournalMode::Wal)
                .into();
            let pool_max_connections = 1;
            (pool_options, pool_max_connections)
        } else {
            let pool_options = config.database.url.parse::<PgConnectOptions>()?.into();
            let pool_max_connections = 10;
            (pool_options, pool_max_connections)
        };
        let pool = sqlx::any::AnyPoolOptions::default()
            .max_connections(pool_max_connections)
            .connect_with(pool_options)
            .await?;
        Ok(Self { pool })
    }

    pub fn schema_builder(&self) -> &dyn SchemaBuilder {
        match self.pool.any_kind() {
            AnyKind::Postgres => &PostgresQueryBuilder,
            AnyKind::Sqlite => &SqliteQueryBuilder,
            AnyKind::MySql => &MysqlQueryBuilder,
        }
    }

    pub fn query_builder(&self) -> &dyn QueryBuilder {
        match self.pool.any_kind() {
            AnyKind::Postgres => &PostgresQueryBuilder,
            AnyKind::Sqlite => &SqliteQueryBuilder,
            AnyKind::MySql => &MysqlQueryBuilder,
        }
    }

    pub fn pool(&self) -> &AnyPool {
        &self.pool
    }

    pub fn is_conflict_error(&self, error: &sqlx::Error) -> bool {
        matches!(error, sqlx::Error::Database(dbe) if dbe.code() == Some("2067".into()))
    }
}

Migration now has to move to rust, but you write once and it works for sqlite, mysql and Postgres.
use crate::{models::user::UserIden, AppResult};

use super::MigrationManager;
use sea_query::{ColumnDef, Table};
use sqlx::migrate::MigrationType;

pub fn up(manager: &MigrationManager) -> AppResult<sqlx::migrate::Migration> {
    let sql = Table::create()
        .table(UserIden::Table)
        .if_not_exists()
        .col(
            ColumnDef::new(UserIden::Id)
                .string()
                .string_len(255)
                .not_null()
                .primary_key(),
        )
        .col(
            ColumnDef::new(UserIden::Username)
                .string()
                .string_len(255)
                .not_null()
                .unique_key(),
        )
        .col(
            ColumnDef::new(UserIden::PasswordHash)
                .string()
                .string_len(255)
                .not_null(),
        )
        .col(ColumnDef::new(UserIden::IsLocked).boolean().not_null())
        .col(ColumnDef::new(UserIden::IsAdmin).boolean().not_null())
        .col(
            ColumnDef::new(UserIden::ColorScheme)
                .string()
                .string_len(255)
                .not_null(),
        )
        .build_any(manager.schema_builder());

    Ok(sqlx::migrate::Migration::new(
<PHONE_NUMBER>2300,
        "create user table".into(),
        MigrationType::ReversibleUp,
        sql.into(),
    ))
}

pub fn down(manager: &MigrationManager) -> AppResult<sqlx::migrate::Migration> {
    let sql = Table::drop()
        .table(UserIden::Table)
        .if_exists()
        .build_any(manager.schema_builder());
    Ok(sqlx::migrate::Migration::new(
<PHONE_NUMBER>2300,
        "drop user table".into(),
        MigrationType::ReversibleDown,
        sql.into(),
    ))
}

Queries are also generic that works in sqlite, mysql and postgres.
#[async_trait]
impl UserService for SqlUserService {
    async fn signup(&self, new_user: &CreateUserRequest) -> AppResult<CreateUserResponse> {
        new_user.validate()?;

        let id = new_id();

        let salt = generate_salt();

        let password_hash = compute_password_hash(&new_user.password, &Secret::new(salt))?;

        let is_admin = if self.config.auth.first_user_admin {
            self.get_total_user_count().await? == 0
        } else {
            false
        };

        let (sql, values) = Query::insert()
            .into_table(UserIden::Table)
            .columns([
                UserIden::Id,
                UserIden::Username,
                UserIden::PasswordHash,
                UserIden::IsLocked,
                UserIden::IsAdmin,
                UserIden::ColorScheme,
            ])
            .values([
                id.clone().into(),
                new_user.username.to_lowercase().trim().into(),
                password_hash.expose_secret().to_owned().into(),
                false.into(),
                is_admin.into(),
                "dark".into(),
            ])?
            .build_any_sqlx(self.db.query_builder());

        sqlx::query_with(&sql, values)
            .execute(&mut self.db.pool().acquire().await?)
            .await
            .map_err(|e| {
                if self.db.is_conflict_error(&e) {
                    AppError::DuplicateUserName(new_user.username.to_owned())
                } else {
                    e.into()
                }
            })?;

        Ok(CreateUserResponse { id })
    }
}

This is what I use for migrator.
use sea_query::{MysqlQueryBuilder, PostgresQueryBuilder, SchemaBuilder, SqliteQueryBuilder};

use futures_core::future::BoxFuture;
use sqlx::{
    any::AnyKind,
    error::BoxDynError,
    migrate::{MigrateError, Migration, MigrationSource, Migrator},
    AnyPool,
};

use crate::AppResult;

pub struct MigrationManager {
    pool: AnyPool,
    migrations: Vec<Migration>,
}

impl MigrationManager {
    pub fn new(pool: AnyPool) -> Self {
        Self {
            pool,
            migrations: vec![],
        }
    }

    pub fn pool(&self) -> &AnyPool {
        &self.pool
    }

    pub fn any_kind(&self) -> AnyKind {
        self.pool().any_kind()
    }

    pub fn schema_builder(&self) -> &dyn SchemaBuilder {
        match self.any_kind() {
            AnyKind::Postgres => &PostgresQueryBuilder,
            AnyKind::MySql => &MysqlQueryBuilder,
            AnyKind::Sqlite => &SqliteQueryBuilder,
        }
    }

    pub fn with_migrator(
        mut self,
        migrator: impl Fn(&MigrationManager) -> AppResult<sqlx::migrate::Migration>,
    ) -> AppResult<Self> {
        self.migrations.push(migrator(&self)?);
        Ok(self)
    }

    pub fn with_migration(mut self, migration: sqlx::migrate::Migration) -> Self {
        self.migrations.push(migration);
        self
    }

    pub async fn run_up(&self) -> Result<(), MigrateError> {
        let m = MigrationList(self.migrations.clone());
        let migrator = Migrator::new(m).await?;
        migrator.run(self.pool()).await?;
        Ok(())
    }

    pub async fn run_down(&self, target: i64) -> Result<(), MigrateError> {
        let m = MigrationList(self.migrations.clone());
        let migrator = Migrator::new(m).await?;
        migrator.undo(self.pool(), target).await?;
        Ok(())
    }
}

#[derive(Debug)]
struct MigrationList(Vec<Migration>);

impl MigrationSource<'static> for MigrationList {
    fn resolve(self) -> BoxFuture<'static, std::result::Result<Vec<Migration>, BoxDynError>> {
        Box::pin(async move { Ok(self.0) })
    }
}

pub async fn migrate_up(pool: AnyPool) -> AppResult<()> {
    get_migration_manager(pool)?.run_up().await?;
    Ok(())
}

pub async fn migrate_down(pool: AnyPool, target: i64) -> AppResult<()> {
    get_migration_manager(pool)?.run_down(target).await?;
    Ok(())
}

mod migration_20221018052300_user;
mod migration_20221030105700_storage;

fn get_migration_manager(pool: AnyPool) -> AppResult<MigrationManager> {
    let manager = MigrationManager::new(pool)
        .with_migrator(migration_20221018052300_user::up)?
        .with_migrator(migration_20221018052300_user::down)?;
    Ok(manager)
}

As for ORMs I'm not a fan of it. While it allows us to move fast initially and makes it easy to refactor in the long run we always land of fighting ORMs. The good part about the solution is one can use custom sql if needed that might be specific to your database and take advantage of it.
As for surrealdb it is quite new. Due to popularity of sql I would suggest supporting sqlx first. Once the cli has stable list of features, it then would make it easy to port to surrealdb if needed. For now I'm ok with just todo!() implementation so I can easily replace it on my side.
For background jobs I use my own https://github.com/prabirshrestha/mq. Currently only Surrealdb backend is implemented. One could create own backend using sql or Redis or cloud queues if needed.
I don't expect this to be done soon anytime, but wanted to just share thoughts as I think there is lot of potential for the cli to make it easy. Every time I create a new salvo project I'm doing quite a lot of copy paste so I think it not just me but others could also benefit here. Best of luck at your work!

My thoughts on sql/db/orm is that salvo-cli only supports one but allows us to bring our own. Here is how I would do it. I will give an example on how one could implement sign up in a generic way. (Pasting code from my old project for reference)

Introduce traits allowing easy change of implementations.

#[async_trait]
pub trait UserService: Sync + Send {
    async fn signup(&self, new_user: &CreateUserRequest) -> AppResult<CreateUserResponse>;
}

If I choose bring your own, replace with todo!(). I can use this with surrealdb or any other implantation.

#[async_trait]
impl UserService for MyUserService {
    async fn signup(&self, new_user: &CreateUserRequest) -> AppResult<CreateUserResponse> {
        todo!();
    }
}

As for database I suggest to go with sqlx but use AnyPool and sea-query-binder. This will allow you to write sql once but use it for sqlite, mysql or Postgres.

sqlx = { version = "0.6.1", default-features = false, features = ["any", "sqlite", "mysql", "postgres"] }
sea-query = "0.27.1"
sea-query-binder = { version = "0.2.1", features = ["sqlx-any", "sqlx-postgres", "sqlx-mysql", "sqlx-sqlite"] }

DB using AnyPool
Migration now has to move to rust, but you write once and it works for sqlite, mysql and Postgres.
Queries are also generic that works in sqlite, mysql and postgres.
This is what I use for migrator.
As for ORMs I'm not a fan of it. While it allows us to move fast initially and makes it easy to refactor in the long run we always land of fighting ORMs. The good part about the solution is one can use custom sql if needed that might be specific to your database and take advantage of it.
As for surrealdb it is quite new. Due to popularity of sql I would suggest supporting sqlx first. Once the cli has stable list of features, it then would make it easy to port to surrealdb if needed. For now I'm ok with just todo!() implementation so I can easily replace it on my side.
For background jobs I use my own https://github.com/prabirshrestha/mq. Currently only Surrealdb backend is implemented. One could create own backend using sql or Redis or cloud queues if needed.
I don't expect this to be done soon anytime, but wanted to just share thoughts as I think there is lot of potential for the cli to make it easy. Every time I create a new salvo project I'm doing quite a lot of copy paste so I think it not just me but others could also benefit here. Best of luck at your work!

Thank you for your reply, I will keep learning and writing better tools. Have a great day! :)

[ ] use cargo workspace

[ ] add support for SPA so client side apps can be written.

[ ]  Add support for surrealdb. It can be embedded as well as run in clusters, supports vector   - [   - [ ] embeddings

[ ] use yaml for config, as this allows other folks in the team not familiar with rust or toml.

[x] generate README.md so we know what the next step is. for now it probably doesn't matter as it just cargo run. For
example I had to read the code to understand where the swagger ui is.

PS:After generating the project, readme.md is created . Contains an introduction to the selected orm, data migration, and the initialization process. As well as an introduction to the project directory and files. After running the project, the current swagger-ui page is printed in the console

[ ] add support for background jobs. I think this is very important to enable rich responsive servers.

[ ] add support for cron jobs

[ ] instead of rand_utils.rs considering using specific files such as password.rs.

[ ] Considering using traits for Services. This would allow us to change the implementation via config.

[ ] consider consistent naming for routes such as get_user_page_router (for html), get_user_route (for apis),   - [ ]   - [ ]   - [ ] delete_user_route and so on.

[ ] remove demo.rs

[ ] considering using sub folders for templates.

[ ] Add support for sending emails. Emails usually have html templates too.

[ ] Add support for 2fa auth.

[ ] Add support for App passwords.

[ ] Add support for updating/reseting passwords.

[ ] call it open api instead of swagger.

[ ] add support for login, logout and register in homepage.

[ ] Add generic pagination concept.

[ ] add CSRF

[ ] add localization

[ ] add systemic and watch support so saving .rs files would automatically build

[ ] add support for server errors. might be even show stack traces in debug mode?

[ ] socket.io with https://github.com/Totodore/socketioxide for real time communication

[ ] in memory as well as distributed caching

[ ] generic storage using https://opendal.apache.org/. Allowing to easily swap files from files system to cloud storages.

Another one I would consider adding is watch mode.
This will allow us to do something like this and when it is compiling the http endpoint will be available and wait for the compilation to finish and start the server.
cargo install systemfd
systemfd --no-pid -s http::8080 -- cargo watch -x 'run'

You can see the sample from here.
Recently published a surrealdb-migrator that I have been using internally in one of my project. This should hopefully unblock surrealdb support.

Here are few more:

Avoid adding JS library if possible. Most likely folks using will use a full blown SPA libraries such as React/Vue/Angular and so on, so I wouldn't bother. Another reason to do so if some may want apps to work with JS disabled specially for non authenticated pages. JS also may be no go for those who use Typescript and have large number of engineers contributing.

One option to support errors is preserve the state either in query string or use flash as shown here. This will require full page refresh.
If you really want to include some sort of dynamic UI, probably worth using htmx/unploy/alipne (currently) but without other JS files or scripts. I personally haven't used any of these so can't give any preferences, but would use one that has the least size and has good set of features.

Group templates into folder. Such as as templates/admin/users/list_page.html instead of templates/user_list_page.html.

Implement 500 internal server error page.

Add support for CSS minification/compliation. Might be can use grass which includes support for compiling SASS files so we get benefits for variables and imports that can be merged to a single file.

static CSS: &str = grass::include!("../static/_index.scss");

Use layout pages instead of duplicating code.
Don't default cors to the following. could be security issue.

cors_allow_origin:
    - "https://salvo.rs"

(If it makes it easy for you to create an new issue with checkmarks as the main comment feel free to do so and I can start commenting there instead and you can lock this issue.)

Here are few more:

Avoid adding JS library if possible. Most likely folks using will use a full blown SPA libraries such as React/Vue/Angular and so on, so I wouldn't bother. Another reason to do so if some may want apps to work with JS disabled specially for non authenticated pages. JS also may be no go for those who use Typescript and have large number of engineers contributing.

One option to support errors is preserve the state either in query string or use flash as shown here. This will require full page refresh.
If you really want to include some sort of dynamic UI, probably worth using htmx/unploy/alipne (currently) but without other JS files or scripts. I personally haven't used any of these so can't give any preferences, but would use one that has the least size and has good set of features.

Group templates into folder. Such as as templates/admin/users/list_page.html instead of templates/user_list_page.html.
Implement 500 internal server error page.
Add support for CSS minification/compliation. Might be can use grass which includes support for compiling SASS files so we get benefits for variables and imports that can be merged to a single file.

static CSS: &str = grass::include!("../static/_index.scss");

Use layout pages instead of duplicating code.
Don't default cors to the following. could be security issue.

cors_allow_origin:
    - "https://salvo.rs"

(If it makes it easy for you to create an new issue with checkmarks as the main comment feel free to do so and I can start commenting there instead and you can lock this issue.)

Thanks for the added advice; I'll start a new issue!


[eslint] Run subset of eslint rules on sample code

Hi @willmtemple , I need your help.
If I ask our ESLint to include our samples, by adding "samples" to our eslint scripts, I get this error:
/REDACTED/keyvault-keys/samples/typescript/src/purgeAllKeys.ts
  0:0  error  Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser.
The file does not match your project config: samples/typescript/src/purgeAllKeys.ts.
The file must be included in at least one of the projects provided

I get that we want to make sure we include the files we're using in our output, but I think we do need eslint on our samples too. 🤔 any help is appreciated.
(title edited by @willmtemple)

We generally don't want to run the SDK linter on the samples. eslint-plugin-azure-sdk/azure-sdk-base is specifically for library code, and sample code doesn't need to be subject to its limitations. We could run a different config, or create a subconfig in our plugin's package for samples.

Marking this up for grabs. The work here is to decide how to lint sample code.

[ ] What ruleset to we use for sample code
[ ] Where do we store that configuration
[ ] How do we add samples linting to our existing lint scripts

What ruleset to we use for sample code
Where do we store that configuration

I would expect all the [custom rules we have in the plugin](What ruleset to we use for sample code) to be not applicable for the samples and have only the rules in the plugin's .eslintrc.json file

How do we add samples linting to our existing lint scripts

Can we do this as aprt of the dev-tool samples prep step which is run as part of build:samples which should ideally be run in our CI?


Fix - Incorrect links to documentation files.

The PSReadLine.csproj project file includes various text and markdown documentation files, but these are actually available from the root solution folder. This PR fixes the links to those documentation files.

Did you change the newlines from Windows to Unix? Every line seems to be changed.

I may have done that unexpectedly indeed. Please, let me fix this.


[WIP] Avoidance heartbeat

Receive a heartbeat from the avoidance process. This allows monitoring the state of the individual and required process running on the companion computer.
As there exists no MAV_TYPE for such processes yet, the MAV_TYPE_SUBMARINE, which is not in use for PX4, is misused.

Also you should update the mavlink submodule to bring the new enum values.

@baumanta just one thing: would you mind adding the new uorb message to https://github.com/PX4/Firmware/blob/master/msg/tools/uorb_rtps_message_ids.yaml? I still have to add a script that runs on the build process to check if all the uORB msgs have a respective ID on the RTPS stream, but needs to be done manually. Thanks!

@TSC21 does it matter which rtps id I assign it? Does that nee to match with anything or should I just use the next free number (137)?

@TSC21 does it matter which rtps id I assign it? Does that nee to match with anything or should I just use the next free number (137)?

120 and above are for multi and aliased topics. Please use 107.

@baumanta this looks good now. Do you have an example output from a test you made?

@TSC21 here a link to a screen record where the avoidance process is running.  If it does not recover during a specified time, it aborts.

Looking good!

@MaEtUgR any idea of what may be causing this https://ci.appveyor.com/project/Dronecode/firmware/builds/20582642#L16?

@TSC21 yer, my fault sry, fixed in #10924. This pr got rebased already.

@MaEtUgR Thanks!
@dagar same old story: http://ci.px4.io:8080/blue/organizations/jenkins/PX4_misc%2FFirmware-compile/detail/PR-10841/15/pipeline#step-549-log-843

@TSC21 I'll go through this PR in detail later. At the moment I don't see why this can't be done with a much simpler extension of the existing commander failsafes based on telemetry heartbeats.

@dagar this is a conceptual option in the end. @baumanta took this approach, which in the end I think it'a also a viable one in the sense it also isolates companion related failsafes and status messages in a separate "module".

@baumanta  If the avoidance timeouts during a mission, do you ask commander to switch to auto loiter? In the video I see that the vehicle is in manual and after the timeout it switches to hold but it doesn't seem to be handled in this PR.

@mrivi No not yet. Right now this PR does not interfere with any of the behavior o fthe drone. It only outputs messages to QGC such that the user is warned if something is not right with the avoidance process. But in the future we plan on extending that. Final decision is not yet made on what actions to take, but we might include checking the avoidance process in the preflight tests. Such that you can not switch to mission if the MPC_OBS_AVOID param is true and the process is not running. Also your suggestion with Loiter does make sense and is definitely an option.

@baumanta Could you please rebase? Flash space is fixed for now.

closed in favor of PR #10933


docs directory causes build issues on Windows

It appears that PlaydateKit can't be cloned on a Windows machine because the documentation's information uses symbols that aren't allowed as file paths in Windows:
    error: unable to create file docs/data/documentation/playdatekit/graphics/drawbitmap(_:at:flip:).json: Invalid argument
    error: unable to create file docs/data/documentation/playdatekit/graphics/drawbitmap(_:at:xscale:yscale:).json: Invalid argument
    error: unable to create file docs/data/documentation/playdatekit/graphics/drawellipse(in:linewidth:startangle:endangle:color:).json: Invalid argument
    error: unable to create file docs/data/documentation/playdatekit/graphics/drawline(_:linewidth:color:).json: Invalid argument
    error: unable to create file docs/data/documentation/playdatekit/graphics/drawrect(_:color:).json: Invalid argument
    error: unable to create file docs/data/documentation/playdatekit/graphics/drawtext(_:at:).json: Invalid argument

Using git config --global core.protectNTFS seems to be ignored here as well. I recommend we convert the project's documentation website to use GitHub Actions to deploy the documentation live rather than hosting it in the docs dir.

I tried to get Github Actions working for the docs a few days ago but couldn't manage to get the xcodebuild docbuild command working using the latest version of Xcode and using the right build settings. Might give it another try, but another option is just to move the docs to a gh-pages branch.


Fix rendering of CIImages that have non-zero origin

This pull request fixes the case when using MetalPetal to render CIImages that have non-zero origin. In this case previously part of images would be lost because startTask that was used renders the CIImage to MTITexture from (0, 0) to (0, 0). Because MTITexture has no concept of origin, anything left or down from (0, 0) would lay beyond the texture and be lost.
The fix uses another overload of startTask that copies the content from outputCIImage.extent.origin instead.
Confirmed on both simulator and real devices.
Example using CIGaussianBlur
Before (you can see 2 cut edges and some garbage was copied):

After (perfect):

@eXCoreX This introduces a few new problems:

CIImage with infinite extent does not render currently. See 6bf207e.
This also breaks the core image transform filter. All translations are ignored. Because the image is always rendered at point (0,0).

So I'm going to revert this change and for the CIGaussianBlur problem I think you should either: a. Apply a transform to the blurred image so it stays in the center. or b. Clamp the blurred image to its original extent.
What do you think?

Hello @YuAo, I think the second problem is a non-issue, because as you can see on the screenshot simply translating the image sometimes won't work because it seems to copy the data from garbage or surrounding memory. To make it work properly it needs to handle when it goes beyond the existing texture and set it to transparent or something. Also in #137 you said that it's okay that translation does not work and recommended using MTICompositingFilter for this task.
As for the first issue, I will try to reproduce it and write back, thanks.

@eXCoreX Any progress?


[BUG][WEBJS] -  WEBJS sometimes cannot receive reaction webhook notifications

WEBJS sometimes cannot receive reaction webhook notifications

Version:
2024.9.3


Update Discord link to use invite link instead of channel link

I just realized the Discord channel link currently will lead us to this page if you are on an account that has not already joined the server.

Let's update the link to use an invite link instead. The following link I've generated is set to never expire: https://discord.gg/YyWcyeEJud
Users who are already part of the server will be redirected to the server channel on Discord.

Fixed by commit c9ae8216fc9f7d8fd0c80b829f3f290a181c3280
Note: Might want to have the link generated by main Woodley Park Archers discord account if there is one, so it looks more official. It is currently generated by my personal account.


Backport: Index only the docs for FacetField posting list (#922)

cc: @gsmiller
Previous PR: #922
I've retained the same PR number in the CHANGES entry as that PR contains the original discussions around the issue.

Gradlew tests are failing on the TestBackwardsCompatibility.testSortedIndex test. I binary searched through recent commits. Tests after the 84133e7aecbf7ece459ebd3c3ce4e3266f30d558 commit have started failing. Maybe @madrob has more context?

Yes, Thanks for the quick turnaround.

Thanks @gautamworah96 !


Filter root packages by "available" condition

This is useful if some packages in a repository only work on certain platforms. For example, eio_linux should only be tested on Linux, but some other packages should still be tested on e.g. macos.
This is on top of #71 (until that's merged, see https://github.com/talex5/solver-service/compare/eio...talex5:solver-service:filter-avail?expand=1 for a more sensible diff).

Rebased.


feat: local catalog drop table

I hereby agree to the terms of the GreptimeDB CLA
What's changed and what's your intention?

impl drop table on local catalog (part of #497)
fix a minor bug that default value of BinaryType is Value::String (should be Value::Binary)
change sqlness tests accordingly

Checklist

[ ]  I have written the necessary rustdoc comments.
[ ]  I have added the necessary unit tests and integration tests.

Refer to a related PR or issue link (optional)

@v0y4g3r PTAL


Add support for Python 3.8 and 3.9

Python 3.8 was released in October 2019 and 3.9 in 2020.

Updated to add Python 3.9.

Great stuff mate, thanks

Great stuff mate, thanks


Display URL for the template to admins

In legacy UI, we display the url of the template to
admins. Do the same thing here also
Below is the view for admin

And below is the view for domain admins/users

The listTemplates response does not return URL, but we can still accept the change as if it does we can display it
@blueorangutan package

@rhtyd a Jenkins job has been kicked to build primate packages. I'll keep you posted as I make progress.

Packaging result: :heavy_check_mark:centos :heavy_check_mark:debian :heavy_check_mark:archive.
QA: http://primate-qa.cloudstack.cloud:8080/client/pr/525 (JID-2264)

Confirmed URL not seen is API does not return the key. Can merge as probably some CloudStack forks maybe returning the URL as part of list API response.


self-hosted compiler has specific performance problems

It seems like the self-hosted compiler has some performance problems in specific parts of the compiler.  In particular, the scanner, parser, and resolver are much slower than dart2js command line.
Is this because the Dart VM is really good at optimizing these parts, or is it because dart2js generates slow code?  I don't know, but it might be worth investigating.
This is compiling the HTML fibonacci example from the command line:
Reading input files took 82msec
LibraryLoader took 53msec
Scanner took 150msec
Diet Parser took 83msec
Parser took 189msec
Patching Parser took 16msec
Resolver took 638msec
Closure Simplifier took 31msec
Type checker took 29msec
Type inference took 173msec
ConstantHandler took 0msec
Deferred Loading took 0msec
Enqueue took 140msec
SSA builder took 169msec
SSA optimizer took 194msec
SSA code generator took 169msec
CodeEmitter took 242msec
Total compile-time 2599msec; unaccounted 241msec
This is compiling the same example on try.dartlang.org:
Reading input files took 0msec
LibraryLoader took 37msec
Scanner took 425msec
Diet Parser took 46msec
Parser took 412msec
Patching Parser took 27msec
Resolver took 1063msec
Closure Simplifier took 26msec
Type checker took 16msec
Type inference took 177msec
ConstantHandler took 0msec
Deferred Loading took 0msec
Enqueue took 241msec
SSA builder took 102msec
SSA optimizer took 238msec
SSA code generator took 146msec
CodeEmitter took 170msec
Total compile-time 3520msec; unaccounted 394msec

These numbers are really old. Please reopen if this is still a problem.


Leverage powerpick/psinject for spawn of empire agent

I don't know if you would be willing but adding support to spawn empire agents without powershell.exe would be epic. If you don't want to do it I could take a shot at doing a PR... let me know your thoughts.

That is a good idea! The reason it wasn't included in the initial release was due to issues with running the encoded blob with the bpowerpick function.
To get PowerPick working bidirectionally, I think the DLL Launcher in Empire is the way to go. I hope tackle this in the near future when I rework the script to support the new Empire 2.0 API. If you'd like to tackle it in the meantime, please feel free to submit a PR 👍


[Foundation Tests] Remove test for NSDate and Date hashing equality

NSDate and Date have no distinct contract for hashing to be the same. If one changes it is only required that their equality and hashing match functionality (not hash value)

@swift-ci test and merge


[E2E] Wrong clusterID when context name != cluster name

When running subctl verify against any deployment where context names != cluster names (i.e cluster1/cluster2/cluster3 - like we do in both kind and CI), some tests (in particular Lighthouse with StatefulSets) will fail because the code picks wrong clusterId values.
A temporary workaround would be to rename the contexts define in the kubeconfigs, and ensure they match the same value as clusterId for those clusters.

Verified on 0.8.0-rc1


Error Messages Not Displayed Properly in Flutter Web (Issue Present in Both 3.10.6 and 3.22.2)

Steps to reproduce

Run Code Sample provided in flutter Web and Android
Click Button to trigger Error
Check for error logs

Description :
I am experiencing an issue where error messages are no longer displayed properly in Flutter Web. Initially, the error messages were displayed correctly while working with Flutter version 3.10.6. However, they suddenly stopped displaying without any changes to the code. I upgraded to the latest version 3.22.2, but the issue persists. The error messages still display correctly on Android.
Expected results
Error messages should be displayed correctly in the web version of the app, as they were initially in Flutter version 3.10.6.
Actual results
Error messages are displayed differently in the web version of the app in both Flutter version 3.10.6 and 3.22.2. The issue does not affect the Android version where error messages are displayed correctly.
Code sample
Code sample
Future<void> main() async {
  runApp(MaterialApp(
    initialRoute: "/",
    routes: {
      "/": (context) => const Home(),
    },
  ));
}

class Home extends StatefulWidget {
  const Home({super.key});

  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {

  String? nullableString;

  void _triggerError() {
    // This will cause a "Null check operator used on a null value" error
    String nonNullableString = nullableString!;
    print(nonNullableString);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter Null Check Error Demo'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: _triggerError,
          child: const Text('Trigger Error'),
        ),
      ),
    );
  }
}

Screenshots or Video

Screenshots / Video demonstration
[Upload media here]

Logs
Logs
Android
The following _TypeError was thrown while handling a gesture:
Null check operator used on a null value

When the exception was thrown, this was the stack:
#0      _HomeState._triggerError (package:design_studio/main_billdesk.dart:61:46)
#1      _InkResponseState.handleTap (package:flutter/src/material/ink_well.dart:1171:21)
#2      GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:344:24)
#3      TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:652:11)
#4      BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:309:5)
#5      BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:242:7)
#6      PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:696:9)
#7      PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:98:12)
#8      PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:143:9)
#9      _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:633:13)
#10     PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:141:18)
#11     PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:127:7)
#12     GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:495:19)
#13     GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:475:22)
#14     RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:425:11)
#15     GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:420:7)
#16     GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:383:5)
#17     GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:330:7)
#18     GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:299:9)
#19     _invoke1 (dart:ui/hooks.dart:328:13)
#20     PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:442:7)
#21     _dispatchPointerDataPacket (dart:ui/hooks.dart:262:31)
Handler: "onTap"
Recognizer: TapGestureRecognizer#8cc5e
  debugOwner: GestureDetector
  state: possible
  won arena
  finalPosition: Offset(203.9, 454.6)
  finalLocalPosition: Offset(84.0, 28.7)
  button: 1
  sent tap down

Web
The following TypeErrorImpl was thrown while handling a gesture:
Unexpected null value.

When the exception was thrown, this was the stack:
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 296:3       throw_
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 586:18  nullCheck
packages/design_studio/main_billdesk.dart 61:46                                   [_triggerError]
packages/flutter/src/material/ink_well.dart 1171:21                               handleTap
packages/flutter/src/gestures/recognizer.dart 344:24                              invokeCallback
packages/flutter/src/gestures/tap.dart 652:11                                     handleTapUp
packages/flutter/src/gestures/tap.dart 309:5                                      [_checkUp]
packages/flutter/src/gestures/tap.dart 242:7                                      handlePrimaryPointer
packages/flutter/src/gestures/recognizer.dart 696:9                               handleEvent
packages/flutter/src/gestures/pointer_router.dart 98:7                            [_dispatch]
packages/flutter/src/gestures/pointer_router.dart 143:9                           <fn>
dart-sdk/lib/_internal/js_dev_runtime/private/linked_hash_map.dart 21:7           forEach
packages/flutter/src/gestures/pointer_router.dart 141:17                          [_dispatchEventToRoutes]
packages/flutter/src/gestures/pointer_router.dart 127:7                           route
packages/flutter/src/gestures/binding.dart 495:5                                  handleEvent
packages/flutter/src/gestures/binding.dart 475:14                                 dispatchEvent
packages/flutter/src/rendering/binding.dart 425:11                                dispatchEvent
packages/flutter/src/gestures/binding.dart 420:7                                  [_handlePointerEventImmediately]
packages/flutter/src/gestures/binding.dart 383:5                                  handlePointerEvent
packages/flutter/src/gestures/binding.dart 330:7                                  [_flushPointerEventQueue]
packages/flutter/src/gestures/binding.dart 299:9                                  [_handlePointerDataPacket]
lib/_engine/engine/platform_dispatcher.dart 1419:5                                invoke1
lib/_engine/engine/platform_dispatcher.dart 333:5                                 invokeOnPointerDataPacket
lib/_engine/engine/pointer_binding.dart 398:30                                    [_sendToFramework]
lib/_engine/engine/pointer_binding.dart 224:7                                     onPointerData
lib/_engine/engine/pointer_binding.dart 1001:20                                   <fn>
lib/_engine/engine/pointer_binding.dart 930:7                                     <fn>
lib/_engine/engine/pointer_binding.dart 531:9                                     loggedHandler
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 426:37  _checkAndCall
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 431:39  dcall
Handler: "onTap"
Recognizer: TapGestureRecognizer#d525f
  debugOwner: GestureDetector
  state: possible
  won arena
  finalPosition: Offset(930.0, 504.0)
  finalLocalPosition: Offset(33.3, 19.5)
  button: 1
  sent tap down

Flutter Doctor output
Doctor output
3.10.6
[√] Flutter (Channel stable, 3.10.6, on Microsoft Windows [Version 10.0.22621.3593], locale en-IN)
    • Flutter version 3.10.6 on channel stable at C:\src\flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision f468f3366c (11 months ago), 2023-07-12 15:19:05 -0700
    • Engine revision cdbeda788a
    • Dart version 3.0.6
    • DevTools version 2.23.1

[√] Windows Version (Installed version of Windows is version 10 or higher)

[√] Android toolchain - develop for Android devices (Android SDK version 33.0.1)
    • Android SDK at C:\Users\Admin\AppData\Local\Android\sdk
    • Platform android-34, build-tools 33.0.1
    • Java binary at: C:\Program Files\Android\Android Studio\jbr\bin\java
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-b2043.56-9586694)
    • All Android licenses accepted.

[√] Chrome - develop for the web
    • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe

[√] Visual Studio - develop for Windows (Visual Studio Community 2022 17.9.1)
    • Visual Studio at C:\Program Files\Microsoft Visual Studio\2022\Community
    • Visual Studio Community 2022 version 17.9.34616.47
    • Windows 10 SDK version 10.0.22621.0

[√] Android Studio (version 2022.2)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin can be installed from:
[√] Connected device (4 available)
    • CPH2467 (mobile)  • 1a715d74 • android-arm64  • Android 14 (API 34)
    • Windows (desktop) • windows  • windows-x64    • Microsoft Windows [Version 10.0.22621.3593]
    • Chrome (web)      • chrome   • web-javascript • Google Chrome 126.0.6478.61
    • Edge (web)        • edge     • web-javascript • Microsoft Edge 126.0.2592.56

[√] Network resources
    • All expected network resources are available.

• No issues found!

3.22.2
[√] Flutter (Channel stable, 3.22.2, on Microsoft Windows [Version 10.0.22621.3593], locale en-IN)
    • Flutter version 3.22.2 on channel stable at C:\Users\Admin\fvm\versions\3.22.2
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 761747bfc5 (12 days ago), 2024-06-05 22:15:13 +0200
    • Engine revision edd8546116
    • Dart version 3.4.3
    • DevTools version 2.34.3

[√] Windows Version (Installed version of Windows is version 10 or higher)

[√] Android toolchain - develop for Android devices (Android SDK version 33.0.1)
    • Android SDK at C:\Users\Admin\AppData\Local\Android\sdk
    • Platform android-34, build-tools 33.0.1
    • Java binary at: C:\Program Files\Android\Android Studio\jbr\bin\java
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-b2043.56-9586694)
    • All Android licenses accepted.

[√] Chrome - develop for the web
    • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe

[√] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.9.1)
    • Visual Studio at C:\Program Files\Microsoft Visual Studio\2022\Community
    • Visual Studio Community 2022 version 17.9.34616.47
    • Windows 10 SDK version 10.0.22621.0

[√] Android Studio (version 2022.2)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-b2043.56-9586694)

[√] VS Code (version 1.89.1)
    • VS Code at C:\Users\Admin\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension version 3.90.0

[√] Connected device (4 available)
    • CPH2467 (mobile)  • 1a715d74 • android-arm64  • Android 14 (API 34)
    • Windows (desktop) • windows  • windows-x64    • Microsoft Windows [Version 10.0.22621.3593]
    • Chrome (web)      • chrome   • web-javascript • Google Chrome 126.0.6478.61
    • Edge (web)        • edge     • web-javascript • Microsoft Edge 126.0.2592.56

[√] Network resources
    • All expected network resources are available.

• No issues found!

@KaushikGupta007
What's the expected console log or behavior are you looking for in web ? The way currently web shows the exception seems to be in sync with android, for example:

[_triggerError]
packages/flutter/src/material/ink_well.dart 1171:21                               handleTap
packages/flutter/src/gestures/recognizer.dart 344:24                              invokeCallback
packages/flutter/src/gestures/tap.dart 652:11                                     handleTapUp
packages/flutter/src/gestures/tap.dart 309:5                                      [_checkUp]
packages/flutter/src/gestures/tap.dart 242:7                                      handlePrimaryPointer
packages/flutter/src/gestures/recognizer.dart 696:9                               handleEvent
packages/flutter/src/gestures/pointer_router.dart 98:7                            [_dispatch]
packages/flutter/src/gestures/pointer_router.dart 143:9                           <fn>
dart-sdk/lib/_internal/js_dev_runtime/private/linked_hash_map.dart 21:7           forEach
packages/flutter/src/gestures/pointer_router.dart 141:17                          [_dispatchEventToRoutes]

The class names are same as thrown in android if you look closely.

I recently updated to 3.22.2, since then i stopped getting details of any error. Just shows 'Error'.

Facing similar issue

I recently updated to 3.22.2, since then i stopped getting details of any error. Just shows 'Error'.

I get below in latest stable version:
══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
The following TypeErrorImpl was thrown while handling a gesture:
Unexpected null value.

When the exception was thrown, this was the stack:
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 296:3       throw_
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 586:18  nullCheck

I recently updated to 3.22.2, since then i stopped getting details of any error. Just shows 'Error'.

Yes, I got the same . Sadly, that's what we get for upgrading. As a Flutter rule of thumb, there is a new instability for every new stable released.

I recently updated to 3.22.2, since then i stopped getting details of any error. Just shows 'Error'.

Yes, I got the same . Sadly, that's what we get for upgrading. As a Flutter rule of thumb, there is a new instability for every new stable released.
Tried also 3.16.9 and 3.19.3.

It still shows Error in console while running on web but displays proper messages while running on Android

I get below running on latest stable (3.22.3) and on master:
══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
The following TypeErrorImpl was thrown while handling a gesture:
Unexpected null value.

When the exception was thrown, this was the stack:

Not the only term Error, so I guess the exception we are seeing now as above is expected ?

The errors are different because of the way Flutter handles exceptions and stack traces across different platforms (Android and Web). The underlying issue, however, is the same: a null check operator (!) is being used on a null value.

Thanks for the update. Based on the report, behavior, I'll keep the issue open for team's attention / tracking.

What is the current workaround ?

What I do is run the app on Android or iOS to get proper error message. But it would be good if this issue is fixed.

What I do is run the app on Android or iOS to get proper error message. But it would be good if this issue is fixed.

In my situation, I don't know what to do: On android, this line await launchUrl(Uri.parse(link.url)); doesn't throw, but it does on web, and I don't know why.

What I do is run the app on Android or iOS to get proper error message. But it would be good if this issue is fixed.

In my situation, I don't know what to do: On android, this line await launchUrl(Uri.parse(link.url)); doesn't throw, but it does on web, and I don't know why. Should I use an old flutter version ? Which one ?

I don't this this will solve with version change because I have tried in older versions.

I found a little workaround. If I wrap my exception in a try/catch to print the exception, I can see the exception.
This code print a generic error :
throw Exception('test');

This one, not :
try{
  throw Exception('test');
} catch(ex){
  print(ex);
}

@suranjum said we can see this :
Error
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 296:3  throw_
packages/XXX.dart XXX:XXX                                                    <fn>
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 45:50           <fn>

I want to add, often, I see this, just before or just after :
ChromeProxyService: Failed to evaluate expression '': InvalidInputError: .

Maybe someone can find a better workaround, with a hook to the exception handler ??

I found a better workaround, to print the string representation, but not the true stack trace unfortunately.
Future<void> main() async {
  await runZonedGuarded<Future<void>>(
    main2,
    (Object error, StackTrace stackTrace) {
      if(kDebugMode){
        print(error);
        print(stackTrace);
      }
    },
  );
}

The initial main function, has been renamed to main2.

I'm a little confused. The original report and repro does not seem to contain the issue. There are bits and piece in the comments indicating that there is an issue in some situations. Could someone please provide a full repro case that reproduces the issue, showing just Error and nothing else?

@yjbanov
In a button onclick callback :
throw Exception('test');