Merge branch 'dev' into screenshotone
commit
0b53f8dc4e
|
@ -0,0 +1,18 @@
|
|||
version = 1
|
||||
|
||||
test_patterns = ["**/*.spec.ts","**/*_test.py","**/*_tests.py","**/test_*.py"]
|
||||
|
||||
exclude_patterns = ["classic/**"]
|
||||
|
||||
[[analyzers]]
|
||||
name = "javascript"
|
||||
|
||||
[analyzers.meta]
|
||||
plugins = ["react"]
|
||||
environment = ["nodejs"]
|
||||
|
||||
[[analyzers]]
|
||||
name = "python"
|
||||
|
||||
[analyzers.meta]
|
||||
runtime_version = "3.x.x"
|
|
@ -37,6 +37,25 @@ jobs:
|
|||
run: |
|
||||
yarn lint
|
||||
|
||||
type-check:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "21"
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
yarn install --frozen-lockfile
|
||||
|
||||
- name: Run tsc check
|
||||
run: |
|
||||
yarn type-check
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "aiohappyeyeballs"
|
||||
|
@ -6,7 +6,6 @@ version = "2.4.0"
|
|||
description = "Happy Eyeballs for asyncio"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "aiohappyeyeballs-2.4.0-py3-none-any.whl", hash = "sha256:7ce92076e249169a13c2f49320d1967425eaf1f407522d707d59cac7628d62bd"},
|
||||
{file = "aiohappyeyeballs-2.4.0.tar.gz", hash = "sha256:55a1714f084e63d49639800f95716da97a1f173d46a16dfcfda0016abb93b6b2"},
|
||||
|
@ -18,7 +17,6 @@ version = "3.10.5"
|
|||
description = "Async http client/server framework (asyncio)"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "aiohttp-3.10.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:18a01eba2574fb9edd5f6e5fb25f66e6ce061da5dab5db75e13fe1558142e0a3"},
|
||||
{file = "aiohttp-3.10.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:94fac7c6e77ccb1ca91e9eb4cb0ac0270b9fb9b289738654120ba8cebb1189c6"},
|
||||
|
@ -131,7 +129,6 @@ version = "1.3.1"
|
|||
description = "aiosignal: a list of registered asynchronous callbacks"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"},
|
||||
{file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"},
|
||||
|
@ -146,7 +143,6 @@ version = "0.7.0"
|
|||
description = "Reusable constraint types to use with typing.Annotated"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"},
|
||||
{file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"},
|
||||
|
@ -158,7 +154,6 @@ version = "4.4.0"
|
|||
description = "High level compatibility layer for multiple asynchronous event loop implementations"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"},
|
||||
{file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"},
|
||||
|
@ -181,12 +176,10 @@ version = "4.0.3"
|
|||
description = "Timeout context manager for asyncio programs"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main", "dev"]
|
||||
files = [
|
||||
{file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"},
|
||||
{file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"},
|
||||
]
|
||||
markers = {main = "python_version < \"3.11\"", dev = "python_full_version < \"3.11.3\""}
|
||||
|
||||
[[package]]
|
||||
name = "attrs"
|
||||
|
@ -194,7 +187,6 @@ version = "24.2.0"
|
|||
description = "Classes Without Boilerplate"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"},
|
||||
{file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"},
|
||||
|
@ -214,7 +206,6 @@ version = "5.5.0"
|
|||
description = "Extensible memoizing collections and decorators"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "cachetools-5.5.0-py3-none-any.whl", hash = "sha256:02134e8439cdc2ffb62023ce1debca2944c3f289d66bb17ead3ab3dede74b292"},
|
||||
{file = "cachetools-5.5.0.tar.gz", hash = "sha256:2cc24fb4cbe39633fb7badd9db9ca6295d766d9c2995f245725a46715d050f2a"},
|
||||
|
@ -226,7 +217,6 @@ version = "2024.8.30"
|
|||
description = "Python package for providing Mozilla's CA Bundle."
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"},
|
||||
{file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"},
|
||||
|
@ -238,7 +228,6 @@ version = "3.3.2"
|
|||
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
|
||||
optional = false
|
||||
python-versions = ">=3.7.0"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"},
|
||||
|
@ -338,7 +327,6 @@ version = "0.4.6"
|
|||
description = "Cross-platform colored terminal text."
|
||||
optional = false
|
||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
|
||||
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
||||
|
@ -350,7 +338,6 @@ version = "1.2.14"
|
|||
description = "Python @deprecated decorator to deprecate old python classes, functions or methods."
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"},
|
||||
{file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"},
|
||||
|
@ -368,7 +355,6 @@ version = "2.1.0"
|
|||
description = "A library to handle automated deprecations"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "deprecation-2.1.0-py2.py3-none-any.whl", hash = "sha256:a10811591210e1fb0e768a8c25517cabeabcba6f0bf96564f8ff45189f90b14a"},
|
||||
{file = "deprecation-2.1.0.tar.gz", hash = "sha256:72b3bde64e5d778694b0cf68178aed03d15e15477116add3fb773e581f9518ff"},
|
||||
|
@ -383,8 +369,6 @@ version = "1.2.2"
|
|||
description = "Backport of PEP 654 (exception groups)"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main"]
|
||||
markers = "python_version < \"3.11\""
|
||||
files = [
|
||||
{file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"},
|
||||
{file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"},
|
||||
|
@ -399,7 +383,6 @@ version = "1.2.2"
|
|||
description = "Dictionary with auto-expiring values for caching purposes"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "expiringdict-1.2.2-py3-none-any.whl", hash = "sha256:09a5d20bc361163e6432a874edd3179676e935eb81b925eccef48d409a8a45e8"},
|
||||
{file = "expiringdict-1.2.2.tar.gz", hash = "sha256:300fb92a7e98f15b05cf9a856c1415b3bc4f2e132be07daa326da6414c23ee09"},
|
||||
|
@ -414,7 +397,6 @@ version = "1.4.1"
|
|||
description = "A list-like structure which implements collections.abc.MutableSequence"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"},
|
||||
{file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"},
|
||||
|
@ -501,7 +483,6 @@ version = "2.19.2"
|
|||
description = "Google API client core library"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "google_api_core-2.19.2-py3-none-any.whl", hash = "sha256:53ec0258f2837dd53bbd3d3df50f5359281b3cc13f800c941dd15a9b5a415af4"},
|
||||
{file = "google_api_core-2.19.2.tar.gz", hash = "sha256:ca07de7e8aa1c98a8bfca9321890ad2340ef7f2eb136e558cee68f24b94b0a8f"},
|
||||
|
@ -533,7 +514,6 @@ version = "2.34.0"
|
|||
description = "Google Authentication Library"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "google_auth-2.34.0-py2.py3-none-any.whl", hash = "sha256:72fd4733b80b6d777dcde515628a9eb4a577339437012874ea286bca7261ee65"},
|
||||
{file = "google_auth-2.34.0.tar.gz", hash = "sha256:8eb87396435c19b20d32abd2f984e31c191a15284af72eb922f10e5bde9c04cc"},
|
||||
|
@ -557,7 +537,6 @@ version = "1.4.5"
|
|||
description = "Google Cloud Appengine Logging API client library"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "google_cloud_appengine_logging-1.4.5-py2.py3-none-any.whl", hash = "sha256:344e0244404049b42164e4d6dc718ca2c81b393d066956e7cb85fd9407ed9c48"},
|
||||
{file = "google_cloud_appengine_logging-1.4.5.tar.gz", hash = "sha256:de7d766e5d67b19fc5833974b505b32d2a5bbdfb283fd941e320e7cfdae4cb83"},
|
||||
|
@ -575,7 +554,6 @@ version = "0.3.0"
|
|||
description = "Google Cloud Audit Protos"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "google_cloud_audit_log-0.3.0-py2.py3-none-any.whl", hash = "sha256:8340793120a1d5aa143605def8704ecdcead15106f754ef1381ae3bab533722f"},
|
||||
{file = "google_cloud_audit_log-0.3.0.tar.gz", hash = "sha256:901428b257020d8c1d1133e0fa004164a555e5a395c7ca3cdbb8486513df3a65"},
|
||||
|
@ -591,7 +569,6 @@ version = "2.4.1"
|
|||
description = "Google Cloud API client core library"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "google-cloud-core-2.4.1.tar.gz", hash = "sha256:9b7749272a812bde58fff28868d0c5e2f585b82f37e09a1f6ed2d4d10f134073"},
|
||||
{file = "google_cloud_core-2.4.1-py2.py3-none-any.whl", hash = "sha256:a9e6a4422b9ac5c29f79a0ede9485473338e2ce78d91f2370c01e730eab22e61"},
|
||||
|
@ -610,7 +587,6 @@ version = "3.11.3"
|
|||
description = "Stackdriver Logging API client library"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "google_cloud_logging-3.11.3-py2.py3-none-any.whl", hash = "sha256:b8ec23f2998f76a58f8492db26a0f4151dd500425c3f08448586b85972f3c494"},
|
||||
{file = "google_cloud_logging-3.11.3.tar.gz", hash = "sha256:0a73cd94118875387d4535371d9e9426861edef8e44fba1261e86782d5b8d54f"},
|
||||
|
@ -636,7 +612,6 @@ version = "1.65.0"
|
|||
description = "Common protobufs used in Google APIs"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "googleapis_common_protos-1.65.0-py2.py3-none-any.whl", hash = "sha256:2972e6c496f435b92590fd54045060867f3fe9be2c82ab148fc8885035479a63"},
|
||||
{file = "googleapis_common_protos-1.65.0.tar.gz", hash = "sha256:334a29d07cddc3aa01dee4988f9afd9b2916ee2ff49d6b757155dc0d197852c0"},
|
||||
|
@ -655,7 +630,6 @@ version = "2.11.1"
|
|||
description = "Python Client Library for Supabase Auth"
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.9"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "gotrue-2.11.1-py3-none-any.whl", hash = "sha256:1b2d915bdc65fd0ad608532759ce9c72fa2e910145c1e6901f2188519e7bcd2d"},
|
||||
{file = "gotrue-2.11.1.tar.gz", hash = "sha256:5594ceee60bd873e5f4fdd028b08dece3906f6013b6ed08e7786b71c0092fed0"},
|
||||
|
@ -671,7 +645,6 @@ version = "0.13.1"
|
|||
description = "IAM API client library"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "grpc-google-iam-v1-0.13.1.tar.gz", hash = "sha256:3ff4b2fd9d990965e410965253c0da6f66205d5a8291c4c31c6ebecca18a9001"},
|
||||
{file = "grpc_google_iam_v1-0.13.1-py2.py3-none-any.whl", hash = "sha256:c3e86151a981811f30d5e7330f271cee53e73bb87755e88cc3b6f0c7b5fe374e"},
|
||||
|
@ -688,7 +661,6 @@ version = "1.66.1"
|
|||
description = "HTTP/2-based RPC framework"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "grpcio-1.66.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:4877ba180591acdf127afe21ec1c7ff8a5ecf0fe2600f0d3c50e8c4a1cbc6492"},
|
||||
{file = "grpcio-1.66.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:3750c5a00bd644c75f4507f77a804d0189d97a107eb1481945a0cf3af3e7a5ac"},
|
||||
|
@ -747,7 +719,6 @@ version = "1.66.1"
|
|||
description = "Status proto mapping for gRPC"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "grpcio_status-1.66.1-py3-none-any.whl", hash = "sha256:cf9ed0b4a83adbe9297211c95cb5488b0cd065707e812145b842c85c4782ff02"},
|
||||
{file = "grpcio_status-1.66.1.tar.gz", hash = "sha256:b3f7d34ccc46d83fea5261eea3786174459f763c31f6e34f1d24eba6d515d024"},
|
||||
|
@ -764,7 +735,6 @@ version = "0.14.0"
|
|||
description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
|
||||
{file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
|
||||
|
@ -776,7 +746,6 @@ version = "4.1.0"
|
|||
description = "HTTP/2 State-Machine based protocol implementation"
|
||||
optional = false
|
||||
python-versions = ">=3.6.1"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "h2-4.1.0-py3-none-any.whl", hash = "sha256:03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d"},
|
||||
{file = "h2-4.1.0.tar.gz", hash = "sha256:a83aca08fbe7aacb79fec788c9c0bac936343560ed9ec18b82a13a12c28d2abb"},
|
||||
|
@ -792,7 +761,6 @@ version = "4.0.0"
|
|||
description = "Pure-Python HPACK header compression"
|
||||
optional = false
|
||||
python-versions = ">=3.6.1"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "hpack-4.0.0-py3-none-any.whl", hash = "sha256:84a076fad3dc9a9f8063ccb8041ef100867b1878b25ef0ee63847a5d53818a6c"},
|
||||
{file = "hpack-4.0.0.tar.gz", hash = "sha256:fc41de0c63e687ebffde81187a948221294896f6bdc0ae2312708df339430095"},
|
||||
|
@ -804,7 +772,6 @@ version = "1.0.5"
|
|||
description = "A minimal low-level HTTP client."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"},
|
||||
{file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"},
|
||||
|
@ -826,7 +793,6 @@ version = "0.27.2"
|
|||
description = "The next generation HTTP client."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "httpx-0.27.2-py3-none-any.whl", hash = "sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0"},
|
||||
{file = "httpx-0.27.2.tar.gz", hash = "sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2"},
|
||||
|
@ -853,7 +819,6 @@ version = "6.0.1"
|
|||
description = "HTTP/2 framing layer for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.6.1"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "hyperframe-6.0.1-py3-none-any.whl", hash = "sha256:0ec6bafd80d8ad2195c4f03aacba3a8265e57bc4cff261e802bf39970ed02a15"},
|
||||
{file = "hyperframe-6.0.1.tar.gz", hash = "sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914"},
|
||||
|
@ -865,7 +830,6 @@ version = "3.8"
|
|||
description = "Internationalized Domain Names in Applications (IDNA)"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "idna-3.8-py3-none-any.whl", hash = "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac"},
|
||||
{file = "idna-3.8.tar.gz", hash = "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603"},
|
||||
|
@ -877,7 +841,6 @@ version = "8.4.0"
|
|||
description = "Read metadata from Python packages"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "importlib_metadata-8.4.0-py3-none-any.whl", hash = "sha256:66f342cc6ac9818fc6ff340576acd24d65ba0b3efabb2b4ac08b598965a4a2f1"},
|
||||
{file = "importlib_metadata-8.4.0.tar.gz", hash = "sha256:9a547d3bc3608b025f93d403fdd1aae741c24fbb8314df4b155675742ce303c5"},
|
||||
|
@ -897,7 +860,6 @@ version = "2.0.0"
|
|||
description = "brain-dead simple config-ini parsing"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
|
||||
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
|
||||
|
@ -909,7 +871,6 @@ version = "6.1.0"
|
|||
description = "multidict implementation"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "multidict-6.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60"},
|
||||
{file = "multidict-6.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1"},
|
||||
|
@ -1014,7 +975,6 @@ version = "1.27.0"
|
|||
description = "OpenTelemetry Python API"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "opentelemetry_api-1.27.0-py3-none-any.whl", hash = "sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7"},
|
||||
{file = "opentelemetry_api-1.27.0.tar.gz", hash = "sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342"},
|
||||
|
@ -1030,7 +990,6 @@ version = "24.1"
|
|||
description = "Core utilities for Python packages"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"},
|
||||
{file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"},
|
||||
|
@ -1042,7 +1001,6 @@ version = "1.5.0"
|
|||
description = "plugin and hook calling mechanisms for python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"},
|
||||
{file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"},
|
||||
|
@ -1058,7 +1016,6 @@ version = "0.19.1"
|
|||
description = "PostgREST client for Python. This library provides an ORM interface to PostgREST."
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.9"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "postgrest-0.19.1-py3-none-any.whl", hash = "sha256:a8e7be4e1abc69fd8eee5a49d7dc3a76dfbffbd778beed0b2bd7accb3f4f3a2a"},
|
||||
{file = "postgrest-0.19.1.tar.gz", hash = "sha256:d8fa88953cced4f45efa0f412056c364f64ece8a35b5b35f458a7e58c133fbca"},
|
||||
|
@ -1076,7 +1033,6 @@ version = "1.24.0"
|
|||
description = "Beautiful, Pythonic protocol buffers."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "proto-plus-1.24.0.tar.gz", hash = "sha256:30b72a5ecafe4406b0d339db35b56c4059064e69227b8c3bda7462397f966445"},
|
||||
{file = "proto_plus-1.24.0-py3-none-any.whl", hash = "sha256:402576830425e5f6ce4c2a6702400ac79897dab0b4343821aa5188b0fab81a12"},
|
||||
|
@ -1094,7 +1050,6 @@ version = "5.28.0"
|
|||
description = ""
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "protobuf-5.28.0-cp310-abi3-win32.whl", hash = "sha256:66c3edeedb774a3508ae70d87b3a19786445fe9a068dd3585e0cefa8a77b83d0"},
|
||||
{file = "protobuf-5.28.0-cp310-abi3-win_amd64.whl", hash = "sha256:6d7cc9e60f976cf3e873acb9a40fed04afb5d224608ed5c1a105db4a3f09c5b6"},
|
||||
|
@ -1115,7 +1070,6 @@ version = "0.6.1"
|
|||
description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629"},
|
||||
{file = "pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034"},
|
||||
|
@ -1127,7 +1081,6 @@ version = "0.4.1"
|
|||
description = "A collection of ASN.1-based protocols modules"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "pyasn1_modules-0.4.1-py3-none-any.whl", hash = "sha256:49bfa96b45a292b711e986f222502c1c9a5e1f4e568fc30e2574a6c7d07838fd"},
|
||||
{file = "pyasn1_modules-0.4.1.tar.gz", hash = "sha256:c28e2dbf9c06ad61c71a075c7e0f9fd0f1b0bb2d2ad4377f240d33ac2ab60a7c"},
|
||||
|
@ -1142,7 +1095,6 @@ version = "2.10.5"
|
|||
description = "Data validation using Python type hints"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "pydantic-2.10.5-py3-none-any.whl", hash = "sha256:4dd4e322dbe55472cb7ca7e73f4b63574eecccf2835ffa2af9021ce113c83c53"},
|
||||
{file = "pydantic-2.10.5.tar.gz", hash = "sha256:278b38dbbaec562011d659ee05f63346951b3a248a6f3642e1bc68894ea2b4ff"},
|
||||
|
@ -1163,7 +1115,6 @@ version = "2.27.2"
|
|||
description = "Core functionality for Pydantic validation and serialization"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"},
|
||||
{file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"},
|
||||
|
@ -1276,7 +1227,6 @@ version = "2.7.1"
|
|||
description = "Settings management using Pydantic"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "pydantic_settings-2.7.1-py3-none-any.whl", hash = "sha256:590be9e6e24d06db33a4262829edef682500ef008565a969c73d39d5f8bfb3fd"},
|
||||
{file = "pydantic_settings-2.7.1.tar.gz", hash = "sha256:10c9caad35e64bfb3c2fbf70a078c0e25cc92499782e5200747f942a065dec93"},
|
||||
|
@ -1297,7 +1247,6 @@ version = "2.10.1"
|
|||
description = "JSON Web Token implementation in Python"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb"},
|
||||
{file = "pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953"},
|
||||
|
@ -1315,7 +1264,6 @@ version = "8.3.3"
|
|||
description = "pytest: simple powerful testing with Python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"},
|
||||
{file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"},
|
||||
|
@ -1338,7 +1286,6 @@ version = "0.25.2"
|
|||
description = "Pytest support for asyncio"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "pytest_asyncio-0.25.2-py3-none-any.whl", hash = "sha256:0d0bb693f7b99da304a0634afc0a4b19e49d5e0de2d670f38dc4bfa5727c5075"},
|
||||
{file = "pytest_asyncio-0.25.2.tar.gz", hash = "sha256:3f8ef9a98f45948ea91a0ed3dc4268b5326c0e7bce73892acc654df4262ad45f"},
|
||||
|
@ -1357,7 +1304,6 @@ version = "3.14.0"
|
|||
description = "Thin-wrapper around the mock package for easier use with pytest"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0"},
|
||||
{file = "pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f"},
|
||||
|
@ -1375,7 +1321,6 @@ version = "2.9.0.post0"
|
|||
description = "Extensions to the standard Python datetime module"
|
||||
optional = false
|
||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"},
|
||||
{file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"},
|
||||
|
@ -1390,7 +1335,6 @@ version = "1.0.1"
|
|||
description = "Read key-value pairs from a .env file and set them as environment variables"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"},
|
||||
{file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"},
|
||||
|
@ -1405,7 +1349,6 @@ version = "2.0.2"
|
|||
description = ""
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.9"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "realtime-2.0.2-py3-none-any.whl", hash = "sha256:2634c915bc38807f2013f21e8bcc4d2f79870dfd81460ddb9393883d0489928a"},
|
||||
{file = "realtime-2.0.2.tar.gz", hash = "sha256:519da9325b3b8102139d51785013d592f6b2403d81fa21d838a0b0234723ed7d"},
|
||||
|
@ -1423,7 +1366,6 @@ version = "5.2.1"
|
|||
description = "Python client for Redis database and key-value store"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "redis-5.2.1-py3-none-any.whl", hash = "sha256:ee7e1056b9aea0f04c6c2ed59452947f34c4940ee025f5dd83e6a6418b6989e4"},
|
||||
{file = "redis-5.2.1.tar.gz", hash = "sha256:16f2e22dff21d5125e8481515e386711a34cbec50f0e44413dd7d9c060a54e0f"},
|
||||
|
@ -1442,7 +1384,6 @@ version = "2.32.3"
|
|||
description = "Python HTTP for Humans."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
|
||||
{file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
|
||||
|
@ -1464,7 +1405,6 @@ version = "4.9"
|
|||
description = "Pure-Python RSA implementation"
|
||||
optional = false
|
||||
python-versions = ">=3.6,<4"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7"},
|
||||
{file = "rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21"},
|
||||
|
@ -1475,30 +1415,29 @@ pyasn1 = ">=0.1.3"
|
|||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.9.2"
|
||||
version = "0.9.3"
|
||||
description = "An extremely fast Python linter and code formatter, written in Rust."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "ruff-0.9.2-py3-none-linux_armv6l.whl", hash = "sha256:80605a039ba1454d002b32139e4970becf84b5fee3a3c3bf1c2af6f61a784347"},
|
||||
{file = "ruff-0.9.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b9aab82bb20afd5f596527045c01e6ae25a718ff1784cb92947bff1f83068b00"},
|
||||
{file = "ruff-0.9.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fbd337bac1cfa96be615f6efcd4bc4d077edbc127ef30e2b8ba2a27e18c054d4"},
|
||||
{file = "ruff-0.9.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82b35259b0cbf8daa22a498018e300b9bb0174c2bbb7bcba593935158a78054d"},
|
||||
{file = "ruff-0.9.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b6a9701d1e371bf41dca22015c3f89769da7576884d2add7317ec1ec8cb9c3c"},
|
||||
{file = "ruff-0.9.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9cc53e68b3c5ae41e8faf83a3b89f4a5d7b2cb666dff4b366bb86ed2a85b481f"},
|
||||
{file = "ruff-0.9.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:8efd9da7a1ee314b910da155ca7e8953094a7c10d0c0a39bfde3fcfd2a015684"},
|
||||
{file = "ruff-0.9.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3292c5a22ea9a5f9a185e2d131dc7f98f8534a32fb6d2ee7b9944569239c648d"},
|
||||
{file = "ruff-0.9.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a605fdcf6e8b2d39f9436d343d1f0ff70c365a1e681546de0104bef81ce88df"},
|
||||
{file = "ruff-0.9.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c547f7f256aa366834829a08375c297fa63386cbe5f1459efaf174086b564247"},
|
||||
{file = "ruff-0.9.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d18bba3d3353ed916e882521bc3e0af403949dbada344c20c16ea78f47af965e"},
|
||||
{file = "ruff-0.9.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b338edc4610142355ccf6b87bd356729b62bf1bc152a2fad5b0c7dc04af77bfe"},
|
||||
{file = "ruff-0.9.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:492a5e44ad9b22a0ea98cf72e40305cbdaf27fac0d927f8bc9e1df316dcc96eb"},
|
||||
{file = "ruff-0.9.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:af1e9e9fe7b1f767264d26b1075ac4ad831c7db976911fa362d09b2d0356426a"},
|
||||
{file = "ruff-0.9.2-py3-none-win32.whl", hash = "sha256:71cbe22e178c5da20e1514e1e01029c73dc09288a8028a5d3446e6bba87a5145"},
|
||||
{file = "ruff-0.9.2-py3-none-win_amd64.whl", hash = "sha256:c5e1d6abc798419cf46eed03f54f2e0c3adb1ad4b801119dedf23fcaf69b55b5"},
|
||||
{file = "ruff-0.9.2-py3-none-win_arm64.whl", hash = "sha256:a1b63fa24149918f8b37cef2ee6fff81f24f0d74b6f0bdc37bc3e1f2143e41c6"},
|
||||
{file = "ruff-0.9.2.tar.gz", hash = "sha256:b5eceb334d55fae5f316f783437392642ae18e16dcf4f1858d55d3c2a0f8f5d0"},
|
||||
{file = "ruff-0.9.3-py3-none-linux_armv6l.whl", hash = "sha256:7f39b879064c7d9670197d91124a75d118d00b0990586549949aae80cdc16624"},
|
||||
{file = "ruff-0.9.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:a187171e7c09efa4b4cc30ee5d0d55a8d6c5311b3e1b74ac5cb96cc89bafc43c"},
|
||||
{file = "ruff-0.9.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c59ab92f8e92d6725b7ded9d4a31be3ef42688a115c6d3da9457a5bda140e2b4"},
|
||||
{file = "ruff-0.9.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2dc153c25e715be41bb228bc651c1e9b1a88d5c6e5ed0194fa0dfea02b026439"},
|
||||
{file = "ruff-0.9.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:646909a1e25e0dc28fbc529eab8eb7bb583079628e8cbe738192853dbbe43af5"},
|
||||
{file = "ruff-0.9.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a5a46e09355695fbdbb30ed9889d6cf1c61b77b700a9fafc21b41f097bfbba4"},
|
||||
{file = "ruff-0.9.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:c4bb09d2bbb394e3730d0918c00276e79b2de70ec2a5231cd4ebb51a57df9ba1"},
|
||||
{file = "ruff-0.9.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:96a87ec31dc1044d8c2da2ebbed1c456d9b561e7d087734336518181b26b3aa5"},
|
||||
{file = "ruff-0.9.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bb7554aca6f842645022fe2d301c264e6925baa708b392867b7a62645304df4"},
|
||||
{file = "ruff-0.9.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cabc332b7075a914ecea912cd1f3d4370489c8018f2c945a30bcc934e3bc06a6"},
|
||||
{file = "ruff-0.9.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:33866c3cc2a575cbd546f2cd02bdd466fed65118e4365ee538a3deffd6fcb730"},
|
||||
{file = "ruff-0.9.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:006e5de2621304c8810bcd2ee101587712fa93b4f955ed0985907a36c427e0c2"},
|
||||
{file = "ruff-0.9.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:ba6eea4459dbd6b1be4e6bfc766079fb9b8dd2e5a35aff6baee4d9b1514ea519"},
|
||||
{file = "ruff-0.9.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:90230a6b8055ad47d3325e9ee8f8a9ae7e273078a66401ac66df68943ced029b"},
|
||||
{file = "ruff-0.9.3-py3-none-win32.whl", hash = "sha256:eabe5eb2c19a42f4808c03b82bd313fc84d4e395133fb3fc1b1516170a31213c"},
|
||||
{file = "ruff-0.9.3-py3-none-win_amd64.whl", hash = "sha256:040ceb7f20791dfa0e78b4230ee9dce23da3b64dd5848e40e3bf3ab76468dcf4"},
|
||||
{file = "ruff-0.9.3-py3-none-win_arm64.whl", hash = "sha256:800d773f6d4d33b0a3c60e2c6ae8f4c202ea2de056365acfa519aa48acf28e0b"},
|
||||
{file = "ruff-0.9.3.tar.gz", hash = "sha256:8293f89985a090ebc3ed1064df31f3b4b56320cdfcec8b60d3295bddb955c22a"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1507,7 +1446,6 @@ version = "1.16.0"
|
|||
description = "Python 2 and 3 compatibility utilities"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
||||
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
||||
|
@ -1519,7 +1457,6 @@ version = "1.3.1"
|
|||
description = "Sniff out which async library your code is running under"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"},
|
||||
{file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
|
||||
|
@ -1531,7 +1468,6 @@ version = "0.11.0"
|
|||
description = "Supabase Storage client for Python."
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.9"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "storage3-0.11.0-py3-none-any.whl", hash = "sha256:de2d8f9c9103ca91a9a9d0d69d80b07a3ab6f647b93e023e6a1a97d3607b9728"},
|
||||
{file = "storage3-0.11.0.tar.gz", hash = "sha256:243583f2180686c0f0a19e6117d8a9796fd60c0ca72ec567d62b75a5af0d57a1"},
|
||||
|
@ -1547,7 +1483,6 @@ version = "0.4.15"
|
|||
description = "An Enum that inherits from str."
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "StrEnum-0.4.15-py3-none-any.whl", hash = "sha256:a30cda4af7cc6b5bf52c8055bc4bf4b2b6b14a93b574626da33df53cf7740659"},
|
||||
{file = "StrEnum-0.4.15.tar.gz", hash = "sha256:878fb5ab705442070e4dd1929bb5e2249511c0bcf2b0eeacf3bcd80875c82eff"},
|
||||
|
@ -1564,7 +1499,6 @@ version = "2.11.0"
|
|||
description = "Supabase client for Python."
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.9"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "supabase-2.11.0-py3-none-any.whl", hash = "sha256:67a0da498895f4cd6554935e2854b4c41f87b297b78fb9c9414902a382041406"},
|
||||
{file = "supabase-2.11.0.tar.gz", hash = "sha256:2a906f7909fd9a50f944cd9332ce66c684e2d37c0864284d34c5815e6c63cc01"},
|
||||
|
@ -1584,7 +1518,6 @@ version = "0.9.2"
|
|||
description = "Library for Supabase Functions"
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.9"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "supafunc-0.9.2-py3-none-any.whl", hash = "sha256:be5ee9f53842c4b0ba5f4abfb5bddf9f9e37e69e755ec0526852bb15af9d2ff5"},
|
||||
{file = "supafunc-0.9.2.tar.gz", hash = "sha256:f5164114a3e65e7e552539f3f1050aa3d4970885abdd7405555c17fd216e2da1"},
|
||||
|
@ -1600,8 +1533,6 @@ version = "2.1.0"
|
|||
description = "A lil' TOML parser"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
markers = "python_version < \"3.11\""
|
||||
files = [
|
||||
{file = "tomli-2.1.0-py3-none-any.whl", hash = "sha256:a5c57c3d1c56f5ccdf89f6523458f60ef716e210fc47c4cfb188c5ba473e0391"},
|
||||
{file = "tomli-2.1.0.tar.gz", hash = "sha256:3f646cae2aec94e17d04973e4249548320197cfabdf130015d023de4b74d8ab8"},
|
||||
|
@ -1613,7 +1544,6 @@ version = "4.12.2"
|
|||
description = "Backported and Experimental Type Hints for Python 3.8+"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
|
||||
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
|
||||
|
@ -1625,7 +1555,6 @@ version = "2.2.2"
|
|||
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"},
|
||||
{file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"},
|
||||
|
@ -1643,7 +1572,6 @@ version = "12.0"
|
|||
description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "websockets-12.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d554236b2a2006e0ce16315c16eaa0d628dab009c33b63ea03f41c6107958374"},
|
||||
{file = "websockets-12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2d225bb6886591b1746b17c0573e29804619c8f755b5598d875bb4235ea639be"},
|
||||
|
@ -1725,7 +1653,6 @@ version = "1.16.0"
|
|||
description = "Module for decorators, wrappers and monkey patching."
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"},
|
||||
{file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"},
|
||||
|
@ -1805,7 +1732,6 @@ version = "1.11.1"
|
|||
description = "Yet another URL library"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "yarl-1.11.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:400cd42185f92de559d29eeb529e71d80dfbd2f45c36844914a4a34297ca6f00"},
|
||||
{file = "yarl-1.11.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8258c86f47e080a258993eed877d579c71da7bda26af86ce6c2d2d072c11320d"},
|
||||
|
@ -1911,7 +1837,6 @@ version = "3.20.1"
|
|||
description = "Backport of pathlib-compatible object wrapper for zip files"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "zipp-3.20.1-py3-none-any.whl", hash = "sha256:9960cd8967c8f85a56f920d5d507274e74f9ff813a0ab8889a5b5be2daf44064"},
|
||||
{file = "zipp-3.20.1.tar.gz", hash = "sha256:c22b14cc4763c5a5b04134207736c107db42e9d3ef2d9779d465f5f1bcba572b"},
|
||||
|
@ -1926,6 +1851,6 @@ test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools",
|
|||
type = ["pytest-mypy"]
|
||||
|
||||
[metadata]
|
||||
lock-version = "2.1"
|
||||
lock-version = "2.0"
|
||||
python-versions = ">=3.10,<4.0"
|
||||
content-hash = "53a31ce3d94999d9267f2a229c53a9d97d96c9413843bfdcb7ef0c0c21723e49"
|
||||
content-hash = "62c4ef3f1ae73546a66783a2dc0672e664ce415a7b0514a7b92fc9fe1a23239e"
|
||||
|
|
|
@ -21,7 +21,7 @@ supabase = "^2.11.0"
|
|||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
redis = "^5.2.1"
|
||||
ruff = "^0.9.2"
|
||||
ruff = "^0.9.3"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
|
|
|
@ -252,3 +252,31 @@ class TextSplitBlock(Block):
|
|||
if input_data.strip:
|
||||
texts = [text.strip() for text in texts]
|
||||
yield "texts", texts
|
||||
|
||||
|
||||
class TextReplaceBlock(Block):
|
||||
class Input(BlockSchema):
|
||||
text: str = SchemaField(description="The text to replace.")
|
||||
old: str = SchemaField(description="The old text to replace.")
|
||||
new: str = SchemaField(description="The new text to replace with.")
|
||||
|
||||
class Output(BlockSchema):
|
||||
output: str = SchemaField(description="The text with the replaced text.")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="7e7c87ab-3469-4bcc-9abe-67705091b713",
|
||||
description="This block is used to replace a text with a new text.",
|
||||
categories={BlockCategory.TEXT},
|
||||
input_schema=TextReplaceBlock.Input,
|
||||
output_schema=TextReplaceBlock.Output,
|
||||
test_input=[
|
||||
{"text": "Hello, World!", "old": "Hello", "new": "Hi"},
|
||||
],
|
||||
test_output=[
|
||||
("output", "Hi, World!"),
|
||||
],
|
||||
)
|
||||
|
||||
def run(self, input_data: Input, **kwargs) -> BlockOutput:
|
||||
yield "output", input_data.text.replace(input_data.old, input_data.new)
|
||||
|
|
|
@ -132,12 +132,14 @@ class UserCreditBase(ABC):
|
|||
},
|
||||
)
|
||||
transaction_balance = (
|
||||
transactions[0].get("_sum", {}).get("amount", 0) + snapshot_balance
|
||||
int(transactions[0].get("_sum", {}).get("amount", 0) + snapshot_balance)
|
||||
if transactions
|
||||
else snapshot_balance
|
||||
)
|
||||
transaction_time = (
|
||||
transactions[0].get("_max", {}).get("createdAt", datetime_min)
|
||||
datetime.fromisoformat(
|
||||
str(transactions[0].get("_max", {}).get("createdAt", datetime_min))
|
||||
)
|
||||
if transactions
|
||||
else snapshot_time
|
||||
)
|
||||
|
@ -360,12 +362,21 @@ class UserCredit(UserCreditBase):
|
|||
)
|
||||
|
||||
async def top_up_intent(self, user_id: str, amount: int) -> str:
|
||||
if amount < 500 or amount % 100 != 0:
|
||||
raise ValueError(
|
||||
f"Top up amount must be at least 500 credits and multiple of 100 but is {amount}"
|
||||
)
|
||||
|
||||
if not (user := await get_user_by_id(user_id)):
|
||||
raise ValueError(f"User not found: {user_id}")
|
||||
|
||||
# Create checkout session
|
||||
# https://docs.stripe.com/checkout/quickstart?client=react
|
||||
# unit_amount param is always in the smallest currency unit (so cents for usd)
|
||||
# which is equal to amount of credits
|
||||
checkout_session = stripe.checkout.Session.create(
|
||||
customer=await get_stripe_customer_id(user_id),
|
||||
customer_email=user.email,
|
||||
line_items=[
|
||||
{
|
||||
"price_data": {
|
||||
|
@ -385,6 +396,7 @@ class UserCredit(UserCreditBase):
|
|||
+ "/marketplace/credits?topup=success",
|
||||
cancel_url=settings.config.platform_base_url
|
||||
+ "/marketplace/credits?topup=cancel",
|
||||
return_url=settings.config.platform_base_url + "/marketplace/credits",
|
||||
)
|
||||
|
||||
await self._add_transaction(
|
||||
|
@ -517,10 +529,10 @@ async def get_stripe_customer_id(user_id: str) -> str:
|
|||
return customer.id
|
||||
|
||||
|
||||
async def set_auto_top_up(user_id: str, threshold: int, amount: int):
|
||||
async def set_auto_top_up(user_id: str, config: AutoTopUpConfig):
|
||||
await User.prisma().update(
|
||||
where={"id": user_id},
|
||||
data={"topUpConfig": Json({"threshold": threshold, "amount": amount})},
|
||||
data={"topUpConfig": Json(config.model_dump())},
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -59,5 +59,4 @@ class UpdatePermissionsRequest(pydantic.BaseModel):
|
|||
|
||||
|
||||
class RequestTopUp(pydantic.BaseModel):
|
||||
amount: int
|
||||
"""Amount of credits to top up."""
|
||||
credit_amount: int
|
||||
|
|
|
@ -151,7 +151,9 @@ async def get_user_credits(
|
|||
async def request_top_up(
|
||||
request: RequestTopUp, user_id: Annotated[str, Depends(get_user_id)]
|
||||
):
|
||||
checkout_url = await _user_credit_model.top_up_intent(user_id, request.amount)
|
||||
checkout_url = await _user_credit_model.top_up_intent(
|
||||
user_id, request.credit_amount
|
||||
)
|
||||
return {"checkout_url": checkout_url}
|
||||
|
||||
|
||||
|
@ -183,7 +185,9 @@ async def configure_user_auto_top_up(
|
|||
else:
|
||||
await _user_credit_model.top_up_credits(user_id, 0)
|
||||
|
||||
await set_auto_top_up(user_id, threshold=request.threshold, amount=request.amount)
|
||||
await set_auto_top_up(
|
||||
user_id, AutoTopUpConfig(threshold=request.threshold, amount=request.amount)
|
||||
)
|
||||
return "Auto top-up settings updated"
|
||||
|
||||
|
||||
|
|
|
@ -173,14 +173,14 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "anthropic"
|
||||
version = "0.40.0"
|
||||
version = "0.45.2"
|
||||
description = "The official Python library for the anthropic API"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "anthropic-0.40.0-py3-none-any.whl", hash = "sha256:442028ae8790ff9e3b6f8912043918755af1230d193904ae2ef78cc22995280c"},
|
||||
{file = "anthropic-0.40.0.tar.gz", hash = "sha256:3efeca6d9e97813f93ed34322c6c7ea2279bf0824cd0aa71b59ce222665e2b87"},
|
||||
{file = "anthropic-0.45.2-py3-none-any.whl", hash = "sha256:ecd746f7274451dfcb7e1180571ead624c7e1195d1d46cb7c70143d2aedb4d35"},
|
||||
{file = "anthropic-0.45.2.tar.gz", hash = "sha256:32a18b9ecd12c91b2be4cae6ca2ab46a06937b5aa01b21308d97a6d29794fb5e"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -190,7 +190,7 @@ httpx = ">=0.23.0,<1"
|
|||
jiter = ">=0.4.0,<1"
|
||||
pydantic = ">=1.9.0,<3"
|
||||
sniffio = "*"
|
||||
typing-extensions = ">=4.7,<5"
|
||||
typing-extensions = ">=4.10,<5"
|
||||
|
||||
[package.extras]
|
||||
bedrock = ["boto3 (>=1.28.57)", "botocore (>=1.31.57)"]
|
||||
|
@ -1015,14 +1015,14 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"]
|
|||
|
||||
[[package]]
|
||||
name = "google-api-python-client"
|
||||
version = "2.159.0"
|
||||
version = "2.160.0"
|
||||
description = "Google API Client Library for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "google_api_python_client-2.159.0-py2.py3-none-any.whl", hash = "sha256:baef0bb631a60a0bd7c0bf12a5499e3a40cd4388484de7ee55c1950bf820a0cf"},
|
||||
{file = "google_api_python_client-2.159.0.tar.gz", hash = "sha256:55197f430f25c907394b44fa078545ffef89d33fd4dca501b7db9f0d8e224bd6"},
|
||||
{file = "google_api_python_client-2.160.0-py2.py3-none-any.whl", hash = "sha256:63d61fb3e4cf3fb31a70a87f45567c22f6dfe87bbfa27252317e3e2c42900db4"},
|
||||
{file = "google_api_python_client-2.160.0.tar.gz", hash = "sha256:a8ccafaecfa42d15d5b5c3134ced8de08380019717fc9fb1ed510ca58eca3b7e"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -1393,14 +1393,14 @@ test = ["objgraph", "psutil"]
|
|||
|
||||
[[package]]
|
||||
name = "groq"
|
||||
version = "0.13.1"
|
||||
version = "0.15.0"
|
||||
description = "The official Python library for the groq API"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "groq-0.13.1-py3-none-any.whl", hash = "sha256:0c5d1d6df93de55de705fe73729b79baaa0c871f7575d6aa64b2962b56101b3e"},
|
||||
{file = "groq-0.13.1.tar.gz", hash = "sha256:588fd5bee984f4eb46ec89552778d5698b9e9614435defef868645c19463cbcc"},
|
||||
{file = "groq-0.15.0-py3-none-any.whl", hash = "sha256:c200558b67fee4b4f2bb89cc166337e3419a68c23280065770f8f8b0729c79ef"},
|
||||
{file = "groq-0.15.0.tar.gz", hash = "sha256:9ad08ba6156c67d0975595a8515b517f22ff63158e063c55192e161ed3648af1"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -2151,14 +2151,14 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "mem0ai"
|
||||
version = "0.1.44"
|
||||
version = "0.1.48"
|
||||
description = "Long-term memory for AI Agents"
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.9"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "mem0ai-0.1.44-py3-none-any.whl", hash = "sha256:32260a2cd935035a1b16ce04ad2e4510a5bd97618709466e2d06303e0eb8d9d4"},
|
||||
{file = "mem0ai-0.1.44.tar.gz", hash = "sha256:93214272915d94f673d370bb8fe7a8bfc21806267e65700b471bec454dcdfa5c"},
|
||||
{file = "mem0ai-0.1.48-py3-none-any.whl", hash = "sha256:23d1bd591c36da9e1f9f013d6f87a79ef9eb1495ac27b1e380af7f819b07fee0"},
|
||||
{file = "mem0ai-0.1.48.tar.gz", hash = "sha256:f5cceb768fa2898e59d55d3d472ccb983e3d9ae82ccba1d435545e16853dbeb6"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -2439,14 +2439,14 @@ pydantic = ">=2.9.0,<3.0.0"
|
|||
|
||||
[[package]]
|
||||
name = "openai"
|
||||
version = "1.60.0"
|
||||
version = "1.60.2"
|
||||
description = "The official Python library for the openai API"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "openai-1.60.0-py3-none-any.whl", hash = "sha256:df06c43be8018274980ac363da07d4b417bd835ead1c66e14396f6f15a0d5dda"},
|
||||
{file = "openai-1.60.0.tar.gz", hash = "sha256:7fa536cd4b644718645b874d2706e36dbbef38b327e42ca0623275da347ee1a9"},
|
||||
{file = "openai-1.60.2-py3-none-any.whl", hash = "sha256:993bd11b96900b9098179c728026f016b4982ded7ee30dfcf4555eab1171fff9"},
|
||||
{file = "openai-1.60.2.tar.gz", hash = "sha256:a8f843e10f2855713007f491d96afb2694b11b5e02cb97c7d01a0be60bc5bb51"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -3451,14 +3451,14 @@ dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments
|
|||
|
||||
[[package]]
|
||||
name = "pytest-asyncio"
|
||||
version = "0.25.2"
|
||||
version = "0.25.3"
|
||||
description = "Pytest support for asyncio"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "pytest_asyncio-0.25.2-py3-none-any.whl", hash = "sha256:0d0bb693f7b99da304a0634afc0a4b19e49d5e0de2d670f38dc4bfa5727c5075"},
|
||||
{file = "pytest_asyncio-0.25.2.tar.gz", hash = "sha256:3f8ef9a98f45948ea91a0ed3dc4268b5326c0e7bce73892acc654df4262ad45f"},
|
||||
{file = "pytest_asyncio-0.25.3-py3-none-any.whl", hash = "sha256:9e89518e0f9bd08928f97a3482fdc4e244df17529460bc038291ccaf8f85c7c3"},
|
||||
{file = "pytest_asyncio-0.25.3.tar.gz", hash = "sha256:fc1da2cf9f125ada7e710b4ddad05518d4cee187ae9412e9ac9271003497f07a"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -3959,14 +3959,14 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "sentry-sdk"
|
||||
version = "2.19.2"
|
||||
version = "2.20.0"
|
||||
description = "Python client for Sentry (https://sentry.io)"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "sentry_sdk-2.19.2-py2.py3-none-any.whl", hash = "sha256:ebdc08228b4d131128e568d696c210d846e5b9d70aa0327dec6b1272d9d40b84"},
|
||||
{file = "sentry_sdk-2.19.2.tar.gz", hash = "sha256:467df6e126ba242d39952375dd816fbee0f217d119bf454a8ce74cf1e7909e8d"},
|
||||
{file = "sentry_sdk-2.20.0-py2.py3-none-any.whl", hash = "sha256:c359a1edf950eb5e80cffd7d9111f3dbeef57994cb4415df37d39fda2cf22364"},
|
||||
{file = "sentry_sdk-2.20.0.tar.gz", hash = "sha256:afa82713a92facf847df3c6f63cec71eb488d826a50965def3d7722aa6f0fdab"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -4011,6 +4011,7 @@ sqlalchemy = ["sqlalchemy (>=1.2)"]
|
|||
starlette = ["starlette (>=0.19.1)"]
|
||||
starlite = ["starlite (>=1.48)"]
|
||||
tornado = ["tornado (>=6)"]
|
||||
unleash = ["UnleashClient (>=6.0.1)"]
|
||||
|
||||
[[package]]
|
||||
name = "serpent"
|
||||
|
@ -4229,14 +4230,14 @@ test = ["pylint", "pytest", "pytest-black", "pytest-cov", "pytest-pylint"]
|
|||
|
||||
[[package]]
|
||||
name = "stripe"
|
||||
version = "11.4.1"
|
||||
version = "11.5.0"
|
||||
description = "Python bindings for the Stripe API"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "stripe-11.4.1-py2.py3-none-any.whl", hash = "sha256:8aa47a241de0355c383c916c4ef7273ab666f096a44ee7081e357db4a36f0cce"},
|
||||
{file = "stripe-11.4.1.tar.gz", hash = "sha256:7ddd251b622d490fe57d78487855dc9f4d95b1bb113607e81fd377037a133d5a"},
|
||||
{file = "stripe-11.5.0-py2.py3-none-any.whl", hash = "sha256:3b2cd47ed3002328249bff5cacaee38d5e756c3899ab425d3bd07acdaf32534a"},
|
||||
{file = "stripe-11.5.0.tar.gz", hash = "sha256:bc3e0358ffc23d5ecfa8aafec1fa4f048ee8107c3237bcb00003e68c8c96fa02"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -4245,14 +4246,14 @@ typing-extensions = {version = ">=4.5.0", markers = "python_version >= \"3.7\""}
|
|||
|
||||
[[package]]
|
||||
name = "supabase"
|
||||
version = "2.11.0"
|
||||
version = "2.12.0"
|
||||
description = "Supabase client for Python."
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.9"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "supabase-2.11.0-py3-none-any.whl", hash = "sha256:67a0da498895f4cd6554935e2854b4c41f87b297b78fb9c9414902a382041406"},
|
||||
{file = "supabase-2.11.0.tar.gz", hash = "sha256:2a906f7909fd9a50f944cd9332ce66c684e2d37c0864284d34c5815e6c63cc01"},
|
||||
{file = "supabase-2.12.0-py3-none-any.whl", hash = "sha256:f8896f3314179fdf27f8bb8357947493ec32b98dcdac7114208aaf21cd59ce35"},
|
||||
{file = "supabase-2.12.0.tar.gz", hash = "sha256:284612c3e94ff4ed2f18c985f5eba4d6e17b5e2bf16a9a24290bb83c9c217078"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -5034,4 +5035,4 @@ type = ["pytest-mypy"]
|
|||
[metadata]
|
||||
lock-version = "2.1"
|
||||
python-versions = ">=3.10,<3.13"
|
||||
content-hash = "38a5c750ddca1a6264fd98b7ee74d199c2bbf57d3acc189264bd9f8ec90febc2"
|
||||
content-hash = "7d37edf4fd4e1935811629fef29d463fa61f904d520aa497de2969fadeba92ec"
|
||||
|
|
|
@ -10,7 +10,7 @@ packages = [{ include = "backend", format = "sdist" }]
|
|||
[tool.poetry.dependencies]
|
||||
python = ">=3.10,<3.13"
|
||||
aio-pika = "^9.5.4"
|
||||
anthropic = "^0.40.0"
|
||||
anthropic = "^0.45.2"
|
||||
apscheduler = "^3.11.0"
|
||||
autogpt-libs = { path = "../autogpt_libs", develop = true }
|
||||
click = "^8.1.7"
|
||||
|
@ -19,14 +19,14 @@ e2b-code-interpreter = "^1.0.1"
|
|||
fastapi = "^0.115.5"
|
||||
feedparser = "^6.0.11"
|
||||
flake8 = "^7.0.0"
|
||||
google-api-python-client = "^2.154.0"
|
||||
google-api-python-client = "^2.160.0"
|
||||
google-auth-oauthlib = "^1.2.1"
|
||||
groq = "^0.13.1"
|
||||
groq = "^0.15.0"
|
||||
jinja2 = "^3.1.4"
|
||||
jsonref = "^1.1.0"
|
||||
jsonschema = "^4.22.0"
|
||||
ollama = "^0.4.1"
|
||||
openai = "^1.57.4"
|
||||
openai = "^1.60.2"
|
||||
praw = "~7.8.1"
|
||||
prisma = "^0.15.0"
|
||||
psutil = "^6.1.0"
|
||||
|
@ -34,13 +34,13 @@ pydantic = "^2.9.2"
|
|||
pydantic-settings = "^2.3.4"
|
||||
pyro5 = "^5.15"
|
||||
pytest = "^8.2.1"
|
||||
pytest-asyncio = "^0.25.0"
|
||||
pytest-asyncio = "^0.25.3"
|
||||
python-dotenv = "^1.0.1"
|
||||
redis = "^5.2.0"
|
||||
sentry-sdk = "2.19.2"
|
||||
sentry-sdk = "2.20.0"
|
||||
strenum = "^0.4.9"
|
||||
stripe = "^11.3.0"
|
||||
supabase = "2.11.0"
|
||||
stripe = "^11.5.0"
|
||||
supabase = "2.12.0"
|
||||
tenacity = "^9.0.0"
|
||||
tweepy = "^4.14.0"
|
||||
uvicorn = { extras = ["standard"], version = "^0.34.0" }
|
||||
|
@ -55,7 +55,7 @@ sqlalchemy = "^2.0.36"
|
|||
psycopg2-binary = "^2.9.10"
|
||||
google-cloud-storage = "^2.18.2"
|
||||
launchdarkly-server-sdk = "^9.8.0"
|
||||
mem0ai = "^0.1.44"
|
||||
mem0ai = "^0.1.48"
|
||||
moviepy = "^2.1.2"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
|
|
|
@ -92,17 +92,23 @@ async def test_block_credit_reset(server: SpinTestServer):
|
|||
month2 = 2
|
||||
|
||||
# set the calendar to month 2 but use current time from now
|
||||
user_credit.time_now = lambda: datetime.now(timezone.utc).replace(month=month2)
|
||||
user_credit.time_now = lambda: datetime.now(timezone.utc).replace(
|
||||
month=month2, day=1
|
||||
)
|
||||
month2credit = await user_credit.get_credits(DEFAULT_USER_ID)
|
||||
|
||||
# Month 1 result should only affect month 1
|
||||
user_credit.time_now = lambda: datetime.now(timezone.utc).replace(month=month1)
|
||||
user_credit.time_now = lambda: datetime.now(timezone.utc).replace(
|
||||
month=month1, day=1
|
||||
)
|
||||
month1credit = await user_credit.get_credits(DEFAULT_USER_ID)
|
||||
await top_up(100)
|
||||
assert await user_credit.get_credits(DEFAULT_USER_ID) == month1credit + 100
|
||||
|
||||
# Month 2 balance is unaffected
|
||||
user_credit.time_now = lambda: datetime.now(timezone.utc).replace(month=month2)
|
||||
user_credit.time_now = lambda: datetime.now(timezone.utc).replace(
|
||||
month=month2, day=1
|
||||
)
|
||||
assert await user_credit.get_credits(DEFAULT_USER_ID) == month2credit
|
||||
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import { withRoleAccess } from "@/lib/withRoleAccess";
|
||||
|
||||
import React from "react";
|
||||
import { getReviewableAgents } from "@/components/admin/marketplace/actions";
|
||||
import AdminMarketplaceAgentList from "@/components/admin/marketplace/AdminMarketplaceAgentList";
|
||||
import AdminFeaturedAgentsControl from "@/components/admin/marketplace/AdminFeaturedAgentsControl";
|
||||
// import { getReviewableAgents } from "@/components/admin/marketplace/actions";
|
||||
// import AdminMarketplaceAgentList from "@/components/admin/marketplace/AdminMarketplaceAgentList";
|
||||
// import AdminFeaturedAgentsControl from "@/components/admin/marketplace/AdminFeaturedAgentsControl";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
async function AdminMarketplace() {
|
||||
const reviewableAgents = await getReviewableAgents();
|
||||
// const reviewableAgents = await getReviewableAgents();
|
||||
|
||||
return (
|
||||
<>
|
||||
<AdminMarketplaceAgentList agents={reviewableAgents.items} />
|
||||
<Separator className="my-4" />
|
||||
<AdminFeaturedAgentsControl className="mt-4" />
|
||||
{/* <AdminMarketplaceAgentList agents={reviewableAgents.items} />
|
||||
<Separator className="my-4" />
|
||||
<AdminFeaturedAgentsControl className="mt-4" /> */}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -179,6 +179,7 @@ export default function PrivatePage() {
|
|||
{
|
||||
oauth2: "OAuth2 credentials",
|
||||
api_key: "API key",
|
||||
user_password: "Username & password",
|
||||
}[cred.type]
|
||||
}{" "}
|
||||
- <code>{cred.id}</code>
|
||||
|
|
|
@ -151,11 +151,7 @@ function SearchResults({
|
|||
<div className="min-h-[500px] max-w-[1440px]">
|
||||
{showAgents && agentsCount > 0 && (
|
||||
<div className="mt-[36px]">
|
||||
<AgentsSection
|
||||
agents={agents}
|
||||
sectionTitle="Agents"
|
||||
className="font-[Large-Poppins] text-[18px] font-semibold leading-[28px]"
|
||||
/>
|
||||
<AgentsSection agents={agents} sectionTitle="Agents" />
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
|
|
@ -109,78 +109,80 @@ export default function ResetPasswordPage() {
|
|||
}
|
||||
|
||||
return (
|
||||
<AuthCard>
|
||||
<AuthHeader>Reset Password</AuthHeader>
|
||||
{user ? (
|
||||
<form onSubmit={changePasswordForm.handleSubmit(onChangePassword)}>
|
||||
<Form {...changePasswordForm}>
|
||||
<FormField
|
||||
control={changePasswordForm.control}
|
||||
name="password"
|
||||
render={({ field }) => (
|
||||
<FormItem className="mb-6">
|
||||
<FormLabel>Password</FormLabel>
|
||||
<FormControl>
|
||||
<PasswordInput {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={changePasswordForm.control}
|
||||
name="confirmPassword"
|
||||
render={({ field }) => (
|
||||
<FormItem className="mb-6">
|
||||
<FormLabel>Confirm Password</FormLabel>
|
||||
<FormControl>
|
||||
<PasswordInput {...field} />
|
||||
</FormControl>
|
||||
<FormDescription className="text-sm font-normal leading-tight text-slate-500">
|
||||
Password needs to be at least 6 characters long
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<AuthButton
|
||||
onClick={() => onChangePassword(changePasswordForm.getValues())}
|
||||
isLoading={isLoading}
|
||||
type="submit"
|
||||
>
|
||||
Update password
|
||||
</AuthButton>
|
||||
<AuthFeedback message={feedback} isError={isError} />
|
||||
</Form>
|
||||
</form>
|
||||
) : (
|
||||
<form onSubmit={sendEmailForm.handleSubmit(onSendEmail)}>
|
||||
<Form {...sendEmailForm}>
|
||||
<FormField
|
||||
control={sendEmailForm.control}
|
||||
name="email"
|
||||
render={({ field }) => (
|
||||
<FormItem className="mb-6">
|
||||
<FormLabel>Email</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="m@example.com" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<AuthButton
|
||||
onClick={() => onSendEmail(sendEmailForm.getValues())}
|
||||
isLoading={isLoading}
|
||||
disabled={disabled}
|
||||
type="submit"
|
||||
>
|
||||
Send reset email
|
||||
</AuthButton>
|
||||
<AuthFeedback message={feedback} isError={isError} />
|
||||
</Form>
|
||||
</form>
|
||||
)}
|
||||
</AuthCard>
|
||||
<div className="flex min-h-screen items-center justify-center">
|
||||
<AuthCard>
|
||||
<AuthHeader>Reset Password</AuthHeader>
|
||||
{user ? (
|
||||
<form onSubmit={changePasswordForm.handleSubmit(onChangePassword)}>
|
||||
<Form {...changePasswordForm}>
|
||||
<FormField
|
||||
control={changePasswordForm.control}
|
||||
name="password"
|
||||
render={({ field }) => (
|
||||
<FormItem className="mb-6">
|
||||
<FormLabel>Password</FormLabel>
|
||||
<FormControl>
|
||||
<PasswordInput {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={changePasswordForm.control}
|
||||
name="confirmPassword"
|
||||
render={({ field }) => (
|
||||
<FormItem className="mb-6">
|
||||
<FormLabel>Confirm Password</FormLabel>
|
||||
<FormControl>
|
||||
<PasswordInput {...field} />
|
||||
</FormControl>
|
||||
<FormDescription className="text-sm font-normal leading-tight text-slate-500">
|
||||
Password needs to be at least 6 characters long
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<AuthButton
|
||||
onClick={() => onChangePassword(changePasswordForm.getValues())}
|
||||
isLoading={isLoading}
|
||||
type="submit"
|
||||
>
|
||||
Update password
|
||||
</AuthButton>
|
||||
<AuthFeedback message={feedback} isError={isError} />
|
||||
</Form>
|
||||
</form>
|
||||
) : (
|
||||
<form onSubmit={sendEmailForm.handleSubmit(onSendEmail)}>
|
||||
<Form {...sendEmailForm}>
|
||||
<FormField
|
||||
control={sendEmailForm.control}
|
||||
name="email"
|
||||
render={({ field }) => (
|
||||
<FormItem className="mb-6">
|
||||
<FormLabel>Email</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="m@example.com" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<AuthButton
|
||||
onClick={() => onSendEmail(sendEmailForm.getValues())}
|
||||
isLoading={isLoading}
|
||||
disabled={disabled}
|
||||
type="submit"
|
||||
>
|
||||
Send reset email
|
||||
</AuthButton>
|
||||
<AuthFeedback message={feedback} isError={isError} />
|
||||
</Form>
|
||||
</form>
|
||||
)}
|
||||
</AuthCard>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -250,7 +250,7 @@ const FlowEditor: React.FC<{
|
|||
if (deletedNodeData) {
|
||||
history.push({
|
||||
type: "DELETE_NODE",
|
||||
payload: { node: deletedNodeData },
|
||||
payload: { node: deletedNodeData.data },
|
||||
undo: () => addNodes(deletedNodeData),
|
||||
redo: () => deleteElements({ nodes: [{ id: nodeID }] }),
|
||||
});
|
||||
|
@ -660,7 +660,7 @@ const FlowEditor: React.FC<{
|
|||
onNodeDragStop={onNodeDragEnd}
|
||||
onNodeDragStart={onNodeDragStart}
|
||||
deleteKeyCode={["Backspace", "Delete"]}
|
||||
minZoom={0.2}
|
||||
minZoom={0.1}
|
||||
maxZoom={2}
|
||||
className="dark:bg-slate-900"
|
||||
>
|
||||
|
|
|
@ -9,6 +9,7 @@ import RunnerOutputUI from "./runner-ui/RunnerOutputUI";
|
|||
import { Node } from "@xyflow/react";
|
||||
import { filterBlocksByType } from "@/lib/utils";
|
||||
import { BlockIORootSchema, BlockUIType } from "@/lib/autogpt-server-api/types";
|
||||
import { CustomNode } from "./CustomNode";
|
||||
|
||||
interface HardcodedValues {
|
||||
name: any;
|
||||
|
@ -27,7 +28,7 @@ export interface InputItem {
|
|||
|
||||
interface RunnerUIWrapperProps {
|
||||
nodes: Node[];
|
||||
setNodes: React.Dispatch<React.SetStateAction<Node[]>>;
|
||||
setNodes: React.Dispatch<React.SetStateAction<CustomNode[]>>;
|
||||
setIsScheduling: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
isRunning: boolean;
|
||||
isScheduling: boolean;
|
||||
|
|
|
@ -10,7 +10,6 @@ const meta = {
|
|||
},
|
||||
tags: ["autodocs"],
|
||||
argTypes: {
|
||||
onRunAgent: { action: "run agent clicked" },
|
||||
name: { control: "text" },
|
||||
creator: { control: "text" },
|
||||
shortDescription: { control: "text" },
|
||||
|
@ -28,8 +27,8 @@ type Story = StoryObj<typeof meta>;
|
|||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
onRunAgent: () => console.log("Run agent clicked"),
|
||||
name: "AI Video Generator",
|
||||
storeListingVersionId: "123",
|
||||
creator: "Toran Richards",
|
||||
shortDescription:
|
||||
"Transform ideas into breathtaking images with this AI-powered Image Generator.",
|
||||
|
|
|
@ -15,40 +15,64 @@ type Story = StoryObj<typeof AgentTable>;
|
|||
|
||||
const sampleAgents: AgentTableRowProps[] = [
|
||||
{
|
||||
id: "agent-1",
|
||||
id: 43,
|
||||
agentName: "Super Coder",
|
||||
description: "An AI agent that writes clean, efficient code",
|
||||
imageSrc:
|
||||
imageSrc: [
|
||||
"https://ddz4ak4pa3d19.cloudfront.net/cache/53/b2/53b2bc7d7900f0e1e60bf64ebf38032d.jpg",
|
||||
],
|
||||
dateSubmitted: "2023-05-15",
|
||||
status: "approved",
|
||||
runs: 1500,
|
||||
rating: 4.8,
|
||||
onEdit: () => console.log("Edit Super Coder"),
|
||||
agent_id: "43",
|
||||
agent_version: 1,
|
||||
sub_heading: "Super Coder",
|
||||
date_submitted: "2023-05-15",
|
||||
onEditSubmission: () => console.log("Edit Super Coder"),
|
||||
onDeleteSubmission: () => console.log("Delete Super Coder"),
|
||||
selectedAgents: new Set(),
|
||||
setSelectedAgents: () => {},
|
||||
},
|
||||
{
|
||||
id: "agent-2",
|
||||
id: 44,
|
||||
agentName: "Data Analyzer",
|
||||
description: "Processes and analyzes large datasets with ease",
|
||||
imageSrc:
|
||||
imageSrc: [
|
||||
"https://ddz4ak4pa3d19.cloudfront.net/cache/40/f7/40f7bc97c952f8df0f9c88d29defe8d4.jpg",
|
||||
],
|
||||
dateSubmitted: "2023-05-10",
|
||||
status: "awaiting_review",
|
||||
runs: 1200,
|
||||
rating: 4.5,
|
||||
onEdit: () => console.log("Edit Data Analyzer"),
|
||||
agent_id: "44",
|
||||
agent_version: 1,
|
||||
sub_heading: "Data Analyzer",
|
||||
date_submitted: "2023-05-10",
|
||||
onEditSubmission: () => console.log("Edit Data Analyzer"),
|
||||
onDeleteSubmission: () => console.log("Delete Data Analyzer"),
|
||||
selectedAgents: new Set(),
|
||||
setSelectedAgents: () => {},
|
||||
},
|
||||
{
|
||||
id: "agent-3",
|
||||
id: 45,
|
||||
agentName: "UI Designer",
|
||||
description: "Creates beautiful and intuitive user interfaces",
|
||||
imageSrc:
|
||||
imageSrc: [
|
||||
"https://ddz4ak4pa3d19.cloudfront.net/cache/14/9e/149ebb9014aa8c0097e72ed89845af0e.jpg",
|
||||
],
|
||||
dateSubmitted: "2023-05-05",
|
||||
status: "draft",
|
||||
runs: 800,
|
||||
rating: 4.2,
|
||||
onEdit: () => console.log("Edit UI Designer"),
|
||||
agent_id: "45",
|
||||
agent_version: 1,
|
||||
sub_heading: "UI Designer",
|
||||
date_submitted: "2023-05-05",
|
||||
onEditSubmission: () => console.log("Edit UI Designer"),
|
||||
onDeleteSubmission: () => console.log("Delete UI Designer"),
|
||||
selectedAgents: new Set(),
|
||||
setSelectedAgents: () => {},
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
@ -16,13 +16,13 @@ export const Default: Story = {
|
|||
args: {
|
||||
agentName: "Super Coder",
|
||||
description: "An AI agent that writes clean, efficient code",
|
||||
imageSrc:
|
||||
imageSrc: [
|
||||
"https://ddz4ak4pa3d19.cloudfront.net/cache/53/b2/53b2bc7d7900f0e1e60bf64ebf38032d.jpg",
|
||||
],
|
||||
dateSubmitted: "2023-05-15",
|
||||
status: "ACTIVE" as StatusType,
|
||||
runs: 1500,
|
||||
rating: 4.8,
|
||||
onEdit: () => console.log("Edit Super Coder"),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import * as React from "react";
|
|||
import Image from "next/image";
|
||||
import { IconStarFilled, IconMore } from "@/components/ui/icons";
|
||||
import { Status, StatusType } from "./Status";
|
||||
import { StoreSubmissionRequest } from "@/lib/autogpt-server-api";
|
||||
|
||||
export interface AgentTableCardProps {
|
||||
agent_id: string;
|
||||
|
|
|
@ -11,7 +11,6 @@ const meta = {
|
|||
tags: ["autodocs"],
|
||||
argTypes: {
|
||||
title: { control: "text" },
|
||||
heading: { control: "text" },
|
||||
description: { control: "text" },
|
||||
buttonText: { control: "text" },
|
||||
onButtonClick: { action: "buttonClicked" },
|
||||
|
@ -24,7 +23,6 @@ type Story = StoryObj<typeof meta>;
|
|||
export const Default: Story = {
|
||||
args: {
|
||||
title: "Want to contribute?",
|
||||
heading: "We're always looking for more Creators!",
|
||||
description: "Join our ever-growing community of hackers and tinkerers",
|
||||
buttonText: "Become a Creator",
|
||||
onButtonClick: () => console.log("Button clicked"),
|
||||
|
@ -34,7 +32,6 @@ export const Default: Story = {
|
|||
export const CustomText: Story = {
|
||||
args: {
|
||||
title: "Become a Creator Today!",
|
||||
heading: "Join Our Creator Community",
|
||||
description: "Share your ideas and build amazing AI agents with us",
|
||||
buttonText: "Start Creating",
|
||||
onButtonClick: () => console.log("Custom button clicked"),
|
||||
|
|
|
@ -15,7 +15,6 @@ const meta = {
|
|||
bio: { control: "text" },
|
||||
agentsUploaded: { control: "number" },
|
||||
onClick: { action: "clicked" },
|
||||
avatarSrc: { control: "text" },
|
||||
},
|
||||
} satisfies Meta<typeof CreatorCard>;
|
||||
|
||||
|
@ -24,49 +23,49 @@ type Story = StoryObj<typeof meta>;
|
|||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
index: 0,
|
||||
creatorName: "John Doe",
|
||||
creatorImage:
|
||||
"https://framerusercontent.com/images/KCIpxr9f97EGJgpaoqnjKsrOPwI.jpg",
|
||||
bio: "AI enthusiast and developer with a passion for creating innovative agents.",
|
||||
agentsUploaded: 15,
|
||||
onClick: () => console.log("Default CreatorCard clicked"),
|
||||
avatarSrc: "https://github.com/shadcn.png",
|
||||
},
|
||||
};
|
||||
|
||||
export const NewCreator: Story = {
|
||||
args: {
|
||||
index: 1,
|
||||
creatorName: "Jane Smith",
|
||||
creatorImage:
|
||||
"https://framerusercontent.com/images/KCIpxr9f97EGJgpaoqnjKsrOPwI.jpg",
|
||||
bio: "Excited to start my journey in AI agent development!",
|
||||
agentsUploaded: 1,
|
||||
onClick: () => console.log("NewCreator CreatorCard clicked"),
|
||||
avatarSrc: "https://example.com/avatar2.jpg",
|
||||
},
|
||||
};
|
||||
|
||||
export const ExperiencedCreator: Story = {
|
||||
args: {
|
||||
index: 2,
|
||||
creatorName: "Alex Johnson",
|
||||
creatorImage:
|
||||
"https://framerusercontent.com/images/KCIpxr9f97EGJgpaoqnjKsrOPwI.jpg",
|
||||
bio: "Veteran AI researcher with a focus on natural language processing and machine learning.",
|
||||
agentsUploaded: 50,
|
||||
onClick: () => console.log("ExperiencedCreator CreatorCard clicked"),
|
||||
avatarSrc: "https://example.com/avatar3.jpg",
|
||||
},
|
||||
};
|
||||
|
||||
export const WithInteraction: Story = {
|
||||
args: {
|
||||
index: 3,
|
||||
creatorName: "Sam Brown",
|
||||
creatorImage:
|
||||
"https://framerusercontent.com/images/KCIpxr9f97EGJgpaoqnjKsrOPwI.jpg",
|
||||
bio: "Exploring the frontiers of AI and its applications in everyday life.",
|
||||
agentsUploaded: 30,
|
||||
onClick: () => console.log("WithInteraction CreatorCard clicked"),
|
||||
avatarSrc: "https://example.com/avatar4.jpg",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
|
|
@ -21,51 +21,48 @@ type Story = StoryObj<typeof meta>;
|
|||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
links: {
|
||||
website: "https://example.com",
|
||||
linkedin: "https://linkedin.com/in/johndoe",
|
||||
github: "https://github.com/johndoe",
|
||||
other: ["https://twitter.com/johndoe", "https://medium.com/@johndoe"],
|
||||
},
|
||||
links: [
|
||||
"https://example.com",
|
||||
"https://linkedin.com/in/johndoe",
|
||||
"https://github.com/johndoe",
|
||||
"https://twitter.com/johndoe",
|
||||
"https://medium.com/@johndoe",
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export const WebsiteOnly: Story = {
|
||||
args: {
|
||||
links: {
|
||||
website: "https://example.com",
|
||||
},
|
||||
links: ["https://example.com"],
|
||||
},
|
||||
};
|
||||
|
||||
export const SocialLinks: Story = {
|
||||
args: {
|
||||
links: {
|
||||
linkedin: "https://linkedin.com/in/janedoe",
|
||||
github: "https://github.com/janedoe",
|
||||
other: ["https://twitter.com/janedoe"],
|
||||
},
|
||||
links: [
|
||||
"https://linkedin.com/in/janedoe",
|
||||
"https://github.com/janedoe",
|
||||
"https://twitter.com/janedoe",
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export const NoLinks: Story = {
|
||||
args: {
|
||||
links: {},
|
||||
links: [],
|
||||
},
|
||||
};
|
||||
|
||||
export const MultipleOtherLinks: Story = {
|
||||
args: {
|
||||
links: {
|
||||
website: "https://example.com",
|
||||
linkedin: "https://linkedin.com/in/creator",
|
||||
github: "https://github.com/creator",
|
||||
other: [
|
||||
"https://twitter.com/creator",
|
||||
"https://medium.com/@creator",
|
||||
"https://youtube.com/@creator",
|
||||
"https://tiktok.com/@creator",
|
||||
],
|
||||
},
|
||||
links: [
|
||||
"https://example.com",
|
||||
"https://linkedin.com/in/creator",
|
||||
"https://github.com/creator",
|
||||
"https://twitter.com/creator",
|
||||
"https://medium.com/@creator",
|
||||
"https://youtube.com/@creator",
|
||||
"https://tiktok.com/@creator",
|
||||
],
|
||||
},
|
||||
};
|
||||
|
|
|
@ -43,6 +43,7 @@ export const Default: Story = {
|
|||
runs: 50000,
|
||||
rating: 4.7,
|
||||
onClick: () => console.log("Card clicked"),
|
||||
backgroundColor: "bg-white",
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -60,6 +61,7 @@ export const LowRating: Story = {
|
|||
runs: 10000,
|
||||
rating: 2.8,
|
||||
onClick: () => console.log("Card clicked"),
|
||||
backgroundColor: "bg-white",
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -77,6 +79,7 @@ export const HighRuns: Story = {
|
|||
runs: 1000000,
|
||||
rating: 4.9,
|
||||
onClick: () => console.log("Card clicked"),
|
||||
backgroundColor: "bg-white",
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -92,6 +95,7 @@ export const NoCreatorImage: Story = {
|
|||
runs: 75000,
|
||||
rating: 4.5,
|
||||
onClick: () => console.log("Card clicked"),
|
||||
backgroundColor: "bg-white",
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -108,6 +112,7 @@ export const ShortDescription: Story = {
|
|||
runs: 50000,
|
||||
rating: 4.2,
|
||||
onClick: () => console.log("Card clicked"),
|
||||
backgroundColor: "bg-white",
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -125,6 +130,7 @@ export const WithInteraction: Story = {
|
|||
runs: 200000,
|
||||
rating: 4.6,
|
||||
onClick: () => console.log("Card clicked"),
|
||||
backgroundColor: "bg-white",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
|
|
@ -13,7 +13,6 @@ const meta = {
|
|||
argTypes: {
|
||||
userName: { control: "text" },
|
||||
userEmail: { control: "text" },
|
||||
activeLink: { control: "text" },
|
||||
avatarSrc: { control: "text" },
|
||||
menuItemGroups: { control: "object" },
|
||||
},
|
||||
|
@ -67,7 +66,6 @@ export const Default: Story = {
|
|||
args: {
|
||||
userName: "John Doe",
|
||||
userEmail: "john.doe@example.com",
|
||||
activeLink: "/marketplace",
|
||||
avatarSrc: "https://avatars.githubusercontent.com/u/123456789?v=4",
|
||||
menuItemGroups: defaultMenuItemGroups,
|
||||
},
|
||||
|
@ -77,7 +75,6 @@ export const NoAvatar: Story = {
|
|||
args: {
|
||||
userName: "Jane Smith",
|
||||
userEmail: "jane.smith@example.com",
|
||||
activeLink: "/library",
|
||||
menuItemGroups: defaultMenuItemGroups,
|
||||
},
|
||||
};
|
||||
|
@ -86,7 +83,6 @@ export const LongUserName: Story = {
|
|||
args: {
|
||||
userName: "Alexander Bartholomew Christopherson III",
|
||||
userEmail: "alexander@example.com",
|
||||
activeLink: "/builder",
|
||||
avatarSrc: "https://avatars.githubusercontent.com/u/987654321?v=4",
|
||||
menuItemGroups: defaultMenuItemGroups,
|
||||
},
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import Navbar from "./Navbar";
|
||||
import { Navbar } from "./Navbar";
|
||||
import { userEvent, within } from "@storybook/test";
|
||||
import { IconType } from "../ui/icons";
|
||||
import { ProfileDetails } from "@/lib/autogpt-server-api/types";
|
||||
import { jest } from "@jest/globals";
|
||||
// You can't import this here, jest is not available in storybook and will crash it
|
||||
// import { jest } from "@jest/globals";
|
||||
|
||||
// Mock the API responses
|
||||
const mockProfileData: ProfileDetails = {
|
||||
|
@ -19,14 +20,14 @@ const mockCreditData = {
|
|||
};
|
||||
|
||||
// Mock the API module
|
||||
jest.mock("@/lib/autogpt-server-api", () => {
|
||||
return function () {
|
||||
return {
|
||||
getStoreProfile: () => Promise.resolve(mockProfileData),
|
||||
getUserCredit: () => Promise.resolve(mockCreditData),
|
||||
};
|
||||
};
|
||||
});
|
||||
// jest.mock("@/lib/autogpt-server-api", () => {
|
||||
// return function () {
|
||||
// return {
|
||||
// getStoreProfile: () => Promise.resolve(mockProfileData),
|
||||
// getUserCredit: () => Promise.resolve(mockCreditData),
|
||||
// };
|
||||
// };
|
||||
// });
|
||||
|
||||
const meta = {
|
||||
title: "AGPT UI/Navbar",
|
||||
|
@ -36,12 +37,12 @@ const meta = {
|
|||
},
|
||||
tags: ["autodocs"],
|
||||
argTypes: {
|
||||
isLoggedIn: { control: "boolean" },
|
||||
avatarSrc: { control: "text" },
|
||||
// isLoggedIn: { control: "boolean" },
|
||||
// avatarSrc: { control: "text" },
|
||||
links: { control: "object" },
|
||||
activeLink: { control: "text" },
|
||||
// activeLink: { control: "text" },
|
||||
menuItemGroups: { control: "object" },
|
||||
params: { control: { type: "object", defaultValue: { lang: "en" } } },
|
||||
// params: { control: { type: "object", defaultValue: { lang: "en" } } },
|
||||
},
|
||||
} satisfies Meta<typeof Navbar>;
|
||||
|
||||
|
@ -90,11 +91,11 @@ const defaultLinks = [
|
|||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
params: { lang: "en" },
|
||||
isLoggedIn: true,
|
||||
// params: { lang: "en" },
|
||||
// isLoggedIn: true,
|
||||
links: defaultLinks,
|
||||
activeLink: "/marketplace",
|
||||
avatarSrc: mockProfileData.avatar_url,
|
||||
// activeLink: "/marketplace",
|
||||
// avatarSrc: mockProfileData.avatar_url,
|
||||
menuItemGroups: defaultMenuItemGroups,
|
||||
},
|
||||
};
|
||||
|
@ -102,21 +103,21 @@ export const Default: Story = {
|
|||
export const WithActiveLink: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
activeLink: "/library",
|
||||
// activeLink: "/library",
|
||||
},
|
||||
};
|
||||
|
||||
export const LongUserName: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
avatarSrc: "https://avatars.githubusercontent.com/u/987654321?v=4",
|
||||
// avatarSrc: "https://avatars.githubusercontent.com/u/987654321?v=4",
|
||||
},
|
||||
};
|
||||
|
||||
export const NoAvatar: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
avatarSrc: undefined,
|
||||
// avatarSrc: undefined,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -138,8 +139,8 @@ export const WithInteraction: Story = {
|
|||
export const NotLoggedIn: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
isLoggedIn: false,
|
||||
avatarSrc: undefined,
|
||||
// isLoggedIn: false,
|
||||
// avatarSrc: undefined,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -63,12 +63,7 @@ export const Navbar = async ({ links, menuItemGroups }: NavbarProps) => {
|
|||
<IconAutoGPTLogo className="h-full w-full" />
|
||||
</div>
|
||||
{links.map((link) => (
|
||||
<NavbarLink
|
||||
key={link.name}
|
||||
name={link.name}
|
||||
href={link.href}
|
||||
className="font-poppins text-[20px] leading-[28px]"
|
||||
/>
|
||||
<NavbarLink key={link.name} name={link.name} href={link.href} />
|
||||
))}
|
||||
</div>
|
||||
{/* Profile section */}
|
||||
|
|
|
@ -20,7 +20,11 @@ export const NavbarLink = ({ name, href }: NavbarLinkProps) => {
|
|||
const activeLink = "/" + (parts.length > 2 ? parts[2] : parts[1]);
|
||||
|
||||
return (
|
||||
<Link href={href} data-testid={`navbar-link-${name.toLowerCase()}`}>
|
||||
<Link
|
||||
href={href}
|
||||
data-testid={`navbar-link-${name.toLowerCase()}`}
|
||||
className="font-poppins text-[20px] leading-[28px]"
|
||||
>
|
||||
<div
|
||||
className={`h-[48px] px-5 py-4 ${
|
||||
activeLink === href
|
||||
|
|
|
@ -9,29 +9,33 @@ const meta: Meta<typeof ProfileInfoForm> = {
|
|||
},
|
||||
tags: ["autodocs"],
|
||||
argTypes: {
|
||||
displayName: {
|
||||
control: "text",
|
||||
description: "The display name of the user",
|
||||
},
|
||||
handle: {
|
||||
control: "text",
|
||||
description: "The user's handle/username",
|
||||
},
|
||||
bio: {
|
||||
control: "text",
|
||||
description: "User's biography text",
|
||||
},
|
||||
profileImage: {
|
||||
control: "text",
|
||||
description: "URL of the user's profile image",
|
||||
},
|
||||
links: {
|
||||
profile: {
|
||||
control: "object",
|
||||
description: "Array of social media links",
|
||||
},
|
||||
categories: {
|
||||
control: "object",
|
||||
description: "Array of selected categories",
|
||||
description: "The profile details of the user",
|
||||
displayName: {
|
||||
control: "text",
|
||||
description: "The display name of the user",
|
||||
},
|
||||
handle: {
|
||||
control: "text",
|
||||
description: "The user's handle/username",
|
||||
},
|
||||
bio: {
|
||||
control: "text",
|
||||
description: "User's biography text",
|
||||
},
|
||||
profileImage: {
|
||||
control: "text",
|
||||
description: "URL of the user's profile image",
|
||||
},
|
||||
links: {
|
||||
control: "object",
|
||||
description: "Array of social media links",
|
||||
},
|
||||
categories: {
|
||||
control: "object",
|
||||
description: "Array of selected categories",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -41,30 +45,35 @@ type Story = StoryObj<typeof ProfileInfoForm>;
|
|||
|
||||
export const Empty: Story = {
|
||||
args: {
|
||||
displayName: "",
|
||||
handle: "",
|
||||
bio: "",
|
||||
profileImage: undefined,
|
||||
links: [],
|
||||
categories: [],
|
||||
profile: {
|
||||
name: "",
|
||||
username: "",
|
||||
description: "",
|
||||
avatar_url: "",
|
||||
links: [],
|
||||
top_categories: [],
|
||||
agent_rating: 0,
|
||||
agent_runs: 0,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const Filled: Story = {
|
||||
args: {
|
||||
displayName: "Olivia Grace",
|
||||
handle: "@ograce1421",
|
||||
bio: "Our agents are designed to bring happiness and positive vibes to your daily routine. Each template helps you create and live more efficiently.",
|
||||
profileImage: "https://via.placeholder.com/130x130",
|
||||
links: [
|
||||
{ id: 1, url: "www.websitelink.com" },
|
||||
{ id: 2, url: "twitter.com/oliviagrace" },
|
||||
{ id: 3, url: "github.com/ograce" },
|
||||
],
|
||||
categories: [
|
||||
{ id: 1, name: "Entertainment" },
|
||||
{ id: 2, name: "Blog" },
|
||||
{ id: 3, name: "Content creation" },
|
||||
],
|
||||
profile: {
|
||||
name: "Olivia Grace",
|
||||
username: "@ograce1421",
|
||||
description:
|
||||
"Our agents are designed to bring happiness and positive vibes to your daily routine. Each template helps you create and live more efficiently.",
|
||||
avatar_url: "https://via.placeholder.com/130x130",
|
||||
links: [
|
||||
"www.websitelink.com",
|
||||
"twitter.com/oliviagrace",
|
||||
"github.com/ograce",
|
||||
],
|
||||
top_categories: ["Entertainment", "Blog", "Content creation"],
|
||||
agent_rating: 4.5,
|
||||
agent_runs: 100,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import { PublishAgentSelect } from "./PublishAgentSelect";
|
||||
import { Agent, PublishAgentSelect } from "./PublishAgentSelect";
|
||||
|
||||
const meta: Meta<typeof PublishAgentSelect> = {
|
||||
title: "AGPT UI/Publish Agent Select",
|
||||
|
@ -10,51 +10,69 @@ const meta: Meta<typeof PublishAgentSelect> = {
|
|||
export default meta;
|
||||
type Story = StoryObj<typeof PublishAgentSelect>;
|
||||
|
||||
const mockAgents = [
|
||||
const mockAgents: Agent[] = [
|
||||
{
|
||||
name: "SEO Optimizer",
|
||||
lastEdited: "2 days ago",
|
||||
imageSrc: "https://picsum.photos/seed/seo/300/200",
|
||||
id: "1",
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
name: "Content Writer",
|
||||
lastEdited: "5 days ago",
|
||||
imageSrc: "https://picsum.photos/seed/writer/300/200",
|
||||
id: "1",
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
name: "Data Analyzer",
|
||||
lastEdited: "1 week ago",
|
||||
imageSrc: "https://picsum.photos/seed/data/300/200",
|
||||
id: "1",
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
name: "Image Recognition",
|
||||
lastEdited: "2 weeks ago",
|
||||
imageSrc: "https://picsum.photos/seed/image/300/200",
|
||||
id: "1",
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
name: "Chatbot Assistant",
|
||||
lastEdited: "3 weeks ago",
|
||||
imageSrc: "https://picsum.photos/seed/chat/300/200",
|
||||
id: "1",
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
name: "Code Generator",
|
||||
lastEdited: "1 month ago",
|
||||
imageSrc: "https://picsum.photos/seed/code/300/200",
|
||||
id: "1",
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
name: "AI Translator",
|
||||
lastEdited: "6 weeks ago",
|
||||
imageSrc: "https://picsum.photos/seed/translate/300/200",
|
||||
id: "1",
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
name: "Voice Assistant",
|
||||
lastEdited: "2 months ago",
|
||||
imageSrc: "https://picsum.photos/seed/voice/300/200",
|
||||
id: "1",
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
name: "Data Visualizer",
|
||||
lastEdited: "3 months ago",
|
||||
imageSrc: "https://picsum.photos/seed/visualize/300/200",
|
||||
id: "1",
|
||||
version: 1,
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@ export const Filled: Story = {
|
|||
args: {
|
||||
...Default.args,
|
||||
initialData: {
|
||||
agent_id: "1",
|
||||
slug: "super-seo-optimizer",
|
||||
title: "Super SEO Optimizer",
|
||||
subheader: "Boost your website's search engine rankings",
|
||||
thumbnailSrc: "https://picsum.photos/seed/seo/500/350",
|
||||
|
@ -44,6 +46,8 @@ export const ThreeImages: Story = {
|
|||
args: {
|
||||
...Default.args,
|
||||
initialData: {
|
||||
agent_id: "1",
|
||||
slug: "super-seo-optimizer",
|
||||
title: "Multi-Image Agent",
|
||||
subheader: "Showcasing multiple images",
|
||||
thumbnailSrc: "https://picsum.photos/seed/initial/500/350",
|
||||
|
@ -63,6 +67,8 @@ export const SixImages: Story = {
|
|||
args: {
|
||||
...Default.args,
|
||||
initialData: {
|
||||
agent_id: "1",
|
||||
slug: "super-seo-optimizer",
|
||||
title: "Gallery Agent",
|
||||
subheader: "Showcasing a gallery of images",
|
||||
thumbnailSrc: "https://picsum.photos/seed/gallery1/500/350",
|
||||
|
|
|
@ -6,6 +6,18 @@ import { Button } from "../agptui/Button";
|
|||
import { IconClose, IconPlus } from "../ui/icons";
|
||||
import BackendAPI from "@/lib/autogpt-server-api";
|
||||
|
||||
export interface PublishAgentInfoInitialData {
|
||||
agent_id: string;
|
||||
title: string;
|
||||
subheader: string;
|
||||
slug: string;
|
||||
thumbnailSrc: string;
|
||||
youtubeLink: string;
|
||||
category: string;
|
||||
description: string;
|
||||
additionalImages?: string[];
|
||||
}
|
||||
|
||||
interface PublishAgentInfoProps {
|
||||
onBack: () => void;
|
||||
onSubmit: (
|
||||
|
@ -18,17 +30,7 @@ interface PublishAgentInfoProps {
|
|||
categories: string[],
|
||||
) => void;
|
||||
onClose: () => void;
|
||||
initialData?: {
|
||||
agent_id: string;
|
||||
title: string;
|
||||
subheader: string;
|
||||
slug: string;
|
||||
thumbnailSrc: string;
|
||||
youtubeLink: string;
|
||||
category: string;
|
||||
description: string;
|
||||
additionalImages?: string[];
|
||||
};
|
||||
initialData?: PublishAgentInfoInitialData;
|
||||
}
|
||||
|
||||
export const PublishAgentInfo: React.FC<PublishAgentInfoProps> = ({
|
||||
|
|
|
@ -16,29 +16,32 @@ type Story = StoryObj<typeof meta>;
|
|||
export const Default: Story = {
|
||||
args: {
|
||||
agentName: "Test Agent",
|
||||
onSubmit: (rating) => {
|
||||
console.log("Rating submitted:", rating);
|
||||
},
|
||||
onClose: () => {
|
||||
console.log("Rating card closed");
|
||||
},
|
||||
// onSubmit: (rating) => {
|
||||
// console.log("Rating submitted:", rating);
|
||||
// },
|
||||
// onClose: () => {
|
||||
// console.log("Rating card closed");
|
||||
// },
|
||||
storeListingVersionId: "1",
|
||||
},
|
||||
};
|
||||
|
||||
export const LongAgentName: Story = {
|
||||
args: {
|
||||
agentName: "Very Long Agent Name That Might Need Special Handling",
|
||||
onSubmit: (rating) => {
|
||||
console.log("Rating submitted:", rating);
|
||||
},
|
||||
onClose: () => {
|
||||
console.log("Rating card closed");
|
||||
},
|
||||
// onSubmit: (rating) => {
|
||||
// console.log("Rating submitted:", rating);
|
||||
// },
|
||||
// onClose: () => {
|
||||
// console.log("Rating card closed");
|
||||
// },
|
||||
storeListingVersionId: "1",
|
||||
},
|
||||
};
|
||||
|
||||
export const WithoutCallbacks: Story = {
|
||||
args: {
|
||||
agentName: "Test Agent",
|
||||
storeListingVersionId: "1",
|
||||
},
|
||||
};
|
||||
|
|
|
@ -44,6 +44,9 @@ export const Rejected: Story = {
|
|||
};
|
||||
|
||||
export const AllStatuses: Story = {
|
||||
args: {
|
||||
status: "draft" as StatusType,
|
||||
},
|
||||
render: () => (
|
||||
<div className="flex flex-col gap-4">
|
||||
<Status status="draft" />
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import { AgentsSection } from "./AgentsSection";
|
||||
import { Agent, AgentsSection } from "./AgentsSection";
|
||||
import { userEvent, within, expect } from "@storybook/test";
|
||||
|
||||
const meta = {
|
||||
|
@ -16,7 +16,7 @@ const meta = {
|
|||
argTypes: {
|
||||
sectionTitle: { control: "text" },
|
||||
agents: { control: "object" },
|
||||
onCardClick: { action: "clicked" },
|
||||
// onCardClick: { action: "clicked" },
|
||||
},
|
||||
} satisfies Meta<typeof AgentsSection>;
|
||||
|
||||
|
@ -25,41 +25,50 @@ type Story = StoryObj<typeof meta>;
|
|||
|
||||
const mockTopAgents = [
|
||||
{
|
||||
agentName: "SEO Optimizer Pro",
|
||||
agentImage:
|
||||
agent_name: "SEO Optimizer Pro",
|
||||
agent_image:
|
||||
"https://framerusercontent.com/images/KCIpxr9f97EGJgpaoqnjKsrOPwI.jpg",
|
||||
description:
|
||||
"Boost your website's search engine rankings with our advanced AI-powered SEO optimization tool.",
|
||||
runs: 50000,
|
||||
rating: 4.7,
|
||||
avatarSrc: "https://example.com/avatar1.jpg",
|
||||
creator_avatar: "https://example.com/avatar1.jpg",
|
||||
slug: "seo-optimizer-pro",
|
||||
creator: "John Doe",
|
||||
sub_heading: "SEO Expert",
|
||||
},
|
||||
{
|
||||
agentName: "Content Writer AI",
|
||||
agentImage:
|
||||
agent_name: "Content Writer AI",
|
||||
agent_image:
|
||||
"https://upload.wikimedia.org/wikipedia/commons/c/c5/Big_buck_bunny_poster_big.jpg",
|
||||
description:
|
||||
"Generate high-quality, engaging content for your blog, social media, or marketing campaigns.",
|
||||
runs: 75000,
|
||||
rating: 4.5,
|
||||
avatarSrc: "https://example.com/avatar2.jpg",
|
||||
creator_avatar: "https://example.com/avatar2.jpg",
|
||||
slug: "content-writer-ai",
|
||||
creator: "Jane Doe",
|
||||
sub_heading: "Content Writer",
|
||||
},
|
||||
{
|
||||
agentName: "Data Analyzer Lite",
|
||||
agentImage:
|
||||
agent_name: "Data Analyzer Lite",
|
||||
agent_image:
|
||||
"https://framerusercontent.com/images/KCIpxr9f97EGJgpaoqnjKsrOPwI.jpg",
|
||||
description: "A basic tool for analyzing small to medium-sized datasets.",
|
||||
runs: 10000,
|
||||
rating: 3.8,
|
||||
avatarSrc: "https://example.com/avatar3.jpg",
|
||||
creator_avatar: "https://example.com/avatar3.jpg",
|
||||
slug: "data-analyzer-lite",
|
||||
creator: "John Doe",
|
||||
sub_heading: "Data Analyst",
|
||||
},
|
||||
];
|
||||
] satisfies Agent[];
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
sectionTitle: "Top Agents",
|
||||
agents: mockTopAgents,
|
||||
onCardClick: (agentName: string) => console.log(`Clicked on ${agentName}`),
|
||||
// onCardClick: (agentName: string) => console.log(`Clicked on ${agentName}`),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -67,7 +76,7 @@ export const SingleAgent: Story = {
|
|||
args: {
|
||||
sectionTitle: "Top Agents",
|
||||
agents: [mockTopAgents[0]],
|
||||
onCardClick: (agentName: string) => console.log(`Clicked on ${agentName}`),
|
||||
// onCardClick: (agentName: string) => console.log(`Clicked on ${agentName}`),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -75,7 +84,7 @@ export const NoAgents: Story = {
|
|||
args: {
|
||||
sectionTitle: "Top Agents",
|
||||
agents: [],
|
||||
onCardClick: (agentName: string) => console.log(`Clicked on ${agentName}`),
|
||||
// onCardClick: (agentName: string) => console.log(`Clicked on ${agentName}`),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -83,7 +92,7 @@ export const WithInteraction: Story = {
|
|||
args: {
|
||||
sectionTitle: "Top Agents",
|
||||
agents: mockTopAgents,
|
||||
onCardClick: (agentName: string) => console.log(`Clicked on ${agentName}`),
|
||||
// onCardClick: (agentName: string) => console.log(`Clicked on ${agentName}`),
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
@ -107,6 +116,9 @@ export const MultiRowAgents: Story = {
|
|||
runs: 60000,
|
||||
rating: 4.6,
|
||||
creator_avatar: "https://example.com/avatar4.jpg",
|
||||
slug: "image-recognition-ai",
|
||||
creator: "John Doe",
|
||||
sub_heading: "Image Recognition",
|
||||
},
|
||||
{
|
||||
agent_name: "Natural Language Processor",
|
||||
|
@ -117,6 +129,9 @@ export const MultiRowAgents: Story = {
|
|||
runs: 80000,
|
||||
rating: 4.8,
|
||||
creator_avatar: "https://example.com/avatar5.jpg",
|
||||
slug: "natural-language-processor",
|
||||
creator: "John Doe",
|
||||
sub_heading: "Natural Language Processing",
|
||||
},
|
||||
{
|
||||
agent_name: "Sentiment Analyzer",
|
||||
|
@ -127,6 +142,9 @@ export const MultiRowAgents: Story = {
|
|||
runs: 45000,
|
||||
rating: 4.3,
|
||||
creator_avatar: "https://example.com/avatar6.jpg",
|
||||
slug: "sentiment-analyzer",
|
||||
creator: "John Doe",
|
||||
sub_heading: "Sentiment Analysis",
|
||||
},
|
||||
{
|
||||
agent_name: "Chatbot Builder",
|
||||
|
@ -137,6 +155,9 @@ export const MultiRowAgents: Story = {
|
|||
runs: 55000,
|
||||
rating: 4.4,
|
||||
creator_avatar: "https://example.com/avatar7.jpg",
|
||||
slug: "chatbot-builder",
|
||||
creator: "John Doe",
|
||||
sub_heading: "Chatbot Developer",
|
||||
},
|
||||
{
|
||||
agent_name: "Predictive Analytics Tool",
|
||||
|
@ -147,6 +168,9 @@ export const MultiRowAgents: Story = {
|
|||
runs: 40000,
|
||||
rating: 4.2,
|
||||
creator_avatar: "https://example.com/avatar8.jpg",
|
||||
slug: "predictive-analytics-tool",
|
||||
creator: "John Doe",
|
||||
sub_heading: "Predictive Analytics",
|
||||
},
|
||||
{
|
||||
agent_name: "Text-to-Speech Converter",
|
||||
|
@ -157,9 +181,12 @@ export const MultiRowAgents: Story = {
|
|||
runs: 35000,
|
||||
rating: 4.1,
|
||||
creator_avatar: "https://example.com/avatar9.jpg",
|
||||
slug: "text-to-speech-converter",
|
||||
creator: "John Doe",
|
||||
sub_heading: "Text-to-Speech",
|
||||
},
|
||||
],
|
||||
onCardClick: (agentName: string) => console.log(`Clicked on ${agentName}`),
|
||||
// onCardClick: (agentName: string) => console.log(`Clicked on ${agentName}`),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import {
|
|||
CarouselItem,
|
||||
} from "@/components/ui/carousel";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export interface Agent {
|
||||
slug: string;
|
||||
|
|
|
@ -15,7 +15,7 @@ const meta = {
|
|||
tags: ["autodocs"],
|
||||
argTypes: {
|
||||
featuredCreators: { control: "object" },
|
||||
onCardClick: { action: "cardClicked" },
|
||||
// onCardClick: { action: "cardClicked" },
|
||||
},
|
||||
} satisfies Meta<typeof FeaturedCreators>;
|
||||
|
||||
|
@ -64,14 +64,14 @@ const defaultCreators = [
|
|||
export const Default: Story = {
|
||||
args: {
|
||||
featuredCreators: defaultCreators,
|
||||
onCardClick: (creatorName) => console.log(`Clicked on ${creatorName}`),
|
||||
// onCardClick: (creatorName) => console.log(`Clicked on ${creatorName}`),
|
||||
},
|
||||
};
|
||||
|
||||
export const SingleCreator: Story = {
|
||||
args: {
|
||||
featuredCreators: [defaultCreators[0]],
|
||||
onCardClick: (creatorName) => console.log(`Clicked on ${creatorName}`),
|
||||
// onCardClick: (creatorName) => console.log(`Clicked on ${creatorName}`),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -98,14 +98,14 @@ export const ManyCreators: Story = {
|
|||
num_agents: 25,
|
||||
},
|
||||
],
|
||||
onCardClick: (creatorName) => console.log(`Clicked on ${creatorName}`),
|
||||
// onCardClick: (creatorName) => console.log(`Clicked on ${creatorName}`),
|
||||
},
|
||||
};
|
||||
|
||||
export const WithInteraction: Story = {
|
||||
args: {
|
||||
featuredCreators: defaultCreators,
|
||||
onCardClick: (creatorName) => console.log(`Clicked on ${creatorName}`),
|
||||
// onCardClick: (creatorName) => console.log(`Clicked on ${creatorName}`),
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import { FeaturedSection } from "./FeaturedSection";
|
||||
import { FeaturedAgent, FeaturedSection } from "./FeaturedSection";
|
||||
import { userEvent, within, expect } from "@storybook/test";
|
||||
|
||||
const meta = {
|
||||
|
@ -15,7 +15,7 @@ const meta = {
|
|||
tags: ["autodocs"],
|
||||
argTypes: {
|
||||
featuredAgents: { control: "object" },
|
||||
onCardClick: { action: "clicked" },
|
||||
// onCardClick: { action: "clicked" },
|
||||
},
|
||||
} satisfies Meta<typeof FeaturedSection>;
|
||||
|
||||
|
@ -24,97 +24,102 @@ type Story = StoryObj<typeof meta>;
|
|||
|
||||
const mockFeaturedAgents = [
|
||||
{
|
||||
agentName: "Personalized Morning Coffee Newsletter example of three lines",
|
||||
subHeading:
|
||||
agent_name: "Personalized Morning Coffee Newsletter example of three lines",
|
||||
sub_heading:
|
||||
"Transform ideas into breathtaking images with this AI-powered Image Generator.",
|
||||
creatorName: "AI Solutions Inc.",
|
||||
creator: "AI Solutions Inc.",
|
||||
description:
|
||||
"Elevate your web content with this powerful AI Webpage Copy Improver. Designed for marketers, SEO specialists, and web developers, this tool analyses and enhances website copy for maximum impact. Using advanced language models, it optimizes text for better clarity, SEO performance, and increased conversion rates.",
|
||||
runs: 50000,
|
||||
rating: 4.7,
|
||||
agentImage:
|
||||
agent_image:
|
||||
"https://framerusercontent.com/images/KCIpxr9f97EGJgpaoqnjKsrOPwI.jpg",
|
||||
creatorImage:
|
||||
creator_avatar:
|
||||
"https://framerusercontent.com/images/KCIpxr9f97EGJgpaoqnjKsrOPwI.jpg",
|
||||
slug: "personalized-morning-coffee-newsletter",
|
||||
},
|
||||
{
|
||||
agentName: "Data Analyzer Lite",
|
||||
subHeading: "Basic data analysis tool",
|
||||
creatorName: "DataTech",
|
||||
agent_name: "Data Analyzer Lite",
|
||||
sub_heading: "Basic data analysis tool",
|
||||
creator: "DataTech",
|
||||
description:
|
||||
"A lightweight data analysis tool for basic data processing needs.",
|
||||
runs: 10000,
|
||||
rating: 2.8,
|
||||
agentImage:
|
||||
agent_image:
|
||||
"https://framerusercontent.com/images/KCIpxr9f97EGJgpaoqnjKsrOPwI.jpg",
|
||||
creatorImage:
|
||||
creator_avatar:
|
||||
"https://framerusercontent.com/images/KCIpxr9f97EGJgpaoqnjKsrOPwI.jpg",
|
||||
slug: "data-analyzer-lite",
|
||||
},
|
||||
{
|
||||
agentName: "CodeAssist AI",
|
||||
subHeading: "Your AI coding companion",
|
||||
creatorName: "DevTools Co.",
|
||||
agent_name: "CodeAssist AI",
|
||||
sub_heading: "Your AI coding companion",
|
||||
creator: "DevTools Co.",
|
||||
description:
|
||||
"An intelligent coding assistant that helps developers write better code faster.",
|
||||
runs: 1000000,
|
||||
rating: 4.9,
|
||||
agentImage:
|
||||
agent_image:
|
||||
"https://framerusercontent.com/images/KCIpxr9f97EGJgpaoqnjKsrOPwI.jpg",
|
||||
creatorImage:
|
||||
creator_avatar:
|
||||
"https://framerusercontent.com/images/KCIpxr9f97EGJgpaoqnjKsrOPwI.jpg",
|
||||
slug: "codeassist-ai",
|
||||
},
|
||||
{
|
||||
agentName: "MultiTasker",
|
||||
subHeading: "All-in-one productivity suite",
|
||||
creatorName: "Productivity Plus",
|
||||
agent_name: "MultiTasker",
|
||||
sub_heading: "All-in-one productivity suite",
|
||||
creator: "Productivity Plus",
|
||||
description:
|
||||
"A comprehensive productivity suite that combines task management, note-taking, and project planning into one seamless interface. Features include smart task prioritization, automated scheduling, and AI-powered insights to help you work more efficiently.",
|
||||
runs: 75000,
|
||||
rating: 4.5,
|
||||
agentImage:
|
||||
agent_image:
|
||||
"https://framerusercontent.com/images/KCIpxr9f97EGJgpaoqnjKsrOPwI.jpg",
|
||||
creatorImage:
|
||||
creator_avatar:
|
||||
"https://framerusercontent.com/images/KCIpxr9f97EGJgpaoqnjKsrOPwI.jpg",
|
||||
slug: "multitasker",
|
||||
},
|
||||
{
|
||||
agentName: "QuickTask",
|
||||
subHeading: "Fast task automation",
|
||||
creatorName: "EfficientWorks",
|
||||
agent_name: "QuickTask",
|
||||
sub_heading: "Fast task automation",
|
||||
creator: "EfficientWorks",
|
||||
description: "Simple and efficient task automation tool.",
|
||||
runs: 50000,
|
||||
rating: 4.2,
|
||||
agentImage:
|
||||
agent_image:
|
||||
"https://framerusercontent.com/images/KCIpxr9f97EGJgpaoqnjKsrOPwI.jpg",
|
||||
creatorImage:
|
||||
creator_avatar:
|
||||
"https://framerusercontent.com/images/KCIpxr9f97EGJgpaoqnjKsrOPwI.jpg",
|
||||
slug: "quicktask",
|
||||
},
|
||||
];
|
||||
] satisfies FeaturedAgent[];
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
featuredAgents: mockFeaturedAgents,
|
||||
onCardClick: (agentName: string) => console.log(`Clicked on ${agentName}`),
|
||||
// onCardClick: (agentName: string) => console.log(`Clicked on ${agentName}`),
|
||||
},
|
||||
};
|
||||
|
||||
export const SingleAgent: Story = {
|
||||
args: {
|
||||
featuredAgents: [mockFeaturedAgents[0]],
|
||||
onCardClick: (agentName: string) => console.log(`Clicked on ${agentName}`),
|
||||
// onCardClick: (agentName: string) => console.log(`Clicked on ${agentName}`),
|
||||
},
|
||||
};
|
||||
|
||||
export const NoAgents: Story = {
|
||||
args: {
|
||||
featuredAgents: [],
|
||||
onCardClick: (agentName: string) => console.log(`Clicked on ${agentName}`),
|
||||
// onCardClick: (agentName: string) => console.log(`Clicked on ${agentName}`),
|
||||
},
|
||||
};
|
||||
|
||||
export const WithInteraction: Story = {
|
||||
args: {
|
||||
featuredAgents: mockFeaturedAgents,
|
||||
onCardClick: (agentName: string) => console.log(`Clicked on ${agentName}`),
|
||||
// onCardClick: (agentName: string) => console.log(`Clicked on ${agentName}`),
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
|
|
@ -8,7 +8,10 @@ import {
|
|||
PopoverAnchor,
|
||||
} from "@/components/ui/popover";
|
||||
import { PublishAgentSelect } from "../PublishAgentSelect";
|
||||
import { PublishAgentInfo } from "../PublishAgentSelectInfo";
|
||||
import {
|
||||
PublishAgentInfo,
|
||||
PublishAgentInfoInitialData,
|
||||
} from "../PublishAgentSelectInfo";
|
||||
import { PublishAgentAwaitingReview } from "../PublishAgentAwaitingReview";
|
||||
import { Button } from "../Button";
|
||||
import {
|
||||
|
@ -45,17 +48,17 @@ export const PublishAgentPopout: React.FC<PublishAgentPopoutProps> = ({
|
|||
);
|
||||
const [myAgents, setMyAgents] = React.useState<MyAgentsResponse | null>(null);
|
||||
const [selectedAgent, setSelectedAgent] = React.useState<string | null>(null);
|
||||
const [initialData, setInitialData] = React.useState<{
|
||||
agent_id: string;
|
||||
title: string;
|
||||
subheader: string;
|
||||
slug: string;
|
||||
thumbnailSrc: string;
|
||||
youtubeLink: string;
|
||||
category: string;
|
||||
description: string;
|
||||
additionalImages?: string[];
|
||||
} | null>(null);
|
||||
const [initialData, setInitialData] =
|
||||
React.useState<PublishAgentInfoInitialData>({
|
||||
agent_id: "",
|
||||
title: "",
|
||||
subheader: "",
|
||||
slug: "",
|
||||
thumbnailSrc: "",
|
||||
youtubeLink: "",
|
||||
category: "",
|
||||
description: "",
|
||||
});
|
||||
const [publishData, setPublishData] =
|
||||
React.useState<StoreSubmissionRequest>(submissionData);
|
||||
const [selectedAgentId, setSelectedAgentId] = React.useState<string | null>(
|
||||
|
|
|
@ -2,16 +2,14 @@ import { LDProvider } from "launchdarkly-react-client-sdk";
|
|||
import { ReactNode } from "react";
|
||||
|
||||
export function LaunchDarklyProvider({ children }: { children: ReactNode }) {
|
||||
if (
|
||||
process.env.NEXT_PUBLIC_LAUNCHDARKLY_ENABLED === true &&
|
||||
!process.env.NEXT_PUBLIC_LAUNCHDARKLY_CLIENT_ID
|
||||
) {
|
||||
const clientId = process.env.NEXT_PUBLIC_LAUNCHDARKLY_CLIENT_ID;
|
||||
const enabled = process.env.NEXT_PUBLIC_LAUNCHDARKLY_ENABLED === "true";
|
||||
|
||||
if (!enabled) return <>{children}</>;
|
||||
|
||||
if (!clientId) {
|
||||
throw new Error("NEXT_PUBLIC_LAUNCHDARKLY_CLIENT_ID is not defined");
|
||||
}
|
||||
|
||||
return (
|
||||
<LDProvider clientSideID={process.env.NEXT_PUBLIC_LAUNCHDARKLY_CLIENT_ID}>
|
||||
{children}
|
||||
</LDProvider>
|
||||
);
|
||||
return <LDProvider clientSideID={clientId}>{children}</LDProvider>;
|
||||
}
|
||||
|
|
|
@ -41,7 +41,6 @@ import { LocalValuedInput } from "./ui/input";
|
|||
import NodeHandle from "./NodeHandle";
|
||||
import { ConnectionData } from "./CustomNode";
|
||||
import { CredentialsInput } from "./integrations/credentials-input";
|
||||
import { MultiSelect } from "./ui/multiselect-input";
|
||||
|
||||
type NodeObjectInputTreeProps = {
|
||||
nodeId: string;
|
||||
|
@ -663,20 +662,6 @@ export const NodeGenericInputField: FC<{
|
|||
handleInputClick={handleInputClick}
|
||||
/>
|
||||
);
|
||||
case "object":
|
||||
return (
|
||||
<NodeKeyValueInput
|
||||
nodeId={nodeId}
|
||||
selfKey={propKey}
|
||||
schema={propSchema}
|
||||
entries={currentValue}
|
||||
errors={errors}
|
||||
className={className}
|
||||
displayName={displayName}
|
||||
connections={connections}
|
||||
handleInputChange={handleInputChange}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
console.warn(
|
||||
`Schema for '${propKey}' specifies unknown type:`,
|
||||
|
@ -968,10 +953,8 @@ const NodeKeyValueInput: FC<{
|
|||
>
|
||||
<div>
|
||||
{keyValuePairs.map(({ key, value }, index) => (
|
||||
/*
|
||||
The `index` is used as a DOM key instead of the actual `key`
|
||||
because the `key` can change with each input, causing the input to lose focus.
|
||||
*/
|
||||
// The `index` is used as a DOM key instead of the actual `key`
|
||||
// because the `key` can change with each input, causing the input to lose focus.
|
||||
<div key={index}>
|
||||
<NodeHandle
|
||||
keyName={getEntryKey(key)}
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
import React from "react";
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import {
|
||||
FieldValues,
|
||||
InternalFieldName,
|
||||
RegisterOptions,
|
||||
useForm,
|
||||
UseFormHandleSubmit,
|
||||
UseFormRegister,
|
||||
UseFormWatch,
|
||||
} from "react-hook-form";
|
||||
import { z } from "zod";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
|
||||
|
@ -72,10 +80,300 @@ const FormExample = () => {
|
|||
};
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
children: <FormExample />,
|
||||
// watch(callback: (data, { name, type }) => void, defaultValues?: {[key:string]: unknown}): { unsubscribe: () => void }
|
||||
watch: (name?: any, defaultValue?: any) => {
|
||||
if (typeof name === "function") {
|
||||
return { unsubscribe: () => {} };
|
||||
}
|
||||
return defaultValue || {};
|
||||
},
|
||||
getValues: () => [],
|
||||
getFieldState: (name, formState) => ({
|
||||
invalid: false,
|
||||
isDirty: false,
|
||||
isTouched: false,
|
||||
isValidating: false,
|
||||
error: undefined,
|
||||
}),
|
||||
setError: () => {},
|
||||
setValue: () => {},
|
||||
trigger: async () => true,
|
||||
reset: () => {},
|
||||
clearErrors: () => {},
|
||||
formState: {
|
||||
errors: {},
|
||||
isDirty: false,
|
||||
isSubmitting: false,
|
||||
isValid: true,
|
||||
isLoading: false,
|
||||
isSubmitted: false,
|
||||
isSubmitSuccessful: false,
|
||||
isValidating: false,
|
||||
defaultValues: {},
|
||||
dirtyFields: {},
|
||||
touchedFields: {},
|
||||
disabled: false,
|
||||
submitCount: 0,
|
||||
validatingFields: {},
|
||||
},
|
||||
resetField: () => {},
|
||||
handleSubmit: (() => {
|
||||
return async (e?: React.BaseSyntheticEvent) => {
|
||||
e?.preventDefault();
|
||||
return Promise.resolve();
|
||||
};
|
||||
}) as unknown as UseFormHandleSubmit<any>,
|
||||
unregister: () => {},
|
||||
control: {
|
||||
_subjects: {
|
||||
state: {
|
||||
observers: [],
|
||||
subscribe: () => ({ unsubscribe: () => {} }),
|
||||
unsubscribe: () => {},
|
||||
next: () => {},
|
||||
},
|
||||
array: {
|
||||
observers: [],
|
||||
subscribe: () => ({ unsubscribe: () => {} }),
|
||||
unsubscribe: () => {},
|
||||
next: () => {},
|
||||
},
|
||||
values: {
|
||||
observers: [],
|
||||
subscribe: () => ({ unsubscribe: () => {} }),
|
||||
unsubscribe: () => {},
|
||||
next: () => {},
|
||||
},
|
||||
},
|
||||
_reset: () => {},
|
||||
_resetDefaultValues: () => {},
|
||||
_getFieldArray: () => [],
|
||||
_setErrors: () => {},
|
||||
_updateDisabledField: () => {},
|
||||
_executeSchema: () => Promise.resolve({ errors: {} }),
|
||||
handleSubmit: (onSubmit?: any) => (e?: React.BaseSyntheticEvent) => {
|
||||
e?.preventDefault();
|
||||
return Promise.resolve();
|
||||
},
|
||||
unregister: () => {},
|
||||
getFieldState: () => ({
|
||||
invalid: false,
|
||||
isDirty: false,
|
||||
isTouched: false,
|
||||
isValidating: false,
|
||||
error: undefined,
|
||||
}),
|
||||
setError: () => {},
|
||||
_disableForm: () => {},
|
||||
_removeUnmounted: () => {},
|
||||
_names: {
|
||||
mount: new Set(),
|
||||
array: new Set(),
|
||||
watch: new Set(),
|
||||
unMount: new Set(),
|
||||
disabled: new Set(),
|
||||
},
|
||||
_state: { mount: false, watch: false, action: false },
|
||||
_options: { mode: "onSubmit", defaultValues: {} },
|
||||
_formState: {
|
||||
isDirty: false,
|
||||
isSubmitted: false,
|
||||
submitCount: 0,
|
||||
isLoading: false,
|
||||
isSubmitSuccessful: false,
|
||||
isSubmitting: false,
|
||||
isValidating: false,
|
||||
isValid: true,
|
||||
disabled: false,
|
||||
dirtyFields: {},
|
||||
touchedFields: {},
|
||||
errors: {},
|
||||
validatingFields: {},
|
||||
},
|
||||
_fields: {},
|
||||
|
||||
_defaultValues: {},
|
||||
_formValues: {},
|
||||
_proxyFormState: {
|
||||
isDirty: false,
|
||||
dirtyFields: false,
|
||||
touchedFields: false,
|
||||
errors: false,
|
||||
isValid: true,
|
||||
isValidating: false,
|
||||
validatingFields: false,
|
||||
},
|
||||
_getDirty: () => false,
|
||||
_updateValid: () => {},
|
||||
_updateFieldArray: () => {},
|
||||
_getWatch: () => ({}),
|
||||
_updateFormState: () => {},
|
||||
register: ((name: string, options?: RegisterOptions<any>) => ({
|
||||
name,
|
||||
onChange: (e: any) => Promise.resolve(),
|
||||
onBlur: (e: any) => Promise.resolve(),
|
||||
ref: () => {},
|
||||
})) as unknown as UseFormRegister<any>,
|
||||
},
|
||||
register: ((name: string) => ({
|
||||
name,
|
||||
onChange: (e: any) => Promise.resolve(),
|
||||
onBlur: (e: any) => Promise.resolve(),
|
||||
ref: () => {},
|
||||
})) as UseFormRegister<FieldValues>,
|
||||
setFocus: () => {},
|
||||
},
|
||||
render: () => <FormExample />,
|
||||
};
|
||||
|
||||
export const WithError: Story = {
|
||||
args: {
|
||||
children: <FormExample />,
|
||||
// watch(callback: (data, { name, type }) => void, defaultValues?: {[key:string]: unknown}): { unsubscribe: () => void }
|
||||
watch: (name?: any, defaultValue?: any) => {
|
||||
if (typeof name === "function") {
|
||||
return { unsubscribe: () => {} };
|
||||
}
|
||||
return defaultValue || {};
|
||||
},
|
||||
getValues: () => [],
|
||||
getFieldState: (name, formState) => ({
|
||||
invalid: false,
|
||||
isDirty: false,
|
||||
isTouched: false,
|
||||
isValidating: false,
|
||||
error: undefined,
|
||||
}),
|
||||
setError: () => {},
|
||||
setValue: () => {},
|
||||
trigger: async () => true,
|
||||
reset: () => {},
|
||||
clearErrors: () => {},
|
||||
formState: {
|
||||
errors: {},
|
||||
isDirty: false,
|
||||
isSubmitting: false,
|
||||
isValid: true,
|
||||
isLoading: false,
|
||||
isSubmitted: false,
|
||||
isSubmitSuccessful: false,
|
||||
isValidating: false,
|
||||
defaultValues: {},
|
||||
dirtyFields: {},
|
||||
touchedFields: {},
|
||||
disabled: false,
|
||||
submitCount: 0,
|
||||
validatingFields: {},
|
||||
},
|
||||
resetField: () => {},
|
||||
handleSubmit: (() => {
|
||||
return async (e?: React.BaseSyntheticEvent) => {
|
||||
e?.preventDefault();
|
||||
return Promise.resolve();
|
||||
};
|
||||
}) as unknown as UseFormHandleSubmit<any>,
|
||||
unregister: () => {},
|
||||
control: {
|
||||
_subjects: {
|
||||
state: {
|
||||
observers: [],
|
||||
subscribe: () => ({ unsubscribe: () => {} }),
|
||||
unsubscribe: () => {},
|
||||
next: () => {},
|
||||
},
|
||||
array: {
|
||||
observers: [],
|
||||
subscribe: () => ({ unsubscribe: () => {} }),
|
||||
unsubscribe: () => {},
|
||||
next: () => {},
|
||||
},
|
||||
values: {
|
||||
observers: [],
|
||||
subscribe: () => ({ unsubscribe: () => {} }),
|
||||
unsubscribe: () => {},
|
||||
next: () => {},
|
||||
},
|
||||
},
|
||||
_reset: () => {},
|
||||
_resetDefaultValues: () => {},
|
||||
_getFieldArray: () => [],
|
||||
_setErrors: () => {},
|
||||
_updateDisabledField: () => {},
|
||||
_executeSchema: () => Promise.resolve({ errors: {} }),
|
||||
handleSubmit: (onSubmit?: any) => (e?: React.BaseSyntheticEvent) => {
|
||||
e?.preventDefault();
|
||||
return Promise.resolve();
|
||||
},
|
||||
unregister: () => {},
|
||||
getFieldState: () => ({
|
||||
invalid: false,
|
||||
isDirty: false,
|
||||
isTouched: false,
|
||||
isValidating: false,
|
||||
error: undefined,
|
||||
}),
|
||||
setError: () => {},
|
||||
_disableForm: () => {},
|
||||
_removeUnmounted: () => {},
|
||||
_names: {
|
||||
mount: new Set(),
|
||||
array: new Set(),
|
||||
watch: new Set(),
|
||||
unMount: new Set(),
|
||||
disabled: new Set(),
|
||||
},
|
||||
_state: { mount: false, watch: false, action: false },
|
||||
_options: { mode: "onSubmit", defaultValues: {} },
|
||||
_formState: {
|
||||
isDirty: false,
|
||||
isSubmitted: false,
|
||||
submitCount: 0,
|
||||
isLoading: false,
|
||||
isSubmitSuccessful: false,
|
||||
isSubmitting: false,
|
||||
isValidating: false,
|
||||
isValid: true,
|
||||
disabled: false,
|
||||
dirtyFields: {},
|
||||
touchedFields: {},
|
||||
errors: {},
|
||||
validatingFields: {},
|
||||
},
|
||||
_fields: {},
|
||||
|
||||
_defaultValues: {},
|
||||
_formValues: {},
|
||||
_proxyFormState: {
|
||||
isDirty: false,
|
||||
dirtyFields: false,
|
||||
touchedFields: false,
|
||||
errors: false,
|
||||
isValid: true,
|
||||
isValidating: false,
|
||||
validatingFields: false,
|
||||
},
|
||||
_getDirty: () => false,
|
||||
_updateValid: () => {},
|
||||
_updateFieldArray: () => {},
|
||||
_getWatch: () => ({}),
|
||||
_updateFormState: () => {},
|
||||
register: ((name: string, options?: RegisterOptions<any>) => ({
|
||||
name,
|
||||
onChange: (e: any) => Promise.resolve(),
|
||||
onBlur: (e: any) => Promise.resolve(),
|
||||
ref: () => {},
|
||||
})) as unknown as UseFormRegister<any>,
|
||||
},
|
||||
register: ((name: string) => ({
|
||||
name,
|
||||
onChange: (e: any) => Promise.resolve(),
|
||||
onBlur: (e: any) => Promise.resolve(),
|
||||
ref: () => {},
|
||||
})) as UseFormRegister<FieldValues>,
|
||||
setFocus: () => {},
|
||||
},
|
||||
render: () => {
|
||||
const FormWithError = () => {
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
|
@ -126,6 +424,151 @@ export const WithError: Story = {
|
|||
};
|
||||
|
||||
export const WithDefaultValue: Story = {
|
||||
args: {
|
||||
children: <FormExample />,
|
||||
// watch(callback: (data, { name, type }) => void, defaultValues?: {[key:string]: unknown}): { unsubscribe: () => void }
|
||||
watch: (name?: any, defaultValue?: any) => {
|
||||
if (typeof name === "function") {
|
||||
return { unsubscribe: () => {} };
|
||||
}
|
||||
return defaultValue || {};
|
||||
},
|
||||
getValues: () => [],
|
||||
getFieldState: (name, formState) => ({
|
||||
invalid: false,
|
||||
isDirty: false,
|
||||
isTouched: false,
|
||||
isValidating: false,
|
||||
error: undefined,
|
||||
}),
|
||||
setError: () => {},
|
||||
setValue: () => {},
|
||||
trigger: async () => true,
|
||||
reset: () => {},
|
||||
clearErrors: () => {},
|
||||
formState: {
|
||||
errors: {},
|
||||
isDirty: false,
|
||||
isSubmitting: false,
|
||||
isValid: true,
|
||||
isLoading: false,
|
||||
isSubmitted: false,
|
||||
isSubmitSuccessful: false,
|
||||
isValidating: false,
|
||||
defaultValues: {},
|
||||
dirtyFields: {},
|
||||
touchedFields: {},
|
||||
disabled: false,
|
||||
submitCount: 0,
|
||||
validatingFields: {},
|
||||
},
|
||||
resetField: () => {},
|
||||
handleSubmit: (() => {
|
||||
return async (e?: React.BaseSyntheticEvent) => {
|
||||
e?.preventDefault();
|
||||
return Promise.resolve();
|
||||
};
|
||||
}) as unknown as UseFormHandleSubmit<any>,
|
||||
unregister: () => {},
|
||||
control: {
|
||||
_subjects: {
|
||||
state: {
|
||||
observers: [],
|
||||
subscribe: () => ({ unsubscribe: () => {} }),
|
||||
unsubscribe: () => {},
|
||||
next: () => {},
|
||||
},
|
||||
array: {
|
||||
observers: [],
|
||||
subscribe: () => ({ unsubscribe: () => {} }),
|
||||
unsubscribe: () => {},
|
||||
next: () => {},
|
||||
},
|
||||
values: {
|
||||
observers: [],
|
||||
subscribe: () => ({ unsubscribe: () => {} }),
|
||||
unsubscribe: () => {},
|
||||
next: () => {},
|
||||
},
|
||||
},
|
||||
_reset: () => {},
|
||||
_resetDefaultValues: () => {},
|
||||
_getFieldArray: () => [],
|
||||
_setErrors: () => {},
|
||||
_updateDisabledField: () => {},
|
||||
_executeSchema: () => Promise.resolve({ errors: {} }),
|
||||
handleSubmit: (onSubmit?: any) => (e?: React.BaseSyntheticEvent) => {
|
||||
e?.preventDefault();
|
||||
return Promise.resolve();
|
||||
},
|
||||
unregister: () => {},
|
||||
getFieldState: () => ({
|
||||
invalid: false,
|
||||
isDirty: false,
|
||||
isTouched: false,
|
||||
isValidating: false,
|
||||
error: undefined,
|
||||
}),
|
||||
setError: () => {},
|
||||
_disableForm: () => {},
|
||||
_removeUnmounted: () => {},
|
||||
_names: {
|
||||
mount: new Set(),
|
||||
array: new Set(),
|
||||
watch: new Set(),
|
||||
unMount: new Set(),
|
||||
disabled: new Set(),
|
||||
},
|
||||
_state: { mount: false, watch: false, action: false },
|
||||
_options: { mode: "onSubmit", defaultValues: {} },
|
||||
_formState: {
|
||||
isDirty: false,
|
||||
isSubmitted: false,
|
||||
submitCount: 0,
|
||||
isLoading: false,
|
||||
isSubmitSuccessful: false,
|
||||
isSubmitting: false,
|
||||
isValidating: false,
|
||||
isValid: true,
|
||||
disabled: false,
|
||||
dirtyFields: {},
|
||||
touchedFields: {},
|
||||
errors: {},
|
||||
validatingFields: {},
|
||||
},
|
||||
_fields: {},
|
||||
|
||||
_defaultValues: {},
|
||||
_formValues: {},
|
||||
_proxyFormState: {
|
||||
isDirty: false,
|
||||
dirtyFields: false,
|
||||
touchedFields: false,
|
||||
errors: false,
|
||||
isValid: true,
|
||||
isValidating: false,
|
||||
validatingFields: false,
|
||||
},
|
||||
_getDirty: () => false,
|
||||
_updateValid: () => {},
|
||||
_updateFieldArray: () => {},
|
||||
_getWatch: () => ({}),
|
||||
_updateFormState: () => {},
|
||||
register: ((name: string, options?: RegisterOptions<any>) => ({
|
||||
name,
|
||||
onChange: (e: any) => Promise.resolve(),
|
||||
onBlur: (e: any) => Promise.resolve(),
|
||||
ref: () => {},
|
||||
})) as unknown as UseFormRegister<any>,
|
||||
},
|
||||
register: ((name: string) => ({
|
||||
name,
|
||||
onChange: (e: any) => Promise.resolve(),
|
||||
onBlur: (e: any) => Promise.resolve(),
|
||||
ref: () => {},
|
||||
})) as UseFormRegister<FieldValues>,
|
||||
setFocus: () => {},
|
||||
},
|
||||
render: () => {
|
||||
const FormWithDefaultValue = () => {
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
|
|
|
@ -7,7 +7,13 @@ import { cn } from "@/lib/utils";
|
|||
|
||||
const TooltipProvider = TooltipPrimitive.Provider;
|
||||
|
||||
const Tooltip = ({ children, delayDuration = 10 }) => (
|
||||
const Tooltip = ({
|
||||
children,
|
||||
delayDuration = 10,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
delayDuration?: number;
|
||||
}) => (
|
||||
<TooltipPrimitive.Root delayDuration={delayDuration}>
|
||||
{children}
|
||||
</TooltipPrimitive.Root>
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
import { useCallback } from "react";
|
||||
import { Node, Edge, useReactFlow, useViewport } from "@xyflow/react";
|
||||
|
||||
interface CopyableData {
|
||||
nodes: Node[];
|
||||
edges: Edge[];
|
||||
}
|
||||
|
||||
export function useCopyPaste(getNextNodeId: () => string) {
|
||||
const { setNodes, addEdges, getNodes, getEdges } = useReactFlow();
|
||||
const { x, y, zoom } = useViewport();
|
||||
|
@ -20,7 +25,7 @@ export function useCopyPaste(getNextNodeId: () => string) {
|
|||
selectedNodeIds.has(edge.target),
|
||||
);
|
||||
|
||||
const copiedData = {
|
||||
const copiedData: CopyableData = {
|
||||
nodes: selectedNodes.map((node) => ({
|
||||
...node,
|
||||
data: {
|
||||
|
@ -36,7 +41,7 @@ export function useCopyPaste(getNextNodeId: () => string) {
|
|||
if (event.key === "v" || event.key === "V") {
|
||||
const copiedDataString = localStorage.getItem("copiedFlowData");
|
||||
if (copiedDataString) {
|
||||
const copiedData = JSON.parse(copiedDataString);
|
||||
const copiedData = JSON.parse(copiedDataString) as CopyableData;
|
||||
const oldToNewIdMap: Record<string, string> = {};
|
||||
|
||||
const viewportCenter = {
|
||||
|
@ -77,7 +82,7 @@ export function useCopyPaste(getNextNodeId: () => string) {
|
|||
};
|
||||
});
|
||||
|
||||
const pastedEdges = copiedData.edges.map((edge: Edge) => {
|
||||
const pastedEdges = copiedData.edges.map((edge) => {
|
||||
const newSourceId = oldToNewIdMap[edge.source] ?? edge.source;
|
||||
const newTargetId = oldToNewIdMap[edge.target] ?? edge.target;
|
||||
return {
|
||||
|
@ -99,10 +104,10 @@ export function useCopyPaste(getNextNodeId: () => string) {
|
|||
if (oldToNewIdMap[node.id]) {
|
||||
const nodeConnections = pastedEdges
|
||||
.filter(
|
||||
(edge) =>
|
||||
(edge: Edge) =>
|
||||
edge.source === node.id || edge.target === node.id,
|
||||
)
|
||||
.map((edge) => ({
|
||||
.map((edge: Edge) => ({
|
||||
edge_id: edge.id,
|
||||
source: edge.source,
|
||||
target: edge.target,
|
||||
|
|
|
@ -10,7 +10,7 @@ const stripePromise = loadStripe(
|
|||
export default function useCredits(): {
|
||||
credits: number | null;
|
||||
fetchCredits: () => void;
|
||||
requestTopUp: (amount: number) => Promise<void>;
|
||||
requestTopUp: (credit_amount: number) => Promise<void>;
|
||||
autoTopUpConfig: { amount: number; threshold: number } | null;
|
||||
fetchAutoTopUpConfig: () => void;
|
||||
updateAutoTopUpConfig: (amount: number, threshold: number) => Promise<void>;
|
||||
|
@ -51,15 +51,14 @@ export default function useCredits(): {
|
|||
);
|
||||
|
||||
const requestTopUp = useCallback(
|
||||
async (amount: number) => {
|
||||
async (credit_amount: number) => {
|
||||
const stripe = await stripePromise;
|
||||
|
||||
if (!stripe) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert dollar amount to credit count
|
||||
const response = await api.requestTopUp(amount);
|
||||
const response = await api.requestTopUp(credit_amount);
|
||||
router.push(response.checkout_url);
|
||||
},
|
||||
[api, router],
|
||||
|
|
|
@ -100,8 +100,8 @@ export default class BackendAPI {
|
|||
return this._request("POST", "/credits/auto-top-up", config);
|
||||
}
|
||||
|
||||
requestTopUp(amount: number): Promise<{ checkout_url: string }> {
|
||||
return this._request("POST", "/credits", { amount });
|
||||
requestTopUp(credit_amount: number): Promise<{ checkout_url: string }> {
|
||||
return this._request("POST", "/credits", { credit_amount });
|
||||
}
|
||||
|
||||
getUserPaymentPortalLink(): Promise<{ url: string }> {
|
||||
|
|
|
@ -65,18 +65,21 @@ export type BlockIOObjectSubSchema = BlockIOSubSchemaMeta & {
|
|||
properties: { [key: string]: BlockIOSubSchema };
|
||||
default?: { [key: keyof BlockIOObjectSubSchema["properties"]]: any };
|
||||
required?: (keyof BlockIOObjectSubSchema["properties"])[];
|
||||
secret?: boolean;
|
||||
};
|
||||
|
||||
export type BlockIOKVSubSchema = BlockIOSubSchemaMeta & {
|
||||
type: "object";
|
||||
additionalProperties: { type: "string" | "number" | "integer" };
|
||||
default?: { [key: string]: string | number };
|
||||
secret?: boolean;
|
||||
};
|
||||
|
||||
export type BlockIOArraySubSchema = BlockIOSubSchemaMeta & {
|
||||
type: "array";
|
||||
items?: BlockIOSimpleTypeSubSchema;
|
||||
default?: Array<string>;
|
||||
secret?: boolean;
|
||||
};
|
||||
|
||||
export type BlockIOStringSubSchema = BlockIOSubSchemaMeta & {
|
||||
|
@ -90,11 +93,13 @@ export type BlockIOStringSubSchema = BlockIOSubSchemaMeta & {
|
|||
export type BlockIONumberSubSchema = BlockIOSubSchemaMeta & {
|
||||
type: "integer" | "number";
|
||||
default?: number;
|
||||
secret?: boolean;
|
||||
};
|
||||
|
||||
export type BlockIOBooleanSubSchema = BlockIOSubSchemaMeta & {
|
||||
type: "boolean";
|
||||
default?: boolean;
|
||||
secret?: boolean;
|
||||
};
|
||||
|
||||
export type CredentialsType = "api_key" | "oauth2" | "user_password";
|
||||
|
@ -144,16 +149,19 @@ export type CredentialsProviderName =
|
|||
(typeof PROVIDER_NAMES)[keyof typeof PROVIDER_NAMES];
|
||||
|
||||
export type BlockIOCredentialsSubSchema = BlockIOSubSchemaMeta & {
|
||||
type: "object";
|
||||
/* Mirror of backend/data/model.py:CredentialsFieldSchemaExtra */
|
||||
credentials_provider: CredentialsProviderName[];
|
||||
credentials_scopes?: string[];
|
||||
credentials_types: Array<CredentialsType>;
|
||||
discriminator?: string;
|
||||
discriminator_mapping?: { [key: string]: CredentialsProviderName };
|
||||
secret?: boolean;
|
||||
};
|
||||
|
||||
export type BlockIONullSubSchema = BlockIOSubSchemaMeta & {
|
||||
type: "null";
|
||||
secret?: boolean;
|
||||
};
|
||||
|
||||
// At the time of writing, combined schemas only occur on the first nested level in a
|
||||
|
@ -161,15 +169,21 @@ export type BlockIONullSubSchema = BlockIOSubSchemaMeta & {
|
|||
type BlockIOCombinedTypeSubSchema = BlockIOSubSchemaMeta &
|
||||
(
|
||||
| {
|
||||
type: "allOf";
|
||||
allOf: [BlockIOSimpleTypeSubSchema];
|
||||
secret?: boolean;
|
||||
}
|
||||
| {
|
||||
type: "anyOf";
|
||||
anyOf: BlockIOSimpleTypeSubSchema[];
|
||||
default?: string | number | boolean | null;
|
||||
secret?: boolean;
|
||||
}
|
||||
| {
|
||||
type: "oneOf";
|
||||
oneOf: BlockIOSimpleTypeSubSchema[];
|
||||
default?: string | number | boolean | null;
|
||||
secret?: boolean;
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* eslint-disable react-hooks/rules-of-hooks */
|
||||
import { createClient, SupabaseClient } from "@supabase/supabase-js";
|
||||
import { faker } from "@faker-js/faker";
|
||||
|
||||
export type TestUser = {
|
||||
email: string;
|
||||
|
@ -26,24 +25,6 @@ function getSupabaseAdmin() {
|
|||
return supabase;
|
||||
}
|
||||
|
||||
async function createTestUser(userData: TestUser): Promise<TestUser> {
|
||||
const supabase = getSupabaseAdmin();
|
||||
|
||||
const { data: authUser, error: authError } = await supabase.auth.signUp({
|
||||
email: userData.email,
|
||||
password: userData.password,
|
||||
});
|
||||
|
||||
if (authError) {
|
||||
throw new Error(`Failed to create test user: ${authError.message}`);
|
||||
}
|
||||
|
||||
return {
|
||||
...userData,
|
||||
id: authUser.user?.id,
|
||||
};
|
||||
}
|
||||
|
||||
async function deleteTestUser(userId: string) {
|
||||
const supabase = getSupabaseAdmin();
|
||||
|
||||
|
@ -59,25 +40,3 @@ async function deleteTestUser(userId: string) {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
function generateUserData(): TestUser {
|
||||
return {
|
||||
email: `test.${faker.string.uuid()}@example.com`,
|
||||
password: faker.internet.password({ length: 12 }),
|
||||
};
|
||||
}
|
||||
|
||||
// Export just the fixture function
|
||||
export const createTestUserFixture = async ({}, use) => {
|
||||
let user: TestUser | null = null;
|
||||
|
||||
try {
|
||||
const userData = generateUserData();
|
||||
user = await createTestUser(userData);
|
||||
await use(user);
|
||||
} finally {
|
||||
if (user?.id) {
|
||||
await deleteTestUser(user.id);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue