Compare commits

...

307 Commits

Author SHA1 Message Date
Eric Allam 6881de84ab Fix pnpm lock file 2023-10-26 20:04:03 +01:00
github-actions[bot] 0ca8296b9a chore: Update version for release (#686)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-10-26 20:03:37 +01:00
Eric Allam 55946fcdb7 Update @trigger.dev/nextjs to support Next.js 14 (#690) 2023-10-26 19:45:19 +01:00
Eric Allam c0f9f10b07 Upgrade to Remix v2.1.0 2023-10-26 15:54:21 +01:00
Eric Allam e80aa2826d @trigger.dev/express: Remove web-fetch dependency and use native node Request/Response 2023-10-26 13:42:20 +01:00
NIXEY 1be25d7639 BlankRow centered (#678) 2023-10-26 13:35:15 +01:00
ROMIT PAL 3c3a5e1f28 added a missing CODE OF CONDUCT file (#677)
Incorporating a Code of Conduct in your GitHub repository is crucial for promoting an inclusive, respectful community. It establishes guidelines, minimizes conflicts, safeguards participants, and adheres to legal standards. Additionally, it demonstrates professionalism and aligns with GitHub's best practices, contributing to a welcoming and harmonious environment, which, in turn, enhances collaboration and the project's overall success.
2023-10-26 13:30:14 +01:00
Vineet J Karni 8e741c7218 Added warning ⚠️ - No support for long-running servers (#669) 2023-10-26 13:18:28 +01:00
Hemachandar 83455e3ad4 feat: implement API key regeneration (#649) 2023-10-26 13:15:50 +01:00
Ronit Panda f0f0420280 feat: adds helm charts (#636)
* feat: adds helm charts template and adds postgres deps

* feat: adds all depl (barebones)

* feat: adds all depl (barebones)

* fix: removes print

* fix: image pulling issue

* fix: templatisation complete

* style: cleanup

* feat: works

* feat: adds ingress and some docs

* fix: ingress bug --> routing to cluster works

* feat: completes docs v1 todo --> needs hosting of the helm chart on chosen platform
2023-10-26 11:50:59 +01:00
Hemachandar c4533c36cb fix: set error message in runTask & executeJob (#634)
* fix: set error message in runTask & executeJob

* add changeset
2023-10-26 11:46:09 +01:00
Eric Allam f8e034c190 Fixed import that was causing typecheck to fail 2023-10-26 11:43:23 +01:00
Eric Allam 21f62e780c Added tests and refactored response to use camelCase 2023-10-26 11:30:49 +01:00
hmacr c3564ca0d4 fix doc 2023-10-26 11:18:11 +01:00
hmacr 6e1b8a11d4 feat: allow cancelling job runs for an event-id 2023-10-26 11:18:11 +01:00
Matt Aitken 9900f19b70 Migration: Updates any Endpoint runChunkExecutionLimits that were 60ms to be 60000ms 2023-10-25 15:50:11 +01:00
Matt Aitken 237545754f Indexing errors weren’t being serialized to JSON properly in some cases, so the errors weren’t getting inserted
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 1s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 0s
🚀 Publish Trigger.dev Docker / units (push) Failing after 21s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
2023-10-24 18:08:46 +01:00
Eric Allam d7c1e98e5e Update pnpm lock 2023-10-24 17:49:39 +01:00
github-actions[bot] 71a0afeb8d chore: Update version for release (#684)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-10-24 17:49:06 +01:00
Eric Allam 36a390449a @trigger.dev/openai: Upgrade to openai-node SDK 4.13.0, add support for request options and defaultQuery/defaultHeaders 2023-10-24 17:45:43 +01:00
James Ritchie 375e495423 Fixed accounts table not scrolling in the admin area 2023-10-24 17:34:33 +01:00
D-K-P 866c20cd39 Updated the Slack underlying client example 2023-10-24 16:26:14 +01:00
Eric Allam 408785b8ef Update pnpm lock file 2023-10-24 13:41:35 +01:00
github-actions[bot] f982e00997 chore: Update version for release (#618)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-10-24 13:40:57 +01:00
Eric Allam 7e100b8362 ignore: adding more logs to perform task operation
🚀 Publish Trigger.dev Docker / units (push) Failing after 0s
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 5s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 6s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
2023-10-24 12:14:52 +01:00
Eric Allam ea052c44c7 ignore: Add durationinMs to log 2023-10-24 11:38:35 +01:00
D-K-P 76224568f4 Airtable copy updates 2023-10-24 11:31:01 +01:00
Dan 72e67981b0 Merge pull request #666 from shelar1423/patch-3
Improved the Airtable integration documentation
2023-10-24 11:08:03 +01:00
Eric Allam cc44aff24b Added some docs about using the OpenAI integration as a universal client 2023-10-24 09:35:20 +01:00
Eric Allam 07d28ee4f5 Add custom baseURL and idempotency key support to OpenAI integration (#682)
This commit introduces the ability to set custom base URLs, which allows for the use of different APIs such as Perplexity. It also ensures that any OpenAI-related task now includes an idempotency key when making requests. Works for background tasks as well.
2023-10-24 09:19:38 +01:00
D-K-P f16a2cc4e6 Added link to the api reference repo to the readme 2023-10-24 09:11:57 +01:00
D-K-P b859837564 Edited the OpenAI ovrerview and added correct links for the tasks 2023-10-23 17:19:19 +01:00
Dan 1343003efa Merge pull request #673 from Rutam21/TRI-1430
[TRI-1430] : Improve the OpenAI integration documentation
2023-10-23 16:58:22 +01:00
Eric Allam 0c4aea0338 Add execution duration for background fetch 2023-10-23 16:55:00 +01:00
Eric Allam 627c767c64 fix: fix trigger sources getting repeatedly registered
Fixes a bug where trigger sources would get re-registered on every index, no matter if they were already properly registered or not. This was causing a lot of extra “internal” runs and being overly chatty with client endpoints
2023-10-23 15:24:35 +01:00
Digvijay Shelar f3a0c3a5d1 Merge branch 'main' into patch-3 2023-10-23 17:00:57 +05:30
dhselar1423 7bca3d9c15 made suggested changes 2023-10-23 16:57:52 +05:30
D-K-P 01fc1c6634 Slack integration docs copy updates 2023-10-23 12:17:29 +01:00
Dan 2d4f85e9f4 Merge pull request #667 from shelar1423/patch-4
Improved the Slack integration documentation
2023-10-23 12:08:40 +01:00
Rutam21 8718b28949 [TRI-1430] : Improve the OpenAI integration documentation 2023-10-21 04:55:12 +05:30
dhselar1423 2caa2a5bbd Merge branch 'patch-4' of https://github.com/shelar1423/trigger.dev into patch-4 2023-10-20 23:14:43 +05:30
dhselar1423 43a10ee695 slack fixes 2023-10-20 23:11:41 +05:30
Digvijay Shelar 018005d478 Merge branch 'main' into patch-4 2023-10-20 22:33:54 +05:30
dhselar1423 4da187c4c5 Merge branch 'patch-3' of https://github.com/shelar1423/trigger.dev into patch-3 2023-10-20 22:33:15 +05:30
dhselar1423 4925424778 Oauth and overview modifications 2023-10-20 22:32:48 +05:30
dhselar1423 7ef61222ed slack editing 2023-10-20 22:26:38 +05:30
Eric Allam 044d38e390 Improvement: Auto Execution Yielding (#612)
* Auto-yield run execution to help prevent duplicate task executions

* Add auto-yield config to endpoints

* Refactor run execution with buffer and limits

Introduced constants RUN_CHUNK_EXECUTION_BUFFER and MAX_RUN_CHUNK_EXECUTION_LIMIT. Adjusted PerformRunExecutionV2Service to use the new constants to fine-tune execution timings and buffers.

* Add endpoint probing functionality

Added new `RESPONSE_TIMEOUT_STATUS_CODES` in `consts.ts` to manage timeout responses. Additional functions `detectResponseIsTimeout(response: Response)` was added in `endpoint.server.ts` to detect if a response was a timeout based on the status codes from `RESPONSE_TIMEOUT_STATUS_CODES`.

Update actions to use new endpoint probing endpoint service. This allows for the early probing of endpoints to determine if they're up and running.

A new class `ProbeEndpointService` was created in `probeEndpoint.server.ts` which makes HTTP requests to a given endpoint and updates its properties based on the result.

Finally, `detectResponseIsTimeout(response)` is used in `performRunExecutionV2.server.ts` for marking the execution as succeeded when facing a timeout.

* Refactored probe method in EndpointApi class

The probe method of the EndpointApi class has been refactored to remove the error handling part and it now takes a timeout sent from the client directly. The corresponding changes were also made in the ProbeEndpointService and TriggerClient objects to reflect the alterations in the probe method.

The error handling related to the timeout has been removed and the responsibility of handling the timeout has been shifted to the client. Thus, the probe method has been greatly simplified. The `probeEndpoint.server.ts` file was also changed to accommodate the change in behavior of the probe result.

In the `triggerClient.ts` the timeout for probe is now read from the incoming request object. For backward compatibility, if no timeout is provided in the request, the default value of 15 minutes is used.

* Remove performRunExecution v1 enqueue function
* Better document limits and add docs on increasing function timeouts
* Upgrade webapp docker container to use 18.18.2
* force clients to yield when a run is executing in a gracefully shutting down worker
* Renamed task `key` to `cacheKey` and added more task documentation
* Index the `@trigger.dev/sdk` version on Endpoints
2023-10-20 17:44:10 +01:00
James Ritchie e7768881af Admin page now full screen with now extra UI 2023-10-20 16:53:04 +01:00
James Ritchie 5ea6a49d08 Made the app work very basically on mobile devices (#668)
* Removed the no-mobile blocker overlay so you can use the site on a phone

* Removed mobile dropdown from nav

* The app works on mobile at a width of 1024px
2023-10-20 16:12:17 +01:00
D-K-P dce5578327 Improved the GitHub overview copy 2023-10-20 14:35:28 +01:00
dhselar1423 fde3f17a25 fixed typos 2023-10-20 19:00:41 +05:30
dhselar1423 a6c9cac26c slack docs 2023-10-20 18:30:03 +05:30
Digvijay Shelar 960d99461a Merge branch 'triggerdotdev:main' into patch-3 2023-10-20 17:55:25 +05:30
dhselar1423 e5307133b3 airtable docs 2023-10-20 17:55:07 +05:30
D-K-P 34bb3acc23 Removed idempotencyKey line from GH tasks 2023-10-20 12:50:27 +01:00
Hemachandar 6d3b761cd7 fix: set correct next/prev cursors in run-list-presenter (#642)
* fix: set correct next/prev cursors in run-list-presenter

* set runs to return
2023-10-20 12:00:17 +01:00
Matt Aitken abc9737a4f Tabler icons added to NamedIcon
commit 13ed268f1d6732ef28c6e4a9eeb927c1af822032
Author: Matt Aitken <matt@mattaitken.com>
Date:   Fri Oct 20 11:38:22 2023 +0100

    Added all the tabler-icons to Storybook

commit 62738d71a40f17c45c0b29332359b2b670233a97
Author: Matt Aitken <matt@mattaitken.com>
Date:   Fri Oct 20 11:38:09 2023 +0100

    Use the no-stroke version of the tabler-sprite so we can control the stroke width

commit a1b7edd57f8b2d3f2a5f4d96cbc9eb0a887f3442
Author: Matt Aitken <matt@mattaitken.com>
Date:   Fri Oct 20 11:37:54 2023 +0100

    Set the default width to 1.5, so they’re a bit thinner

commit 69ba38802b849376611678537f7d8e248b60086b
Author: Matt Aitken <matt@mattaitken.com>
Date:   Fri Oct 20 10:55:34 2023 +0100

    Added a tabler icon to an events job catalog job

commit eb3c5f649d06adcc9ce0641f50e082ecdeead7a2
Author: Matt Aitken <matt@mattaitken.com>
Date:   Fri Oct 20 10:53:40 2023 +0100

    Moved the tabler sprite to the app and use an import. This means it’ll be cached and we can move it

commit c24d76e6df9233b001a0242f8806076562ca2e90
Author: Chaturved Degloorkar <48447253+chaturrved@users.noreply.github.com>
Date:   Fri Oct 20 15:22:59 2023 +0530

    feat: Add support for tabler-icons when using the icon for Tasks  (#629)

    * Add support for tabler-icons

    * Changed the core update type from minor to a patch

    ---------

    Co-authored-by: Matt Aitken <matt@mattaitken.com>
2023-10-20 11:41:45 +01:00
Bhargav Shirin Nalamati 84af64165c changed the title for contributors (#633) 2023-10-20 10:22:13 +01:00
Alexandre Costa 0adf41c7f0 Feat: add maxDuration setting for API/Trigger route in the CLI Init Command for Next.js (#617)
* add cli init maxDuration to the api/trigger route for nextjs

* refactor createTriggerRoute

* move boxen log to createTriggerRoute function

* refine detectNextVersion and versionNumberPattern regex to match the latest nextjs version

* add tests for the detectNextVersion function

* add changeset file

* If the regex doesn't match, it returns null instead of throwing

* Tweaked message about the max duration

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2023-10-20 10:16:44 +01:00
Dan b7f4e40edb Merge pull request #660 from Rutam21/TRI-1425
[TRI-1425] : Improve the Plain integration documentation.
2023-10-20 10:05:18 +01:00
Rutam21 cf33396dc0 [TRI-1425] Improve the Plain integration documentation 2023-10-20 02:45:46 +05:30
Dan 51f2cd6b3f Updated posthog to 1.83.0 (#608) 2023-10-19 16:34:41 +01:00
vimode 513d0f071d fix: broken links in documentation (#602)
* fix: broken links at what is triggerdev docs

* fix: broken links for apikey

* fix: broken sdk link

* fix: broken link in concepts/triggers

* fix: broken link for zod guide at concepts/triggers/events

* fix: broken links in title for projects

* Shouldn't have /docs at the start

* Use backgroundFetch path

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2023-10-19 16:27:21 +01:00
Hemachandar 50e3192453 feat: add ability to use custom tunnel in dev cmd (#597)
* feat: add ability to use custom tunnel in dev cmd

* Added a short flag -t for the tunnel flag

* skip framework url resolution if tunnel-url is provided

* remove type annotation

---------

Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Matt Aitken <matt@mattaitken.com>
2023-10-19 16:11:08 +01:00
Dan 1524c95a7a Merge pull request #650 from shelar1423/patch2
Get help icon and twitter text modifications
2023-10-19 12:46:41 +01:00
Eric Allam c8aaea8ad0 Improvements: Gracefully shutdown to prevent locked jobs (#648)
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 6s
🚀 Publish Trigger.dev Docker / units (push) Failing after 5s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 6s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
* WIP

* Report ECS task info on startup and shutdown

* Fixed lifecycle name

* Re-add terminus

* Require the build dir when http server is disabled

* Remove unnecessary logs

* Implement graceful shutdown in ZodWorker

* Re-order some code

* Increase the keepAliveTimeout to 65 seconds to prevent LB 502 errors
2023-10-19 11:18:19 +01:00
dhselar1423 cf7f25abcd fix 2023-10-19 08:08:53 +05:30
dhselar1423 99453e8581 Merge branch 'patch2' of https://github.com/shelar1423/trigger.dev into patch2 2023-10-19 01:10:16 +05:30
dhselar1423 bc7206d981 x 2023-10-19 01:10:05 +05:30
Digvijay Shelar 64b8e150ea Merge branch 'triggerdotdev:main' into patch2 2023-10-19 01:03:19 +05:30
dhselar1423 b3b5852a88 fixed icons 2023-10-19 01:02:54 +05:30
Digvijay Shelar d1ecd6b99c framework icons (#635) 2023-10-17 22:00:56 +01:00
dhselar1423 0fb16a7324 framework icons 2023-10-18 01:21:47 +05:30
Matt Aitken 4f317055fd useDevEnvironment returns the current user’s dev environment, not the first 2023-10-16 16:19:16 +01:00
Eric Allam 3afd5f8cf3 Merge branch 'main' of github.com:triggerdotdev/trigger.dev 2023-10-16 16:04:09 +01:00
Eric Allam c922d24941 Adding simulate graphile job to easily debug graceful shutdown retries in docker image 2023-10-16 16:04:05 +01:00
Matt Aitken 39ec34f84f Latest lockfile 2023-10-16 13:16:02 +01:00
Ravan b9eba68078 feat: export base file (#610)
* feat: export base file

* Added a change set

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2023-10-13 17:44:05 +01:00
nicktrn 9df93d0798 CLI create-integration templates and shared configs (#511)
* Add tsup config package

* Add integration tsconfig to extend from

* Return correct version via cli -v

* Make create-integration use templates

* Add changeset

* Switch to liquidjs templates

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2023-10-13 16:55:22 +01:00
Matt Aitken 6769d6b439 Squashed commit of the following:
commit c028db229cece2bf7d7acf04e7b1c08fea61798c
Author: Matt Aitken <matt@mattaitken.com>
Date:   Fri Oct 13 16:04:54 2023 +0100

    Some fixes for getting the endpoint id

commit e31b7ac5f2d451f70e3d42a3fb3e5f718d93485b
Author: Matt Aitken <matt@mattaitken.com>
Date:   Fri Oct 13 15:39:18 2023 +0100

    Added a link in the instructions if Node isn’t detected

commit 1a59cced775fbeac3e5b94e0c151b490c838d8f8
Author: Matt Aitken <matt@mattaitken.com>
Date:   Fri Oct 13 15:39:05 2023 +0100

    Fixed some conflict issues

commit 77263ed26bcf7025071ac0faf15fb867fff245d0
Author: Matt Aitken <matt@mattaitken.com>
Date:   Fri Oct 13 15:38:56 2023 +0100

    Added a changeset

commit 1a7df3f37f0c65d68cb9a9fe7ac50328bbb4d879
Author: GuyBorderless <100129659+guy-borderless@users.noreply.github.com>
Date:   Fri Oct 13 17:31:01 2023 +0300

    feat: enable deno  (#531)

    * adding deno reference project and JSRuntime file

    * accessing runtime specific functions through JsRuntime

    * adding support for both deno.json and deno.jsonc

    * no automatic setup for deno projects currently

    ---------

    Co-authored-by: Guy Kedem <guy@propertiz.net>
    Co-authored-by: Matt Aitken <matt@mattaitken.com>
2023-10-13 16:20:18 +01:00
Eric Allam 70410d33af Ability to change the timeout of the graceful shutdown via env var 2023-10-13 15:12:05 +01:00
Hemachandar 6371dd4f95 feat: allow sendEvent to update an existing event (#607) 2023-10-13 14:46:35 +01:00
Eric Allam ebe78017ef Update pnpm lock file after package release merge 2023-10-13 13:21:52 +01:00
github-actions[bot] b697a19954 chore: Update version for release (#579)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-10-13 13:21:10 +01:00
Eric Allam 29ca09e42d Fixes #611: intervalTriggers of >10 never starting
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 5s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 6s
🚀 Publish Trigger.dev Docker / units (push) Failing after 21s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
2023-10-13 09:38:25 +01:00
Eric Allam 375b788ab0 Add row locking with FOR UPDATE in delete query 2023-10-13 09:23:05 +01:00
Matt Aitken d6b44d13f7 Show magic link errors in the UI, switch to useNavigation hook, and return using the authenticator 2023-10-12 18:15:46 +01:00
Matt Aitken c6784ba7b8 Added logging when the magic link authentication function is called 2023-10-12 18:12:26 +01:00
James Ritchie 6b8b1c7cae Added data-action tracking to all the login buttons 2023-10-12 17:38:37 +01:00
Eric Allam 0c20756624 Remove reporter because of https://github.com/graphile/worker/issues/349 2023-10-12 17:06:06 +01:00
Matt Aitken 3d387d602d Added additional log after a magic link user has done verification 2023-10-12 16:48:51 +01:00
Matt Aitken 5d45dea0e1 Added some logging when sending magic link emails 2023-10-12 16:45:05 +01:00
James Ritchie a25751e805 Added some better messaging to the login pages
- Better login page title and subtitle
- Better title and new ‘having issues’ panel on the magic link pages
2023-10-12 16:16:20 +01:00
D-K-P 659be8cbc1 Added Hacktoberfest info to our readme 2023-10-12 13:41:15 +01:00
Matt Aitken 50e3d9e43a Indexing errors don't get displayed anywhere (#605)
* Added EndpointIndex status. Default is PENDING, existing rows are SUCCESS

* Made it easier to create a migration SQL file

* Created a job-catalog file for misconfigured Jobs that should error when running the CLI

* EndpointIndex data and state are now optional

* The Environments page now shows the status of the last refresh

* Improved the UI about endpoints

* Added EndpointIndex error column

* WIP making the endpoint indexing more robust

* Indexing errors are now surfaced

* Improved the error show it shows the job id

* Use “performEndpointIndexing” when you create your first endpoint from the UI

* Use “performEndpointIndexing” for the recurring endpoint checker

* Staging is now auto-indexed every 10 mins too

* Use “performEndpointIndexing” for the webhook

* Moved the throttling to a util

* Removed instructional comments

* Created a reusable retry system with exponential backoff

* Use p-retry for retrying with backoff

* The CLI gets indexing results and displays errors

* Improved the indexing error messages and display in the console

* Use a pre so the Indexing error is correctly split over multiple lines

* Use a db transaction for webhook that triggers endpoint indexing

* Tidied up imports

* Support older versions of the server

* Improved the comment on the misconfigured job

* Changeset: When indexing user's jobs errors are now stored and displayed
2023-10-11 17:31:19 +01:00
Eric Allam 203a431350 Add stripe and airtable to the integrations catalog 2023-10-11 11:55:35 +01:00
Hemachandar 39a332eff1 feat: add filter for active jobs in the dashboard (#601)
* feat: add filter for active jobs in the dashboard

* use cursor-pointer when hovering Switch label

* remove unused import

* remove unnecessary span

* add flex-gap
2023-10-11 11:24:24 +01:00
Arjun S 498f56de3e Feat: Replaicing react hot toast with Sonner toasts (#600)
* Feat: Replaicing react hot toast with  Sonner toasts

* pnpm lock file fix

* Quickfix
2023-10-11 10:52:10 +01:00
Eric Allam b23696b255 Move to reporting worker stats through logs 2023-10-11 10:43:37 +01:00
Eric Allam f3a7e2aa20 Add APP_ENV to worker reporter email 2023-10-10 23:15:06 +01:00
Eric Allam b737f7af92 Report worker metrics when WORKER_REPORTER_EMAIL env var is set 2023-10-10 23:06:07 +01:00
Eric Allam f54a9ff5fc Fixed broken link in runTask description 2023-10-10 16:12:30 +01:00
Eric Allam 067c0db543 Merge branch 'main' of github.com:triggerdotdev/trigger.dev 2023-10-10 15:47:57 +01:00
Eric Allam 773765f82d Cleanup finished graphile_worker.jobs last run more than 7 days ago 2023-10-10 15:47:53 +01:00
Eric Allam 624072c23b Update release.yml 2023-10-10 15:04:13 +01:00
Eric Allam d37576f814 Update release.yml 2023-10-10 15:03:30 +01:00
Eric Allam 476e2f035f Don’t typecheck the workspace packages inside the webapp 2023-10-10 12:02:01 +01:00
Eric Allam ad71964d30 Upgrade local development Node to v18.18.0 using nvm 2023-10-10 11:53:42 +01:00
Rutam Prita Mishra 975c5f1d3c [TRI-1333] : Upgrade all packages to use Node18 and use fetch instead node-fetch (#581)
* [TRI-1333] : Upgrade all packages to use Node18 and use fetch instead of node-fetch

* Changeset Added

* Update pnpm-lock to compatible pnpm v7.18.1

* Restored pnpm-lock to the last known good point compatible with pnpm v7.18.1

* Update chilled-plants-exercise.md

---------

Co-authored-by: Eric Allam <eallam@icloud.com>
2023-10-10 11:42:02 +01:00
D-K-P 916ed4e366 Updated features table 2023-10-10 09:50:48 +01:00
Ikko Eltociear Ashimine df4667b7f5 Fix typo in sse.ts (#591)
Uknown -> Unknown
2023-10-09 22:08:53 +01:00
md d663ba8985 Fixed #593 Added Contributors Section to readme.md (#594)
* Fixed #593 Added Contributors Section to readme.md 

Fixed #593 Added Contributors Section to readme.md

* Update README.md

---------

Co-authored-by: Eric Allam <eallam@icloud.com>
2023-10-09 22:08:32 +01:00
Eric Allam 8c8d1598e3 Reuse common workflow jobs in publish workflow 2023-10-09 18:30:55 +01:00
Eric Allam 646bfd37bd Pushing a commit to the branch so I can open a PR (#592)
* Pushing a commit to the branch so I can open a PR

* Couple improvements to the pr checks workflow
2023-10-09 18:28:49 +01:00
Eric Allam c0d5292b06 Attempt to fix pgadmin error in tests 2023-10-09 18:22:38 +01:00
Eric Allam 8c383bdc69 Add a PR checks github workflow to run typecheck, unit tests, and e2e tests on PRs 2023-10-09 18:19:06 +01:00
Hemachandar 97e63d1222 Event Trigger Example Payload: Fix unsetting icon, and Use fallback icon in case of invalid icon-name. (#576)
* fix: unset event-trigger example icon

* fix: use fallback icon when an invalid icon is used (example payload page)
2023-10-09 17:33:08 +01:00
D-K-P 87ee98aff1 Added NestJS to the quick starts side menu 2023-10-09 17:28:57 +01:00
Hemachandar c070e78d06 feat: allow CLI update to accept a version for trigger-dev package (#536)
* feat: allow CLI update to accept a version for trigger-dev package

* remove console log
2023-10-09 17:15:24 +01:00
Eric Allam 1c4f9ff1ff Add pgAdmin instructions to contributing guide 2023-10-09 17:14:40 +01:00
nicktrn ca031a72e7 Add pgAdmin (#533) 2023-10-09 16:57:28 +01:00
Dan cbc976188e GitHub docs improvements (#568)
* Updated github-triggers and intro

* Edited tasks / triggers and main overview page

* Added links to scopes docs and improved copy

* Added an overview, side bar title and improved the ordering / wording

* Added the underlying Github client section and some formatting updates

---------

Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eallam@icloud.com>
2023-10-09 16:48:38 +01:00
Eric Allam 59a94c710e Fixes #583 by filtering out properties with missing values (#584)
This also improves the retrying behavior of the resend integration by skipping retrying certain client errors
2023-10-09 16:04:32 +01:00
James Ritchie 4cd97c81ea Swapped out the Integration page skeleton state for a simpler message 2023-10-09 15:20:17 +01:00
Matt Aitken d0d5a698ec Added versions to Supabase management docs examples that are missing them 2023-10-09 14:03:17 +01:00
Matt Aitken ee033a1fd4 Onboarding, don’t show undefined if there are no extra params for dev command 2023-10-09 11:21:44 +01:00
D-K-P 2394fcdf35 Added line about Stripe Shell to the Stripe docs 2023-10-09 09:58:20 +01:00
Matt Aitken 6edaffeb7e Try and determine an error some HTTP requests are causing (#586) 2023-10-08 17:20:07 +01:00
Matt Aitken 0558b2c595 feat: sveltekit adaptor (#575)
* Feat/svelte kit support (#467)

* feat: implemented svelte-kit adapter

* feat: implemented the @trigger.dev/svelte package

* scaffolded a sveltekit example project with trigger.dev

* added the convertToStandardRequest function in the sveltekit package

* example sveltekit project with the @trigger.dev/svelte package

* doc: added the manual setup guide for sveltekit

* updated the web app onboard for sveltekit

* formatted the manual setup guide for sveltekit

* added a link to webapp sveltekit onboarding

* added a wait function to the sveltekit example app job

* typo fix

* removed comments from the @trigger.dev/svelte

- commented out the useEventRunDetails

* updated package.json to use internal packages

* added a .env.example file

* updated the example-svelte-app

* updated the svelte-example

* updated the onboarding page to reflect requested changes

* made the manual setup guide more specific

* created a .env.example file for svelte-example

* added import aliases

* updated the tsconfig and svelte.config file

* updated to use uint8Array

* added missing paths in the tsconfig

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>

* Moved examples to references

* Tweaked the SveleteKit manual setup guide

* Updated zod, and set the svelte/sveltekit package versions to match other packages

* Added the headers to the response from the SvelteKit api/trigger route

* Changeset for Svelte and SvelteKit packages

* Revert change to rawBody

* Remove core from changeset packages

* Delete svelte .npmrc file

* Build svelte package to build, not build/lib

* Made the snapshot instructions easier to copy

* Delete the svelte package

* Latest lockfile

* Updated the SvelteKit docs

* Attempt to get Svelte to import the package

* Updates for port and host options

* Updated lockfile from main

* Update neat-feet-wait.md

---------

Co-authored-by: Chigala <92148630+Chigala@users.noreply.github.com>
2023-10-06 17:12:52 +01:00
Hemachandar b12bc6042f (regression) fix: remove invalid envFile response field in sendEvent cmd (#577)
* fix: remove invalid envFile response field in sendEvent cmd

* add changeset
2023-10-06 16:55:26 +01:00
Eric Allam a7bc5df754 use the new JobRun.internal flag in usage stats 2023-10-06 16:15:13 +01:00
Hemachandar 1c524c5acc feat: add internal flag to job-run table (#563)
* feat: add internal flag to job-run table

* add backfill SQL

* Update internal backfill to only update internal jobs

---------

Co-authored-by: Eric Allam <eallam@icloud.com>
2023-10-06 15:46:09 +01:00
Eric Allam 65ad98c20d Add docs for yield and brb 2023-10-06 15:13:45 +01:00
Eric Allam 24d892e322 Merges 573 with fix for Dockerfile (#578)
* update prisma to 5.4.1 (#573)

* Get prisma 5.4.1 to work in the Dockerfile

---------

Co-authored-by: Karthik <kartim316@gmail.com>
2023-10-06 15:10:43 +01:00
Hemachandar be9b51131d feat: allow CLI dev to use injected environment variables (#532)
* feat: allow CLI dev to use injected environment variables

* Remove console.log

---------

Co-authored-by: Eric Allam <eallam@icloud.com>
2023-10-06 14:18:58 +01:00
Hemachandar 63a65dabe4 chore: add example for eventTrigger() doc (#541)
* chore: add example for eventTrigger() doc

* add documentation to the options parameter
2023-10-06 13:56:28 +01:00
Matt Aitken 1f3b423c22 Removed testing dependencies from nestjs example 2023-10-06 13:18:47 +01:00
Matt Aitken a69a5019f1 Removed NestJS example project tests 2023-10-06 13:16:40 +01:00
Matt Aitken 5910339bf4 Latest lockfile 2023-10-06 12:56:56 +01:00
github-actions[bot] 4b641b25a6 chore: Update version for release (#571)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-10-06 12:54:07 +01:00
Matt Aitken a847b492bc NestJS framework suport (from @H4ad) (#574)
* feat: added nestjs package adapter

* Latest lockfile

* Updated Astro setup docs: env import

* Astro docs improvements

* Docs: improved the limitations

* Bumped package versions to 2.1.3

* Updated the Astro docs with SSR notes

* test/368/use vitest instead of jest (#470)

* chore: add vitest dependencies

* refactor: replace jest by vitest

* test: disable broken test

* Update pnpm-lock.yaml

* Update pnpm-lock.yaml

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>

* Created Temp for pull req, bugreport & feature req

* A few teaks to the templates

* Added instructions for how to do Changeset snapshots

* Redirect people to discord to ask a question

* Documentation Update: Added <github_username> instead of triggerdotdev to avoid confusion while cloning the repository (#477)

* Added a link to the homepage from the side menu (#479)

* Added 2 new named icons

* New side menu link to the homepage

* Updated lock file

* Removed un-used import

* Renamed the examples dir to references (true examples are in another repo and this was confusing)

* Add a references README

* Fixes broken pnpm lock file

* Improve the Astro manual setup guide

* Fixed cal.com link

* Upgrade to the latest remix (pre v2)

* React status hooks (#493)

* Added stripInternal to SDK tsconfig

* Statuses can now be set from a run, and are stored in the database

* Added the key to the returned status

* Made the test job have an extra step and only pass in some of the options

* client.getRunStatuses() and the corresponding endpoint

* client.getRun() now includes status info

* Fixed circular dependency schema

* Translate null to undefined

* Added the react package to the nextjs-reference tsconfig

* Removed unused OpenAI integration from nextjs-reference project

* New hooks for getting the statuses

* Disabled most of the nextjs-reference jobs

* Updated the hooks UI

* Updated the endpoints to deal with null statuses values

* The hook is working, with an example

* Changeset: “You can create statuses in your Jobs that can then be read using React hooks”

* Changeset config is back to the old changelog style

* WIP on new React hooks guide

* Guide docs for the new hooks

* Added the status hooks to the React hooks guide

* Removed the links to the status hooks reference for now

* Re-ordered the hooks

* Fix for an error in the docs

* Set a default of a blank array for the GetRunSchema

* Fixed dependency

* Revert "Upgrade to the latest remix (pre v2)"

This reverts commit 4edc7112ab.

* Update introduction.mdx (#498)

Changed https://github.com/triggerdotdev/examples/tree/main/resend (which was a 404) to https://github.com/triggerdotdev/examples/tree/main/resend-email-form

* Use the bell icon for the new status Tasks

* Going exponential with `Linear` (#478)

* Unleash GPT magic

* Clean up after GPT

* All the hooks

* Provisional integration catalog entry

* Sample webhook jobs

* Attachments with alpha warnings

* Remove some verbose logs

* Fix IP restrictions

* Remove tunnel

* Revert "Remove tunnel"

This reverts commit c5b69ce6524e3b40c26b66cdc56e087b8576b8c6.

* Resolve event name clashes

* Remove circular dependency

* Use correct payload uuid

* Schema fixes

* Fix webhook event name

* Start to Linearify catalog entry

* Remove todo

* More catalog updates

* Make OAuth work

* Rename webhook helper

* Schema juggling

* More discrimination

* Add Issue SLA event

* Simplify triggers

* Handle rate limits

* Fix Project schema

* Payload examples

* Improve event props

* Remove redundant source metadata

* One type to rule them all

* Recursive WithoutFunctions type

* Linear output serializer

* Some tasks

* Update catalog entry

* Dynamic usage sample

* Bump version

* Remove tunnel

* More tasks

* Add optional skipRetrying on runTask errors

* Fail fast on user errors

* Entity getter tasks

* Another couple of tasks

* Token to apiKey

* Sort tasks

* Add filtered issue SLA triggers

* Add docs

* Type fixes

* Job catalog examples

* Serialization helper docs

* Add changeset

* Refactor webhooks

* Enhance properties

* Pagination helper and docs

* Clean up imports

* Change misc catalog job

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>

* Use absolute image paths (#490)

* Update sendevent.mdx

* fix: Fail client-side on invalid Stripe event names (#492)

* Parse event names

* Add changeset

* feat: BYO Auth (#491)

* feat: BYO Auth

Define client-side auth resolvers to be able to supply custom authentication credentials for integrations before a run is performed

- Added new defineAuthResolver
- Update all integrations to support the new auth resolvers
- Strip internal symbols from .d.ts in integrations and trigger-sdk
- Added BYO Auth docs
- Update Dynamic Schedule to support associated account IDs
- Create external accounts just-in-time
- Added Account ID field to test job when there are external auth integrations
- Show Account ID on run dashboard
- Added new Run error state called “Unresolved auth”

* Added changeset

* Remove @internal from TriggerIntegration public methods

* Add void to the result union

* DynamicTriggers now work with the new BYO auth system, and added a bunch of docs and docs changes

* Add additional key material for registering dynamic trigger task

* Add new define* instance methods to the overview

* CLI now supports multiple frameworks (with tests) (#480)

* Early work defining CLI framework support

* WIP moving CLI init logic to the Framework class

* Installing files should now work for Nextjs

* Some fixes

* WIP creating unit tests for Next.js project detection

* Delete old jest config

* Latest lockfile

* Detect use of src directory test

* Tests for detection pages/app directory

* Correct detection of Next.js project

* Renamed test file

* Create install files from template files with replacements. With tests

* Added multiple uses of the same replacement

* Created a test for the install step (it fails right now with JS)

* Removed unused import

* Another test that should pass but currently fails…

* Path alias fixed and now has tests

* New pathAlias function used

* Nextjs page install tests

* Fixed app directory install (with tests)

* Removed e2e CLI test, switched to unit testing strategy instead

* Latest lockfile

* The install files are now actual files that are copied and transformed

* Got the template files working correctly after building

* Next steps are now framework specific

* createFileFromTemplate now works with a path again. Uses mock if specified.

* Renamed apiRoute.js to pagesApiRoute.js

* Simplified pages file generation

* Next.js app API route template

* Next.js App routing support, with common files logic shared

* Dev command now uses framework default values if they exist and aren’t overridden

* Unused import

* pathAlias now works for all frameworks

* Added a test to detect Next from the next.config.js

* WIP on Remix framework support

* Tests for Remix install

* Replaced references to Next.js

* Use a green ✔️ instead of  in the CLI

* Support for multiple hostnames

* Tunneling can now use the hostname and port

* Work on multiple ports

* Improved the error messages. Added some extra pots to Next.js

* Update the Remix templates to have .server in the imports

* Remix updated to use server-runtime instead of node. Node v18+

* Frameworks can specify the watch paths and ignore paths

* Define the watch variables above, so we can easily log them for debugging

* Don’t wait for outdated package checking when running the dev command

* Improved the Remix manual setup guide

* Rewriting docs for quickstart

* Updated the Next.js quickstart

* Remix quick start

* Added a changeset

* Improved the Next.js manual setup

* Tweaked the Linear scopes

* Latest lockfile

* Fix for getPathAlias typecheck failure

* Linear getAll type error (weirdly not in VSCode…) and removed the pagination example that uses the SDK as won’t work with timeouts

* Add BYO auth for oauth options

* Add back in Job.toJSON to fix the testing package

* Removed dynamicTrigger @internal from toJSON

* The CLI now checks for a dev server API key in init and dev commands

* Remix onboarding now uses the CLI init command

* Decouple zod (#500)

Zod Schemas is no longer required for validating/inferring event triggers. We’ve taken inspiration from how domain-functions did it: https://github.com/seasonedcc/domain-functions/pull/114

* chore: Update version for release (#481)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Latest lockfile

* feat: Basic usage dashboard to show run volume (#501)

* New usage dashboard with static data

* Implement org usage dash

* Grab chart data for the last 12 months

* If no org is found just return undefined so a 404 will be shown

* Remove mock data

* Fill in missing months with 0s

---------

Co-authored-by: James Ritchie <james@jamesritchie.co.uk>

* Fixed duplicate end month

* hotfix

* hotfix 2

* Astro CLI support (#506)

* Astro framework CLI support

* Changeset: Added Astro automatic installation

* Fixed the package name – was remix, now astro

* Fixed the export of the example

* Added IPv6 localhost to Astro hostnames

* Updated Astro onboarding to show the CLI init command, instead of manual instructions

* Astro quickstart

* Fix for type in Remix quickstart

* Next.js framework detection allows different config file extensions and “next” devDependency

* Made the dev command port more general so it works with various frameworks

* chore: Update version for release (#508)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Fix for incorrectly named Next.js package in manual setup

* Latest lockfile

* Increased the intervalTrigger max from 1 day to 30 days

* Implement the task output redacting to prevent redacted values from showing in the logs

* Express frameworks docs + CLI (#512)

* Manual setup docs

* Added the onboarding

* The emails package now works with Node > 18

* Added CLi support for Express, including custom init command finished messages

* Need to actually log out the installation complete message…

* Fix for an old Remix reference

* Renamed the page export

* Use resolvedOptions.triggerUrl

* Typo in manual instructions

* chore: Update version for release (#513)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Latest lockfile

* Add the STAGING environment by default

* Fixed sparodically failed run creations

- Use a better way of getting the latest job run number to increment
- Make the CreateRunService transaction more reliable
- Invoke dispatchers in parallel
- No longer swallow prisma errors in $transaction

* Swapped out the Homepage link in the side menu for a link to the Changelog

* Youtube embedded video fits its aspect ratio instead of going full width

* Improved CLI init Next.js middleware detection

* CLI init: adds public key as “TRIGGER_PUBLIC_API_KEY” except for Next which overrides this

* Updated the docs for the React hooks

* chore: Update version for release (#521)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Display framework logos on the onboarding setup pages (#519)

* autofocus the search field on the Job page

* Add some documentation around canceling scheduled events

* Updated outdated lockfile

* Updated docs README.md

* Improves the performance of run resuming (#522)

* Improves the perform of run resuming

When runs resume, we try and make sure that tasks that have already been completed are cached and reused. Worst case scenario the client needs to hit the API server once for a non-cached task that is indeed completed on the server, but this can get pretty expensive when there are a larger number of tasks.

This commit does 2 different things to help:

- noop tasks are no longer “cached” using the cachedTasks strategy, instead their idempotency keys are shoved into a bloom filter and the client tests for their inclusion in the bloom filter before running them (since they don’t have any concept of output, this works)
- Additional cached tasks are lazy loaded when a task is run. This allows us to progressively fetch additional tasks to be cached on the client, which will cut down on cache misses by a decent amount

* Create warm-carrots-float.md

* Make io.yield backwards compat with older platform versions

* Better support old clients connecting to server versions that support lazy loading cached tasks

* Fixed type errors when settings headers with unknown value

* Better yield not support error message

* Rename _version to _serverVersion to be more clear

* Add typed filters to `Linear` getAll helper (#517)

* Fix getAll params type

* Changeset

* Search param types

* Update changeset

* `Replicate` integration and remote callbacks (#507)

* Support tasks with remote callbacks

* Add common integration tsconfig

* Add Replicate integration

* Basic job catalog example

* Integration catalog entry

* Check for callbackUrl during executeTask

* Fix getAll

* Improve JSDoc

* Bump version

* Remove named queue

* Simplify runTask types

* Trust the types

* Fail tasks on timeout

* Callback timeout as param

* Mess with types

* performRunExecutionV1

* Update runTask docs

* Shorten callback task methods

* Fix run method return type

* Image processing jobs

* Replicate docs

* Text output example

* Changeset

* Version bump

* Roll back ugly types

* Remove missing types

* Quicker return when waiting on remote callback

* Remote callback example

* Bump version

* Remove schema parsing

* Only schedule positive callback timeout

* Decrease callback secret length

* Explicit default timeouts

* Import deployments tasks

* JSDoc

* Deployments docs

* Fix runTask examples, mention wrappers

---------

Co-authored-by: Eric Allam <eric@trigger.dev>

* Update pnpm lock file

* Allow blank issues

* chore: Update version for release (#538)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Fix pnpm lock file

* feat: New Test page (#558)

* Improvements to the shortcut keys

* Updated code mirror theme to the new dark mode style

* Removed the old test page help panel copy

* WIP new structure for the test page

* Added some of the side panel options for examples and account ID

* Conditionally hide the side panel components if they’re blank

* Example with selected state working

* Allow selecting the example again to overwrite any edits

* Previous run payloads working

* Select a recent payload if there’s no example

* Created Icon and DetailCell components

* The integrations now use the DetailCell

* Use DetailCell on the integrations page

* Added support for description to DetailCell. With proper variants now

* DateTimeAccurate and formatDateTimeAccurate weren’t displaying correctly.

fractionalSecondDigits isn’t in the types, but is supported for 92.5% of users

* DetailCell now allows label and description to be React components

* Using the DetailCell on the Test page

* Styled the CodeMirror scrollbars to match elsewhere

* Adding copy and clear to the JSONEditor, not working properly yet though

* Removed the copy/clear buttons from the Test route

* Delete the light color theme

* The editor now supports copying/clearing etc

* Made it clear when text is copied

* Changed the learn link to a tertiary button

* Fixed CMD shortcut keys

* Run test button now works with ⌘ Enter

* CodeMirror now allows ⌘Enter to escape the field

* Added JSON linter to the test editor

* Fix for buttons not being aligned correctly

* Copy/clear buttons now aligned

* Made the integration DetailCell text smaller

* The test recent payloads now have colored text to help identify the status

* DetailCell descriptions are dimmer

* Added link to docs for BYOA

* Fix for buttons going full width when they shouldn’t

---------

Co-authored-by: James Ritchie <james@jamesritchie.co.uk>

* chore: update doc title for groups (#539)

* chore: update doc title for groups

* update docs for sdk and integrations

* Add instructions for triggering job runs to the job catalog readme

* Updated the Test docs

* Removed a console.log when a user’s file is changed that CLI dev is listening for

* feat: allow cancelling jobs from trigger-client sdk (#562)

* feat: allow cancelling jobs from trigger-client sdk

* use presenter instead of service for non-mutating logic

* chore: upgrade zod to 3.22.3 (#570)

* chore: upgrade zod to 3.22.3

* add changeset

* Created a changeset with the correct starting package version

* Added headers to NestJS response

* Added some types to the NestJS project

* Added fastify types

* Removed log from CodeMirror

* Added InstallPackages component

* Improved the NestJS onboarding instructions

* Updated the onboarding instructions

* Made all the quickstart framework cards snippets, so the page isn’t a nightmare to edit

* NestJS docs updates

* Added dotenv to the earlier code sample

* Latest lockfile

* Moved the nestjs-example to the reference folder

---------

Co-authored-by: Vinícius Lourenço <contact@viniciusl.com.br>
Co-authored-by: Wesley <100464352+ologbonowiwi@users.noreply.github.com>
Co-authored-by: Vishesh Rawal <92795514+visheshrwl@users.noreply.github.com>
Co-authored-by: Eric Allam <eallam@icloud.com>
Co-authored-by: Aniket Bindhani <aniketbindhani44@gmail.com>
Co-authored-by: James Ritchie <james@trigger.dev>
Co-authored-by: D-K-P <dkp.github@pm.me>
Co-authored-by: Gregory <93215236+gjohnsx@users.noreply.github.com>
Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: James Ritchie <james@jamesritchie.co.uk>
Co-authored-by: Hemachandar <132386067+hmacr@users.noreply.github.com>
2023-10-06 12:27:15 +01:00
Eric Allam 0df6410561 Need to properly format the payload JSON
🚀 Publish Trigger.dev Docker / ʦ TypeScript (push) Has been cancelled
🚀 Publish Trigger.dev Docker / Unit Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / e2e Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / publish (push) Has been cancelled
2023-10-06 11:53:12 +01:00
Eric Allam c17faabe9f Stringify event payload and context before serialization
This fixes an issue where an event payload was being serialized through remix-typedjson and was causing issues with incorrect meta keys and so deserialization was failing. See https://github.com/kiliman/remix-typedjson/pull/33 for more
2023-10-06 11:21:14 +01:00
Hemachandar 9a187f9eda chore: upgrade zod to 3.22.3 (#570)
* chore: upgrade zod to 3.22.3

* add changeset
2023-10-05 17:00:33 +01:00
Hemachandar 2e9452ab7c feat: allow cancelling jobs from trigger-client sdk (#562)
* feat: allow cancelling jobs from trigger-client sdk

* use presenter instead of service for non-mutating logic
2023-10-05 16:51:59 +01:00
Matt Aitken 914745f642 Removed a console.log when a user’s file is changed that CLI dev is listening for
🚀 Publish Trigger.dev Docker / ʦ TypeScript (push) Has been cancelled
🚀 Publish Trigger.dev Docker / Unit Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / e2e Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / publish (push) Has been cancelled
2023-10-05 16:49:06 +01:00
Matt Aitken 9189bdf50f Updated the Test docs 2023-10-05 14:42:32 +01:00
Eric Allam 3e5a97c4b5 Add instructions for triggering job runs to the job catalog readme 2023-10-05 12:47:40 +01:00
Hemachandar c0aa6633d2 chore: update doc title for groups (#539)
* chore: update doc title for groups

* update docs for sdk and integrations
2023-10-05 11:54:09 +01:00
Matt Aitken 4e35871861 feat: New Test page (#558)
* Improvements to the shortcut keys

* Updated code mirror theme to the new dark mode style

* Removed the old test page help panel copy

* WIP new structure for the test page

* Added some of the side panel options for examples and account ID

* Conditionally hide the side panel components if they’re blank

* Example with selected state working

* Allow selecting the example again to overwrite any edits

* Previous run payloads working

* Select a recent payload if there’s no example

* Created Icon and DetailCell components

* The integrations now use the DetailCell

* Use DetailCell on the integrations page

* Added support for description to DetailCell. With proper variants now

* DateTimeAccurate and formatDateTimeAccurate weren’t displaying correctly.

fractionalSecondDigits isn’t in the types, but is supported for 92.5% of users

* DetailCell now allows label and description to be React components

* Using the DetailCell on the Test page

* Styled the CodeMirror scrollbars to match elsewhere

* Adding copy and clear to the JSONEditor, not working properly yet though

* Removed the copy/clear buttons from the Test route

* Delete the light color theme

* The editor now supports copying/clearing etc

* Made it clear when text is copied

* Changed the learn link to a tertiary button

* Fixed CMD shortcut keys

* Run test button now works with ⌘ Enter

* CodeMirror now allows ⌘Enter to escape the field

* Added JSON linter to the test editor

* Fix for buttons not being aligned correctly

* Copy/clear buttons now aligned

* Made the integration DetailCell text smaller

* The test recent payloads now have colored text to help identify the status

* DetailCell descriptions are dimmer

* Added link to docs for BYOA

* Fix for buttons going full width when they shouldn’t

---------

Co-authored-by: James Ritchie <james@jamesritchie.co.uk>
2023-10-05 10:38:28 +01:00
Eric Allam 90f52de147 Fix pnpm lock file 2023-10-04 14:01:48 +01:00
github-actions[bot] 28b05a82d8 chore: Update version for release (#538)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-10-04 14:00:20 +01:00
Eric Allam b9ed7e2ced Allow blank issues 2023-10-04 13:21:38 +01:00
Eric Allam 5e651d84af Update pnpm lock file
🚀 Publish Trigger.dev Docker / ʦ TypeScript (push) Has been cancelled
🚀 Publish Trigger.dev Docker / Unit Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / e2e Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / publish (push) Has been cancelled
2023-10-04 11:00:55 +01:00
nicktrn 6a992a1995 Replicate integration and remote callbacks (#507)
* Support tasks with remote callbacks

* Add common integration tsconfig

* Add Replicate integration

* Basic job catalog example

* Integration catalog entry

* Check for callbackUrl during executeTask

* Fix getAll

* Improve JSDoc

* Bump version

* Remove named queue

* Simplify runTask types

* Trust the types

* Fail tasks on timeout

* Callback timeout as param

* Mess with types

* performRunExecutionV1

* Update runTask docs

* Shorten callback task methods

* Fix run method return type

* Image processing jobs

* Replicate docs

* Text output example

* Changeset

* Version bump

* Roll back ugly types

* Remove missing types

* Quicker return when waiting on remote callback

* Remote callback example

* Bump version

* Remove schema parsing

* Only schedule positive callback timeout

* Decrease callback secret length

* Explicit default timeouts

* Import deployments tasks

* JSDoc

* Deployments docs

* Fix runTask examples, mention wrappers

---------

Co-authored-by: Eric Allam <eric@trigger.dev>
2023-10-04 10:46:17 +01:00
nicktrn 81e886a1ba Add typed filters to Linear getAll helper (#517)
* Fix getAll params type

* Changeset

* Search param types

* Update changeset
2023-10-03 16:48:21 +01:00
Eric Allam ab9e4a989c Improves the performance of run resuming (#522)
* Improves the perform of run resuming

When runs resume, we try and make sure that tasks that have already been completed are cached and reused. Worst case scenario the client needs to hit the API server once for a non-cached task that is indeed completed on the server, but this can get pretty expensive when there are a larger number of tasks.

This commit does 2 different things to help:

- noop tasks are no longer “cached” using the cachedTasks strategy, instead their idempotency keys are shoved into a bloom filter and the client tests for their inclusion in the bloom filter before running them (since they don’t have any concept of output, this works)
- Additional cached tasks are lazy loaded when a task is run. This allows us to progressively fetch additional tasks to be cached on the client, which will cut down on cache misses by a decent amount

* Create warm-carrots-float.md

* Make io.yield backwards compat with older platform versions

* Better support old clients connecting to server versions that support lazy loading cached tasks

* Fixed type errors when settings headers with unknown value

* Better yield not support error message

* Rename _version to _serverVersion to be more clear
2023-10-03 16:44:18 +01:00
Matt Aitken e350659e24 Updated docs README.md 2023-10-02 14:26:54 +01:00
Eric Allam f888a49555 Updated outdated lockfile 2023-09-30 22:20:34 +01:00
Eric Allam 421c249e50 Add some documentation around canceling scheduled events 2023-09-30 22:18:52 +01:00
James Ritchie a8a6f51387 autofocus the search field on the Job page 2023-09-29 18:23:22 +01:00
James Ritchie 12e73eef22 Display framework logos on the onboarding setup pages (#519) 2023-09-29 16:44:35 +01:00
github-actions[bot] 2e33fcb16b chore: Update version for release (#521)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-09-29 16:42:53 +01:00
Matt Aitken 5912cdd11c Updated the docs for the React hooks 2023-09-29 15:37:53 +01:00
Matt Aitken cc016b3ae3 CLI init: adds public key as “TRIGGER_PUBLIC_API_KEY” except for Next which overrides this 2023-09-29 15:14:52 +01:00
Matt Aitken 7760e09462 Improved CLI init Next.js middleware detection 2023-09-29 11:26:29 +01:00
James Ritchie 3ca4456c88 Youtube embedded video fits its aspect ratio instead of going full width
🚀 Publish Trigger.dev Docker / ʦ TypeScript (push) Has been cancelled
🚀 Publish Trigger.dev Docker / Unit Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / e2e Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / publish (push) Has been cancelled
2023-09-28 17:37:07 +01:00
James Ritchie 618b7f22da Swapped out the Homepage link in the side menu for a link to the Changelog 2023-09-28 17:27:21 +01:00
Eric Allam a12c7c3b0a Fixed sparodically failed run creations
- Use a better way of getting the latest job run number to increment
- Make the CreateRunService transaction more reliable
- Invoke dispatchers in parallel
- No longer swallow prisma errors in $transaction
2023-09-28 17:08:26 +01:00
Eric Allam a42e94c75f Add the STAGING environment by default
🚀 Publish Trigger.dev Docker / ʦ TypeScript (push) Has been cancelled
🚀 Publish Trigger.dev Docker / Unit Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / e2e Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / publish (push) Has been cancelled
2023-09-27 18:17:19 +01:00
Matt Aitken bc757c8ddb Latest lockfile 2023-09-27 18:12:54 +01:00
github-actions[bot] 6e11ab9183 chore: Update version for release (#513)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-09-27 18:09:16 +01:00
Matt Aitken 2397fcb640 Express frameworks docs + CLI (#512)
* Manual setup docs

* Added the onboarding

* The emails package now works with Node > 18

* Added CLi support for Express, including custom init command finished messages

* Need to actually log out the installation complete message…

* Fix for an old Remix reference

* Renamed the page export

* Use resolvedOptions.triggerUrl

* Typo in manual instructions
2023-09-27 17:44:50 +01:00
Eric Allam 35d0c2a06f Implement the task output redacting to prevent redacted values from showing in the logs 2023-09-27 16:38:30 +01:00
Matt Aitken 813ec74672 Increased the intervalTrigger max from 1 day to 30 days
🚀 Publish Trigger.dev Docker / ʦ TypeScript (push) Has been cancelled
🚀 Publish Trigger.dev Docker / Unit Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / e2e Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / publish (push) Has been cancelled
2023-09-26 17:23:36 +01:00
Matt Aitken 03db13171a Latest lockfile 2023-09-26 16:46:41 +01:00
Matt Aitken 0ecb5129e8 Fix for incorrectly named Next.js package in manual setup 2023-09-26 12:47:49 +01:00
github-actions[bot] 44cb28c1c4 chore: Update version for release (#508)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-09-26 11:49:03 +01:00
Matt Aitken 4578f6bd64 Astro CLI support (#506)
* Astro framework CLI support

* Changeset: Added Astro automatic installation

* Fixed the package name – was remix, now astro

* Fixed the export of the example

* Added IPv6 localhost to Astro hostnames

* Updated Astro onboarding to show the CLI init command, instead of manual instructions

* Astro quickstart

* Fix for type in Remix quickstart

* Next.js framework detection allows different config file extensions and “next” devDependency

* Made the dev command port more general so it works with various frameworks
2023-09-26 11:44:35 +01:00
Eric Allam 8b25e57613 hotfix 2 2023-09-24 14:43:02 -07:00
Eric Allam 8fb9ea19a3 hotfix 2023-09-24 14:04:46 -07:00
Eric Allam eb4ca0ce2d Fixed duplicate end month
🚀 Publish Trigger.dev Docker / ʦ TypeScript (push) Has been cancelled
🚀 Publish Trigger.dev Docker / Unit Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / e2e Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / publish (push) Has been cancelled
2023-09-22 17:24:55 -07:00
Eric Allam df24cd5b71 feat: Basic usage dashboard to show run volume (#501)
* New usage dashboard with static data

* Implement org usage dash

* Grab chart data for the last 12 months

* If no org is found just return undefined so a 404 will be shown

* Remove mock data

* Fill in missing months with 0s

---------

Co-authored-by: James Ritchie <james@jamesritchie.co.uk>
2023-09-22 17:02:53 -07:00
Matt Aitken 284324031c Latest lockfile 2023-09-22 16:23:21 -07:00
github-actions[bot] 2fdf42d444 chore: Update version for release (#481)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-09-22 16:20:21 -07:00
Eric Allam 50137a6f24 Decouple zod (#500)
🚀 Publish Trigger.dev Docker / ʦ TypeScript (push) Has been cancelled
🚀 Publish Trigger.dev Docker / Unit Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / e2e Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / publish (push) Has been cancelled
Zod Schemas is no longer required for validating/inferring event triggers. We’ve taken inspiration from how domain-functions did it: https://github.com/seasonedcc/domain-functions/pull/114
2023-09-22 14:44:03 -07:00
Matt Aitken 3703f989fa Remix onboarding now uses the CLI init command 2023-09-22 14:39:21 -07:00
Matt Aitken 2a42942b01 The CLI now checks for a dev server API key in init and dev commands 2023-09-22 13:37:59 -07:00
Matt Aitken 7b29a92f6a Removed dynamicTrigger @internal from toJSON 2023-09-22 12:24:07 -07:00
Eric Allam 24465c9a7b Add back in Job.toJSON to fix the testing package 2023-09-22 11:21:37 -07:00
Eric Allam 42022b6ba4 Add BYO auth for oauth options 2023-09-22 10:31:40 -07:00
Matt Aitken dcc807d716 Linear getAll type error (weirdly not in VSCode…) and removed the pagination example that uses the SDK as won’t work with timeouts 2023-09-22 10:23:24 -07:00
Matt Aitken b5e37bfa61 Fix for getPathAlias typecheck failure 2023-09-22 09:59:59 -07:00
Matt Aitken 5681ebc756 Latest lockfile 2023-09-22 09:53:30 -07:00
Matt Aitken 886d6fda36 Tweaked the Linear scopes 2023-09-22 09:51:49 -07:00
Matt Aitken 1a4952720f CLI now supports multiple frameworks (with tests) (#480)
* Early work defining CLI framework support

* WIP moving CLI init logic to the Framework class

* Installing files should now work for Nextjs

* Some fixes

* WIP creating unit tests for Next.js project detection

* Delete old jest config

* Latest lockfile

* Detect use of src directory test

* Tests for detection pages/app directory

* Correct detection of Next.js project

* Renamed test file

* Create install files from template files with replacements. With tests

* Added multiple uses of the same replacement

* Created a test for the install step (it fails right now with JS)

* Removed unused import

* Another test that should pass but currently fails…

* Path alias fixed and now has tests

* New pathAlias function used

* Nextjs page install tests

* Fixed app directory install (with tests)

* Removed e2e CLI test, switched to unit testing strategy instead

* Latest lockfile

* The install files are now actual files that are copied and transformed

* Got the template files working correctly after building

* Next steps are now framework specific

* createFileFromTemplate now works with a path again. Uses mock if specified.

* Renamed apiRoute.js to pagesApiRoute.js

* Simplified pages file generation

* Next.js app API route template

* Next.js App routing support, with common files logic shared

* Dev command now uses framework default values if they exist and aren’t overridden

* Unused import

* pathAlias now works for all frameworks

* Added a test to detect Next from the next.config.js

* WIP on Remix framework support

* Tests for Remix install

* Replaced references to Next.js

* Use a green ✔️ instead of  in the CLI

* Support for multiple hostnames

* Tunneling can now use the hostname and port

* Work on multiple ports

* Improved the error messages. Added some extra pots to Next.js

* Update the Remix templates to have .server in the imports

* Remix updated to use server-runtime instead of node. Node v18+

* Frameworks can specify the watch paths and ignore paths

* Define the watch variables above, so we can easily log them for debugging

* Don’t wait for outdated package checking when running the dev command

* Improved the Remix manual setup guide

* Rewriting docs for quickstart

* Updated the Next.js quickstart

* Remix quick start

* Added a changeset

* Improved the Next.js manual setup
2023-09-22 08:55:04 -07:00
Eric Allam c0dfa8048a feat: BYO Auth (#491)
* feat: BYO Auth

Define client-side auth resolvers to be able to supply custom authentication credentials for integrations before a run is performed

- Added new defineAuthResolver
- Update all integrations to support the new auth resolvers
- Strip internal symbols from .d.ts in integrations and trigger-sdk
- Added BYO Auth docs
- Update Dynamic Schedule to support associated account IDs
- Create external accounts just-in-time
- Added Account ID field to test job when there are external auth integrations
- Show Account ID on run dashboard
- Added new Run error state called “Unresolved auth”

* Added changeset

* Remove @internal from TriggerIntegration public methods

* Add void to the result union

* DynamicTriggers now work with the new BYO auth system, and added a bunch of docs and docs changes

* Add additional key material for registering dynamic trigger task

* Add new define* instance methods to the overview
2023-09-22 08:54:31 -07:00
nicktrn 3e63a7e7a0 fix: Fail client-side on invalid Stripe event names (#492)
* Parse event names

* Add changeset
2023-09-22 08:53:04 -07:00
Eric Allam 4cc690a6ce Update sendevent.mdx 2023-09-22 08:44:14 -07:00
nicktrn 537447e318 Use absolute image paths (#490) 2023-09-21 15:45:40 -07:00
nicktrn 15f17d27e0 Going exponential with Linear (#478)
* Unleash GPT magic

* Clean up after GPT

* All the hooks

* Provisional integration catalog entry

* Sample webhook jobs

* Attachments with alpha warnings

* Remove some verbose logs

* Fix IP restrictions

* Remove tunnel

* Revert "Remove tunnel"

This reverts commit c5b69ce6524e3b40c26b66cdc56e087b8576b8c6.

* Resolve event name clashes

* Remove circular dependency

* Use correct payload uuid

* Schema fixes

* Fix webhook event name

* Start to Linearify catalog entry

* Remove todo

* More catalog updates

* Make OAuth work

* Rename webhook helper

* Schema juggling

* More discrimination

* Add Issue SLA event

* Simplify triggers

* Handle rate limits

* Fix Project schema

* Payload examples

* Improve event props

* Remove redundant source metadata

* One type to rule them all

* Recursive WithoutFunctions type

* Linear output serializer

* Some tasks

* Update catalog entry

* Dynamic usage sample

* Bump version

* Remove tunnel

* More tasks

* Add optional skipRetrying on runTask errors

* Fail fast on user errors

* Entity getter tasks

* Another couple of tasks

* Token to apiKey

* Sort tasks

* Add filtered issue SLA triggers

* Add docs

* Type fixes

* Job catalog examples

* Serialization helper docs

* Add changeset

* Refactor webhooks

* Enhance properties

* Pagination helper and docs

* Clean up imports

* Change misc catalog job

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2023-09-21 15:14:54 -07:00
Matt Aitken 91fc1e80f3 Use the bell icon for the new status Tasks
🚀 Publish Trigger.dev Docker / ʦ TypeScript (push) Has been cancelled
🚀 Publish Trigger.dev Docker / Unit Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / e2e Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / publish (push) Has been cancelled
2023-09-21 15:01:35 -07:00
Gregory dfe680a390 Update introduction.mdx (#498)
🚀 Publish Trigger.dev Docker / ʦ TypeScript (push) Has been cancelled
🚀 Publish Trigger.dev Docker / Unit Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / e2e Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / publish (push) Has been cancelled
Changed https://github.com/triggerdotdev/examples/tree/main/resend (which was a 404) to https://github.com/triggerdotdev/examples/tree/main/resend-email-form
2023-09-21 14:06:14 -07:00
Matt Aitken f73a2a424b Revert "Upgrade to the latest remix (pre v2)"
This reverts commit 4edc7112ab.
2023-09-21 13:19:03 -07:00
Matt Aitken 6ce87f169a Fixed dependency 2023-09-21 11:35:12 -07:00
Matt Aitken ad14983e21 React status hooks (#493)
* Added stripInternal to SDK tsconfig

* Statuses can now be set from a run, and are stored in the database

* Added the key to the returned status

* Made the test job have an extra step and only pass in some of the options

* client.getRunStatuses() and the corresponding endpoint

* client.getRun() now includes status info

* Fixed circular dependency schema

* Translate null to undefined

* Added the react package to the nextjs-reference tsconfig

* Removed unused OpenAI integration from nextjs-reference project

* New hooks for getting the statuses

* Disabled most of the nextjs-reference jobs

* Updated the hooks UI

* Updated the endpoints to deal with null statuses values

* The hook is working, with an example

* Changeset: “You can create statuses in your Jobs that can then be read using React hooks”

* Changeset config is back to the old changelog style

* WIP on new React hooks guide

* Guide docs for the new hooks

* Added the status hooks to the React hooks guide

* Removed the links to the status hooks reference for now

* Re-ordered the hooks

* Fix for an error in the docs

* Set a default of a blank array for the GetRunSchema
2023-09-21 10:24:37 -07:00
Eric Allam 4edc7112ab Upgrade to the latest remix (pre v2) 2023-09-18 22:20:41 +01:00
D-K-P c2ce707f3d Fixed cal.com link 2023-09-18 13:54:53 +01:00
Eric Allam cd70a29970 Improve the Astro manual setup guide 2023-09-15 17:40:36 +01:00
Eric Allam cd94d8fee2 Fixes broken pnpm lock file 2023-09-15 16:17:53 +01:00
Eric Allam 241e40e3e2 Add a references README 2023-09-15 16:12:50 +01:00
Eric Allam 486ed20ae7 Renamed the examples dir to references (true examples are in another repo and this was confusing) 2023-09-15 16:09:04 +01:00
James Ritchie e5ffc3a3f3 Added a link to the homepage from the side menu (#479)
* Added 2 new named icons

* New side menu link to the homepage

* Updated lock file

* Removed un-used import
2023-09-15 15:11:40 +01:00
Aniket Bindhani 363c74c6da Documentation Update: Added <github_username> instead of triggerdotdev to avoid confusion while cloning the repository (#477) 2023-09-15 12:55:56 +01:00
Eric Allam f98c425186 Redirect people to discord to ask a question 2023-09-15 12:54:54 +01:00
Matt Aitken da10ba907f Added instructions for how to do Changeset snapshots 2023-09-15 12:54:38 +01:00
Eric Allam 5aeef1233b A few teaks to the templates 2023-09-15 12:52:29 +01:00
Vishesh Rawal fb5f4e308f Created Temp for pull req, bugreport & feature req 2023-09-15 12:52:29 +01:00
Wesley 6ccb4fbc63 test/368/use vitest instead of jest (#470)
* chore: add vitest dependencies

* refactor: replace jest by vitest

* test: disable broken test

* Update pnpm-lock.yaml

* Update pnpm-lock.yaml

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2023-09-15 12:51:25 +01:00
Matt Aitken 88ebf4a1a0 Updated the Astro docs with SSR notes 2023-09-14 15:25:43 +01:00
Matt Aitken 9a0e6412e9 Bumped package versions to 2.1.3 2023-09-14 13:37:02 +01:00
Matt Aitken a68a912d56 Docs: improved the limitations 2023-09-14 11:55:51 +01:00
Matt Aitken dde51d6d25 Astro docs improvements 2023-09-14 11:55:38 +01:00
Matt Aitken dbd094216d Updated Astro setup docs: env import 2023-09-14 11:14:35 +01:00
Matt Aitken dc7f335beb Latest lockfile 2023-09-14 09:22:05 +01:00
github-actions[bot] 454cad69b4 chore: Update version for release (#473)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-09-13 18:07:22 +01:00
Matt Aitken f86117f92b Some improvements to the docs platforms section 2023-09-13 18:05:34 +01:00
Matt Aitken b4c67984bc Latest lockfile 2023-09-13 17:57:22 +01:00
Chigala 1b4db79885 Feat/astro support (#466)
* updated the @trigger.dev/astro package to support typescript

* set up a example astro project

* docs: manual setup of Trigger.dev in an Astro project

* doc: updated the manual setup docs for astro

* updated the webapp onboarding for astro

* cleaned up the example astro project

* removed next from dependency 😅

* updated the readme

* moved trigger.ts file and job folder to src directory

* created a .env.example file

* updated tsconfig

* updated to use aliases

* updated package.json

* updated the astro onboarding page

* updated the manual installation guide for astro

* updated to use alias

* added astro as  a dev dependency

* Remove extra comma I left in

* Changed Object.create() to a Record, so we have some type safety

* Added the localhost URL to the API in the Astro example

* Added the TRIGGER_API_URL to the trigger client in the example

* Added the CLI dev dependency to the Astro example

* Update the running instructions to be closer to Remix's

* Create friendly-carpets-collect.md

* Fix bad package name for Astro

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2023-09-13 17:55:33 +01:00
Matt Aitken e1e60499b2 Fix for incorrect remix package name in docs
🚀 Publish Trigger.dev Docker / ʦ TypeScript (push) Has been cancelled
🚀 Publish Trigger.dev Docker / Unit Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / e2e Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / publish (push) Has been cancelled
2023-09-13 15:41:24 +01:00
Matt Aitken 4eb2439d64 Don’t check for the page title in verify jobs e2e test 2023-09-13 13:57:35 +01:00
Matt Aitken 2895ad52fd Re-run the publish workflow when the test have been updated 2023-09-13 13:56:44 +01:00
Matt Aitken a73b842c60 Latest lockfile 2023-09-13 13:42:00 +01:00
github-actions[bot] cfa3e24123 chore: Update version for release (#444)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-09-13 13:38:03 +01:00
Matt Aitken b2670f5948 @examples/unit-testing shouldn’t be in a changeset 2023-09-13 13:34:01 +01:00
Matt Aitken 5a93aa6fa1 Updated e2e tests because of text changes 2023-09-13 13:29:56 +01:00
Matt Aitken 6b471489b0 Fix for typecheck problem with Remix example 2023-09-13 12:09:51 +01:00
Matt Aitken 07d68a3289 Latest lockfile 2023-09-13 11:19:09 +01:00
Ravan bf24593b7f fix: Added retry config and showed error from subtask in web (#468)
* fix: Added retry config and showed error from subtask in web

* Still fallback to "Task errored" if there's no output

* Create rude-carrots-enjoy.md

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2023-09-12 16:25:29 +01:00
Matt Aitken f52ecb9a84 Removed unused component 2023-09-11 19:20:35 +01:00
Matt Aitken 711019032f Added the SDK to webapp tsconfig 2023-09-11 19:20:30 +01:00
Matt Aitken 68c3c89824 Added className to StepContentContainer. Was missing in a PR I merged… agh 2023-09-11 19:12:42 +01:00
Chigala b00717748b Feat/remix support (#465)
* init remix project

* feat: implemented the remix adapter package

* updated the remix package to return the action variable

* added an example job to the example remix project

* fix: Ensure Side Effects Execution in Remix API Routes

* updated the readme in @trigger.dev/remix package

* doc: added the manual setup guide for remix

* updated the webapp onboarding for remix

* updated the manual setup guide

* added a license to the @trigger.dev/remix package

* added a wait function to the example job

* added a link to the remix webapp onboarding

* Updated the onboarding page

For now, we'll only support existing projects. The button that links to the manual installation was just a blank rectangle – added some text to it.

* Added the Server API key to the instructions

* Remix manual docs

Made some things a bit clearer
- file paths
- exporting the job rather than using a function wrapper
- how to run the app and CLI dev command

* Export the job

* Update api.trigger.ts

* Added tsconfig.json paths

* Remove next dependency

* Package set to 2.1.0 and set dependencies

Shouldn't rely on a specific version in main dependencies. In this case we can just have devDependency for @remix/node

* Changeset

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2023-09-11 18:09:43 +01:00
arika 7833db45d7 feat: add proxy support to the CLI (#404)
* feat: add proxy support for node-fetch

This process is expected to allow the CLI and SDK to work in environments where proxy is enabled.

* Revert "feat: add proxy support for node-fetch"

This reverts commit c850030b5927c562921409fc5b798af353a7ac6b.

* feat: add proxy support for node-fetch (CLI only)

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2023-09-11 13:56:55 +01:00
nicktrn 6de8bd470b Add @trigger.dev/testing package (#432)
* feat: add testing package

* feat: add unit testing example

* Delete examples/unit-testing/dummy-integration/tasks.ts

* Delete examples/unit-testing/dummy-integration/types.ts

* Update DummyIntegration to new format

* Update testing package to new integration format

* Update readme to new task spy format

* Create rotten-meals-cough.md

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2023-09-11 13:38:05 +01:00
hrutik7 1d4e31138e Update nextjs.mdx (#458)
note about next 13.4.4 #423
2023-09-10 18:01:31 +01:00
Matt Aitken a93fba932c Caught another runTask param order update 2023-09-10 17:54:58 +01:00
Matt Aitken 6d29914327 Clarified the webhook response 2023-09-10 17:48:19 +01:00
Matt Aitken bd0b335c1e Added docs on how to create a webhook handler 2023-09-10 17:41:33 +01:00
Matt Aitken 82c5965e8a Some docs on how to create Triggers in integrations 2023-09-08 20:09:15 +01:00
James Ritchie 65fa8300ad Support for more frameworks (#446)
* Removed next references in the ReadMe

* FAQ improvements to update Next.js references

* Added a new Frameworks page with logos to link to the quick start guides

* Renamed the mdx file so the link works

* Added basic platform guides

* Introduction doesn’t reference next.js only

* Added a note about serverless and restructured the side menu

* Added more frameworks pages to the manual install section

* Fixed SVG error

* Coming soon guides now using snippets so they can be in 2 places while we work on them

* Removed redirects

* Added a new named icon

* increased fireworks particle count slightly

* Creating a route for the onboarding and link to access it anytime from the side menu

* Moved the onboarding into new components

* Updated the routes for the onboarding page

* Onboarding is now Setup and the frameworks overview page now links to different framework page in the onboarding side nav

* URLs and pages renamed to ‘setup’

* URLs and pages renamed to ‘setup’

* Fixed some old named component imports

* WIP on a new less hacked-in background image

* Added svg logos for all the frameworks

* New paths for the new framework pages

* Side menu collapses once you selected a framework

* Temporary Nuxt page

* New routes for the new frameworks

* New ‘framework coming soon’ component - now used in the coming soon framework pages

* Moved/removed files

* Moved all svg framework logos into a new folder and file

* balanced the logo sizes

* Framework coming soon pages take a name and url

* New express svg logo

* New component for a Framework item in the grid

* Added information and design for the coming soon frameworks

* Change the grid to 1 row if jobs === 0

* Updated the framework coming soon snippet and added it to the relevant pages

* Express now 2nd in all lists

* Added link to long running server support discussion

* New logo to include next.js + supabase quick start

* roadmap now links to homepage with page anchor to roadmap section

* changelog now links to Github releases page

* Removed reference to Next.js

* Docs pages with coming soon info all share the same framework snippets

* Fixed issue of missing props

* Moved the fireworks effect into a separate file to make it easier for adding more framework onboarding pages

* Info callouts have a more muted style

* Added a callout to the top of the next onboarding to reference Serverless-only support

* Moved the callout explaining scheduled triggers not working in dev to the bottom of the test panel

This is to resolve eric’s UX ticket: https://github.com/triggerdotdev/trigger.dev/issues/416

* Added groundwork for Nest.js framework

* Using framer motion for the menu transition instead of css - now has a slight spring and is snappier

* redirect the manual setup page to the new nextjs setup page

* Fixed broken docs link

* Added a readme.md to next.js package

* Capital I for integration

* Renamed component: NextDevCommand to RunDevCommand

* Made required props non-optional

* CLI now points at manual install guides if no Next project detected

* Explicitly made supported default to false (it was working but a bit hard to read)

* Added links to all github issues for the frameworks coming soon component

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2023-09-08 17:26:08 +01:00
D-K-P aae143d96e Changed examples job / project table 2023-09-08 12:33:18 +01:00
Bryan Eaton 315b94d05b Fix crontrigger.mdx link to /docs/sdk/job (#433) 2023-09-08 11:52:51 +01:00
Dan 440560976d Added progress table to the readme (#438)
* Added ‘our progress’ table to the readme

* Added link to the connect discussion to the progress table

* Removed link from "Polling Triggers"

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2023-09-08 11:50:40 +01:00
arika 5c1e002233 Fix: Magic link login not working properly when booted from docker (#390)
* fix: use NODE_ENV when starting from docker image

When starting from `pnpm run start`, NODE_ENV is fixed to production, causing problems like #186.
So, I added `start_docker`, a process dedicated to docker, and started from it.
The process is exactly the same as `start` except that NODE_ENV is not overwritten.

* fix: align execution name with others

* Change: command name to match review
2023-09-08 11:06:06 +01:00
Matt Aitken 36f2ece44c Latest lockfile 2023-09-07 17:54:09 +01:00
Matt Aitken 316bf9f3c2 Updated the create integration docs for the new integration structure (no trigger docs yet) 2023-09-07 17:52:27 +01:00
Matt Aitken a57221bbfe Removed the log 2023-09-07 14:04:41 +01:00
Matt Aitken 39b8445e06 CLI create-integration command updated with new OpenAI prompts to match new integrations 2023-09-07 14:03:55 +01:00
Matt Aitken 33ecb36be1 Updating the create-integration command for new integrations 2023-09-07 13:10:56 +01:00
Matt Aitken a00fbe421a Fixed GitHub usage example
🚀 Publish Trigger.dev Docker / ʦ TypeScript (push) Has been cancelled
🚀 Publish Trigger.dev Docker / Unit Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / e2e Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / publish (push) Has been cancelled
2023-09-07 10:49:38 +01:00
Matt Aitken c0edeca5cc Airtable docs page 2023-09-07 09:35:22 +01:00
Matt Aitken 7ac7d83c3e Docs: integrations alphabetical in the sidebar, and removed folders where they weren’t used 2023-09-07 09:16:22 +01:00
Matt Aitken 3d1b6c236a Added Typescript devDependency to react, nextjs and integration-kit so they pass a typecheck 2023-09-06 18:35:12 +01:00
Matt Aitken 8ddd151051 Re-ordered runTask params in docs, and example Jobs in the app. 2023-09-06 18:31:50 +01:00
Matt Aitken 9947383f5a Updated lockfile for package release 2023-09-06 16:07:43 +01:00
github-actions[bot] 46e1a1493b chore: Update version for release (#440)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-09-06 16:06:53 +01:00
Matt Aitken b1cdbf52d6 Exited package prerelease mode 2023-09-06 15:53:40 +01:00
Matt Aitken 1491d4251d Set the Airtable integration examples to something useful 2023-09-06 15:50:52 +01:00
Eric Allam 62ac5dd137 Fixed the healthcheck endpoint (hopefully) on https
🚀 Publish Trigger.dev Docker / ʦ TypeScript (push) Has been cancelled
🚀 Publish Trigger.dev Docker / Unit Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / e2e Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / publish (push) Has been cancelled
2023-09-06 13:35:43 +01:00
Matt Aitken 23c93a5712 Latest lockfile 2023-09-05 19:12:56 +01:00
github-actions[bot] 208907e10e chore: Update version for release (beta) (#437)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-09-05 18:55:35 +01:00
Matt Aitken 3ef588e4e5 Supabase changeset: Don't retry enableDatabaseWebhooks 2023-09-05 18:01:11 +01:00
Matt Aitken 10836735be Supabase SDK tsconfig now matches OpenAI. enableDatabaseWebhooks doesn’t retry 2023-09-05 18:00:25 +01:00
Matt Aitken 090bc2e7d2 OverridableRunTaskOptions allows integrations to expose override task options to users 2023-09-05 17:59:46 +01:00
Matt Aitken 4fe2fd63de Latest lockfile 2023-09-05 17:00:27 +01:00
github-actions[bot] 145fb24e4d chore: Update version for release (beta) (#434)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-09-05 16:48:28 +01:00
Matt Aitken 2382d4a5c5 Added patch back in 2023-09-05 16:29:23 +01:00
Matt Aitken adbcfe6f20 Use experimental changeset peer dependency flag 2023-09-05 15:57:49 +01:00
Matt Aitken 0754e99507 Removed changeset patch (it didn’t work) and instead use the documented experimental flag 2023-09-05 15:57:37 +01:00
Matt Aitken dfb0a79abc Delete changeset 2023-09-05 15:40:15 +01:00
Matt Aitken c808e40f61 Changset onlyUpdatePeerDependentsWhenOutOfRange flag on 2023-09-05 15:28:45 +01:00
Matt Aitken a9bb53b529 Use patched changeset package, to get unreleased feature with peer dependencies 2023-09-05 15:28:33 +01:00
Matt Aitken 2636d9091e Release workflow: the changeset folder wasn’t set correctly 2023-09-05 15:14:46 +01:00
Matt Aitken 878da3c01f The changeset for the integrations changes 2023-09-05 14:53:21 +01:00
Matt Aitken 588461188f Removed old changeset 2023-09-05 14:43:02 +01:00
Matt Aitken d4145de9a7 Bumped Airtable starting version to match others 2023-09-05 14:40:41 +01:00
Matt Aitken 188c4b0e24 Trying Changeset experimental option to prevent minor + patch resulting in a major 2023-09-05 14:37:52 +01:00
Matt Aitken ecd050bece Airtable integration with webhook and integration changes (#399)
* CLI create-integration command now accepts an Open AI api key

* Create integration docs separated into multiple pages

* Initial Airtable integration commit, with OpenAI generated code

* OAuth page coming soon

* Export DisplayProperty from the SDK

* TSConfig made to match GitHub’s with paths

* getRecords

* Removed duplicate Stripe job from the catalog

* Renamed Airtable apiKey option to token

* First Airtable job

* Export Collaborator and Attachment field types

* A typesafe example that uses runTask

* WIP on new integration tasks… not working yet

* Attempt with class

* Revert "Attempt with class"

This reverts commit 93a48330019f754c3216c5b49964fa4b0218bd3f.

* WIP changing how tasks work

* Mock of async local storage

* Moved client creation from constructor

* New approach with a clone method on TriggerIntegration

* Added runTask to Airtable which is used by integration tasks

* Added the Airtable icon and connection when using runTask

* base().table() is working

* runTask options moved to the 3rd param, made optional with optional name

* Added some generic arguments

* Added generic type to table

* Removed old comment

* We don’t need to repeat the icon

* getRecords and getRecord now returning the right data and types

* Creating records

* Update records

* Delete records

* The internal properties of integrations are now hidden by the TypeScript types

* Sprinkled a Prettify in there

* Improved the types

* Added Airtable to the integration catalog

* Early work on Airtable webhook registration

* More progress with webhooks

* connectionKey needs to be cloned for webhooks to work

* connectionKey needs to be cloned for webhooks to work

* It was unclear that the ActivateSourceService was using a graphileJob id

* ActivateSourceService optionally takes a jobId, if missing it generate a unique id

* When retrying trigger registration, don’t pass an id so it is generated

* Removed Airtable webhooks tasks from the job-catalog example

* Added TriggerSourceOption, removed TriggerSourceEvent

* WIP with new ExternalSource options

* ExternalSourceTrigger setup

* DynamicTrigger changed to options, will need some more work

* filter gets options passed to it

* SourceMetadata v2 renamed to SourceMetadataV2, kept original

* Started versioning the backend

* Moved param order on io.getEvent and io.cancelEvent

* The runTask stuff that allows unknown to work is back

* Indexing for v1 and v2, with version on “activateSource” schema

* Added todos, to deal with Airtable SDK calls inside the webhook handler

* “deliverHttpSourceRequest” queueName changed to the source id so they process in order

* ActivateSource changes to deal with old and new data formats

* Update existing TriggerSources to v2

* Fix for dynamic.ts typescript errors, need to revisit this later

* UpdateSourceService v1 and v2, with new v2 API endpoint

* Removed unused imports

* More progress on v1 and v2

* Airtable webhooks are now triggering a job

* Moved webhooks to a new file

* You can do API calls in the webhook handler now, Airtable webhook data is being processed

* Airtable events coming through

* Defined the Airtable table payload type

* TriggerSource metadata is being stored and used

* Removed some logs

* Added filtering and don’t allow any webhooks that use automated sources

* Resend switched to new integration

* Moved Resend test jobs to the catalog, and tested it worked

* WIP on Slack, there are compile errors

* Created a generic type that strips out indexes

* Slack updated to use new integration

* SendGrid migrated over

* Integration runTask is now allowing regular types

* Changed io.runTask types so it only allows Json-able types

* OpenAI models tasks working

* Added Airtable changes to runTask

* Removed the index signature crap from the Slack integration

* Don’t need to cast the callback result

* Updated Resend

* Re-ordered runTask params

* WIP on openai

* onAccountUpdated is Connect only

* Removed RunTaskResult

* Handle Resend errors, the official SDK doesn’t expose them properly at the moment

* Removed OmitIndexSignature

* OpenAI converted to new integration, with backwards compatible functions

* Put the openai catalog back to what it was originally

* Export a standard retry with backoff, to be used

* Use the standard exponential backoff in the integrations

* Retry options moved earlier so they can be overriden by a task

* GitHub tasks migrated

* Added sources, fixed one bundling issue

* Added GitHub jobs to catalog

* Remove duplicate options

* Deduplicate events

* Removed duplicate Job

* Switched Plain over

* Set the Plain icon

* Converted Stripe over

* Supabase adapted

* Typeform working

* Added dynamic-schedule to catalog

* Added background-fetch job catalog

* Created dynamic-triggers catalog file

* Fixed old general file with runTask param order

* Dynamic triggers working

* SendGrid updated to use the same tsconfig as other integrations

* Removed Airtable webhook, until we have batch support

* Added OAuth airtable auth example

* Created beta changeset tag

* Beta changesets for most packages

---------

Co-authored-by: Eric Allam <eallam@icloud.com>
2023-09-05 14:21:42 +01:00
Eric Allam b24aeea592 Added a long running job to stress tests 2023-09-05 12:24:58 +01:00
Eric Allam 30ba73c4f1 Various run execution fixes (incl massive memory bloat issue)
🚀 Publish Trigger.dev Docker / ʦ TypeScript (push) Has been cancelled
🚀 Publish Trigger.dev Docker / Unit Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / e2e Tests (push) Has been cancelled
🚀 Publish Trigger.dev Docker / publish (push) Has been cancelled
This commit fixes various issues with run executions, including a pretty gnarly memory bloat issue when resuming a run that had a decent number of completed tasks (e.g. anything over a few). Other issues fixed:

- Run executions no longer are bound to a queue, which will allow more parallel runs in a single job (instead of 1).
- Serverless function timeouts (504) errors are now handled better, and no longer are retried using the graphile worker failure/retry mechanism (causing massive delays).
- Fixed the job_key design of the performRunExecutionV2 task, which will ensure resumed runs are executed
- Added a mechanism to measure the amount of execution time a given run has accrued, and added a maximum execution duration on the org to be able to limit total execution time for a single run
2023-09-05 09:51:43 +01:00
Matt Aitken bf6a2a0319 Fix for seedCloud script having a duplicate pkApiKey in it 2023-09-04 20:19:53 +01:00
James Ritchie 4fc5de0dac Fixed console errors 2023-09-04 16:48:39 +01:00
Eric Allam 11ff63a9d2 Fix pnpm lock file 2023-09-02 07:08:36 +01:00
Eric Allam 0d1bdac8ab Merge branch 'main' of https://github.com/triggerdotdev/trigger.dev 2023-09-01 22:05:09 +01:00
Eric Allam 9f076631ae #346 Improve run dashboard perf when tasks have large outputs
Performance degradation came from the syntax highlighting of large code blocks and from doing that on the server and the client, so fixed this in a couple of ways:

1. Stream the task details data using defer and Suspense/Await
2. Skipped syntax highlighting code blocks with more than 1k lines
2023-09-01 22:05:06 +01:00
Matt Aitken a0d663c0fb Setup debugging for VSCode 2023-09-01 16:41:11 +01:00
D-K-P 8fd68e30e9 Removed typeform line 2023-08-31 11:15:47 +01:00
Akshay Patel 5c13512091 Better handle retrying rate-limited resend requests (#320)
* Better handle retrying rate-limited resend requests

* Better handle Retrying  Rate Request

* update try of better handle Resend Email retry

* added  retry options for when  the onError callback returns undefined

* Changed header to ratelimit-reset

* Create three-pots-flow.md

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2023-08-30 10:09:57 +01:00
Eric Allam 1d7e5737a0 Fix pnpm lock 2023-08-28 16:07:18 +01:00
github-actions[bot] 305e3b7ef2 chore: Update version for release (#417)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-28 16:06:35 +01:00
Eric Allam 03721cb18d Merge branch 'Chigala-refactor/lower-max-retries-for-specific-tasks' 2023-08-28 14:25:59 +01:00
Eric Allam 773a6e2c81 A couple of fixes 2023-08-28 14:25:41 +01:00
Eric Allam 2f13ac100f Merge branch 'refactor/lower-max-retries-for-specific-tasks' of https://github.com/Chigala/trigger.dev into Chigala-refactor/lower-max-retries-for-specific-tasks 2023-08-28 14:02:03 +01:00
Eric Allam a10782490f @trigger.dev/stripe: Added PaymentIntent and Payout trigger events 2023-08-28 12:40:02 +01:00
Eric Allam 6ad91123f2 Turned off automatic github releases 2023-08-28 10:49:24 +01:00
Chigala aa7458fe37 refactor: reduced max retries on some task to 1 on development 2023-08-24 23:50:33 +01:00
1017 changed files with 63277 additions and 17404 deletions
+5 -7
View File
@@ -1,11 +1,6 @@
{
"$schema": "https://unpkg.com/@changesets/config@2.2.0/schema.json",
"changelog": [
"@remix-run/changelog-github",
{
"repo": "triggerdotdev/trigger.dev"
}
],
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [
[
@@ -20,5 +15,8 @@
"webapp",
"emails",
"@trigger.dev/database"
]
],
"___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": {
"onlyUpdatePeerDependentsWhenOutOfRange": true
}
}
+13 -4
View File
@@ -1,35 +1,43 @@
*.log
\*.log
.git
.github
# editor
.idea
.vscode
# dependencies
node_modules
.pnp
.pnp.js
# testing
coverage
# next.js
.next/
build
# packages
build
dist
packages/**/dist
packages/\*\*/dist
# misc
.DS_Store
*.pem
\*.pem
.turbo
.vercel
.cache
.output
apps/**/public/build
apps/\*\*/public/build
cypress/screenshots
cypress/videos
@@ -38,6 +46,7 @@ apps/**/styles/tailwind.css
packages/**/styles/tailwind.css
.changeset
references
examples
CHANGESETS.md
CONTRIBUTING.md
+2
View File
@@ -31,6 +31,8 @@ CLOUD_AIRTABLE_CLIENT_ID=
CLOUD_AIRTABLE_CLIENT_SECRET=
CLOUD_GITHUB_CLIENT_ID=
CLOUD_GITHUB_CLIENT_SECRET=
CLOUD_LINEAR_CLIENT_ID=
CLOUD_LINEAR_CLIENT_SECRET=
CLOUD_SLACK_APP_HOST=
CLOUD_SLACK_CLIENT_ID=
CLOUD_SLACK_CLIENT_SECRET=
+38
View File
@@ -0,0 +1,38 @@
name: 🐞 Bug Report
description: Create a bug report to help us improve
title: "bug: "
labels: ["🐞 unconfirmed bug"]
body:
- type: textarea
attributes:
label: Provide environment information
description: |
Run this command in your project root and paste the results:
```bash
npx envinfo --system --binaries
```
validations:
required: true
- type: textarea
attributes:
label: Describe the bug
description: A clear and concise description of the bug, as well as what you expected to happen when encountering it.
validations:
required: true
- type: input
attributes:
label: Reproduction repo
description: If applicable, please provide a link to a reproduction repo or a Stackblitz / CodeSandbox project. Your issue may be closed if this is not provided and we are unable to reproduce the issue. If your bug is a docs issue, link the appropriate page.
validations:
required: true
- type: textarea
attributes:
label: To reproduce
description: Describe how to reproduce your bug. Steps, code snippets, reproduction repos etc.
validations:
required: true
- type: textarea
attributes:
label: Additional information
description: Add any other information related to the bug here, screenshots if applicable.
+5
View File
@@ -0,0 +1,5 @@
blank_issues_enabled: true
contact_links:
- name: Ask a Question
url: https://trigger.dev/discord
about: Ask questions and discuss with other community members
@@ -0,0 +1,27 @@
name: Feature Request
description: Suggest an idea for this project
title: "feat: "
labels: ["🌟 enhancement"]
body:
- type: textarea
attributes:
label: Is your feature request related to a problem? Please describe.
description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
validations:
required: true
- type: textarea
attributes:
label: Describe the solution you'd like to see
description: A clear and concise description of what you want to happen.
validations:
required: true
- type: textarea
attributes:
label: Describe alternate solutions
description: A clear and concise description of any alternative solutions or features you've considered.
validations:
required: true
- type: textarea
attributes:
label: Additional information
description: Add any other information related to the feature here. If your feature request is related to any issues or discussions, link them here.
+12
View File
@@ -0,0 +1,12 @@
"📌 area: cli":
- any: ["cli/**/*"]
"📌 area: t3-app":
- any: ["cli/template/**/*"]
"📚 documentation":
- any: ["www/**/*"]
- any: ["**/*.md"]
"📌 area: ci":
- any: [".github/**/*"]
+27
View File
@@ -0,0 +1,27 @@
Closes #<issue>
## ✅ Checklist
- [ ] I have followed every step in the [contributing guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md)
- [ ] The PR title follows the convention.
- [ ] I ran and tested the code works
---
## Testing
_[Describe the steps you took to test this change]_
---
## Changelog
_[Short description of what has changed]_
---
## Screenshots
_[Screenshots]_
💯
+65
View File
@@ -0,0 +1,65 @@
name: "🧪 E2E Tests"
on:
workflow_call:
jobs:
e2e:
name: "🧪 E2E Tests"
runs-on: buildjet-4vcpu-ubuntu-2204
steps:
- name: 🐳 Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: ⬇️ Checkout repo
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@v2.2.4
with:
version: 7.18
- name: ⎔ Setup node
uses: buildjet/setup-node@v3
with:
node-version: 18
cache: "pnpm"
- name: 📥 Download deps
run: pnpm install --frozen-lockfile
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run Playwright tests
run: |
# Setup environment variables
cp ./.env.example ./.env
cp ./references/nextjs-test/.env.example ./references/nextjs-test/.env.local
# Build packages
pnpm run build --filter @references/nextjs-test^...
pnpm --filter @trigger.dev/database generate
# Move trigger-cli bin to correct place
pnpm install --frozen-lockfile
# Execute tests
pnpm run docker
pnpm run db:migrate
pnpm run db:seed
pnpm run test:e2e
# Cleanup
pnpm run docker:stop
- name: Upload Playwright report
uses: actions/upload-artifact@v3
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
+31
View File
@@ -0,0 +1,31 @@
name: 🤖 PR Checks
on:
pull_request_target:
branches:
- main
paths-ignore:
- "**.md"
- ".github/CODEOWNERS"
- ".github/ISSUE_TEMPLATE/**"
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions:
contents: read
id-token: write
jobs:
typecheck:
uses: ./.github/workflows/typecheck.yml
secrets: inherit
units:
uses: ./.github/workflows/unit-tests.yml
secrets: inherit
e2e:
uses: ./.github/workflows/e2e.yml
secrets: inherit
+9 -114
View File
@@ -23,6 +23,7 @@ on:
- "turbo.json"
- "docker/Dockerfile"
- "docker/scripts/**"
- "tests/**"
permissions:
id-token: write
@@ -37,125 +38,19 @@ env:
jobs:
typecheck:
name: ʦ TypeScript
runs-on: buildjet-4vcpu-ubuntu-2204
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@v3
with:
fetch-depth: 0
uses: ./.github/workflows/typecheck.yml
secrets: inherit
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@v2.2.4
with:
version: 7.18
- name: ⎔ Setup node
uses: buildjet/setup-node@v3
with:
node-version: 18
cache: "pnpm"
- name: 📥 Download deps
run: pnpm install --frozen-lockfile
- name: 📀 Generate Prisma Client
run: pnpm run generate
- name: 🔎 Type check
run: pnpm run typecheck --filter webapp
unitTests:
name: Unit Tests
runs-on: buildjet-4vcpu-ubuntu-2204
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@v2.2.4
with:
version: 7.18
- name: ⎔ Setup node
uses: buildjet/setup-node@v3
with:
node-version: 18
cache: "pnpm"
- name: 📥 Download deps
run: pnpm install --frozen-lockfile
- name: Run Unit Tests
run: |
pnpm run test
units:
uses: ./.github/workflows/unit-tests.yml
secrets: inherit
e2e:
name: e2e Tests
runs-on: buildjet-4vcpu-ubuntu-2204
steps:
- name: 🐳 Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: ⬇️ Checkout repo
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@v2.2.4
with:
version: 7.18
- name: ⎔ Setup node
uses: buildjet/setup-node@v3
with:
node-version: 18
cache: "pnpm"
- name: 📥 Download deps
run: pnpm install --frozen-lockfile
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run Playwright tests
run: |
# Setup environment variables
cp ./.env.example ./.env
cp ./examples/nextjs-test/.env.example ./examples/nextjs-test/.env.local
# Build packages
pnpm run build --filter @examples/nextjs-test^...
pnpm --filter @trigger.dev/database generate
# Move trigger-cli bin to correct place
pnpm install --frozen-lockfile
# Execute tests
pnpm run docker
pnpm run db:migrate
pnpm run db:seed
pnpm run test:e2e
# Cleanup
pnpm run docker:stop
- name: Upload Playwright report
uses: actions/upload-artifact@v3
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
uses: ./.github/workflows/e2e.yml
secrets: inherit
publish:
needs: [typecheck, unitTests, e2e]
needs: [typecheck, units, e2e]
runs-on: buildjet-4vcpu-ubuntu-2204
outputs:
version: ${{ steps.get_version.outputs.version }}
+6 -11
View File
@@ -4,16 +4,11 @@ on:
push:
branches:
- main
paths:
- ".github/workflows/release.yml"
- "packages/**"
- "!packages/**/*.md"
- "changesets/**"
- "integrations/**"
- "!integrations/**/*.md"
- "pnpm-lock.yaml"
- "pnpm-workspace.yaml"
- "turbo.json"
paths-ignore:
- "**.md"
- ".github/CODEOWNERS"
- ".github/ISSUE_TEMPLATE/**"
jobs:
release:
@@ -71,7 +66,7 @@ jobs:
commit: "chore: Update version for release"
title: "chore: Update version for release"
publish: pnpm run changeset:release
createGithubReleases: true
createGithubReleases: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
+32
View File
@@ -0,0 +1,32 @@
name: "ʦ TypeScript"
on:
workflow_call:
jobs:
typecheck:
runs-on: buildjet-4vcpu-ubuntu-2204
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@v2.2.4
with:
version: 7.18
- name: ⎔ Setup node
uses: buildjet/setup-node@v3
with:
node-version: 18
cache: "pnpm"
- name: 📥 Download deps
run: pnpm install --frozen-lockfile
- name: 📀 Generate Prisma Client
run: pnpm run generate
- name: 🔎 Type check
run: pnpm run typecheck --filter webapp
+30
View File
@@ -0,0 +1,30 @@
name: "🧪 Unit Tests"
on:
workflow_call:
jobs:
unitTests:
name: "🧪 Unit Tests"
runs-on: buildjet-4vcpu-ubuntu-2204
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@v2.2.4
with:
version: 7.18
- name: ⎔ Setup node
uses: buildjet/setup-node@v3
with:
node-version: 18
cache: "pnpm"
- name: 📥 Download deps
run: pnpm install --frozen-lockfile
- name: Run Unit Tests
run: |
pnpm run test
+1 -1
View File
@@ -1 +1 @@
v18.12.1
v18.18.0
+9
View File
@@ -0,0 +1,9 @@
{
"recommendations": [
"astro-build.astro-vscode",
"denoland.vscode-deno"
],
"unwantedRecommendations": [
]
}
+13 -13
View File
@@ -5,29 +5,29 @@
"version": "0.2.0",
"configurations": [
{
"command": "pnpm run dev --filter webapp",
"name": "Run webapp",
"request": "launch",
"type": "node-terminal",
"cwd": "${workspaceFolder}"
"request": "launch",
"name": "Debug WebApp",
"command": "pnpm run dev --filter webapp",
"envFile": "${workspaceFolder}/apps/webapp/.env",
"cwd": "${workspaceFolder}",
"sourceMaps": true
},
{
"type": "chrome",
"request": "launch",
"name": "Chrome webapp",
"url": "http://localhost:3000",
"url": "http://localhost:3030",
"webRoot": "${workspaceFolder}/apps/webapp/app"
},
{
"type": "node",
"type": "node-terminal",
"request": "launch",
"name": "Debug Current Test File",
"autoAttachChildProcesses": true,
"skipFiles": ["<node_internals>/**", "**/node_modules/**"],
"program": "${workspaceRoot}/node_modules/vitest/vitest.mjs",
"args": ["run", "${relativeFile}"],
"smartStep": true,
"console": "integratedTerminal"
"name": "Debug BYO Auth",
"command": "pnpm run byo-auth",
"envFile": "${workspaceFolder}/references/job-catalog/.env",
"cwd": "${workspaceFolder}/references/job-catalog",
"sourceMaps": true
}
]
}
+3
View File
@@ -0,0 +1,3 @@
{
"deno.enablePaths": ["references/deno-reference"]
}
+28
View File
@@ -27,3 +27,31 @@ Please follow the best-practice of adding changesets in the same commit as the c
3. Create version `pnpm run changeset:version`
4. Release `pnpm run changeset:release`
5. Switch back to normal mode by running `pnpm run changeset:normal`
## Snapshot instructions
!MAKE SURE TO UPDATE THE TAG IN THE INSTRUCTIONS BELOW!
1. Add changesets as usual
```sh
pnpm run changeset:add
```
2. Create a snapshot version (replace "prerelease" with your tag)
```sh
pnpm exec changeset version --snapshot prerelease
```
3. Build the packages:
```sh
pnpm run build --filter "@trigger.dev/*"
```
4. Publish the snapshot (replace "dev" with your tag)
```sh
pnpm exec changeset publish --no-git-tag --snapshot --tag prerelease
```
+43
View File
@@ -0,0 +1,43 @@
# Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
- The use of sexualized language or imagery and unwelcome sexual attention or advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic address, without explicit permission
- Other conduct that could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned with this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project email address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the Contributor Covenant, version 2.0, available at [https://www.contributor-covenant.org/version/2/0/code_of_conduct.html](https://www.contributor-covenant.org/version/2/0/code_of_conduct.html).
+25 -13
View File
@@ -23,11 +23,11 @@ branch are tagged into a release monthly.
1. Clone the repo into a public GitHub repository or [fork the repo](https://github.com/triggerdotdev/trigger.dev/fork). If you plan to distribute the code, keep the source code public to comply with the [Apache Licence 2.0](https://github.com/triggerdotdev/trigger.dev/blob/main/LICENSE).
```
git clone https://github.com/triggerdotdev/trigger.dev.git
git clone https://github.com/<github_username>/trigger.dev.git
```
> If you are on windows, run the following command on gitbash with admin privileges:
> `git clone -c core.symlinks=true https://github.com/triggerdotdev/trigger.dev.git`
> `git clone -c core.symlinks=true https://github.com/<github_username>/trigger.dev.git`
2. Navigate to the project folder
```
@@ -52,9 +52,13 @@ branch are tagged into a release monthly.
Feel free to update `SESSION_SECRET` and `MAGIC_LINK_SECRET` as well using the same method.
6. Start Docker. This starts the required services like Postgres. If this is your first time using Docker, consider going through this [guide](DOCKER_INSTALLATION.md)
```
pnpm run docker
```
This will also start and run a local instance of [pgAdmin](https://www.pgadmin.org/) on [localhost:5480](http://localhost:5480), preconfigured with email `admin@example.com` and pwd `admin`. Then use `postgres` as the password to the Trigger.dev server.
7. Migrate the database
```
pnpm run db:migrate
@@ -133,10 +137,10 @@ pnpm run dev
2. Open a new Terminal window and run the webapp locally and then create a new project in the dashboard. Copy out the dev API key.
3. Create a new temporary Next.js app in examples directory
3. Create a new temporary Next.js app in references directory
```sh
cd ./examples
cd ./references
pnpm create next-app@latest test-cli --ts --no-eslint --tailwind --app --src-dir --import-alias "@/*"
```
@@ -149,7 +153,7 @@ pnpm create next-app@latest test-cli --ts --no-eslint --tailwind --app --src-dir
}
```
5. Back in the terminal, navigate into the example, and initialize the CLI. When prompted, select `self-hosted` and enter `localhost:3030` if you are testing against the local instance of Trigger.dev, or you can just use the Trigger.dev cloud. When asked for an API key, use the key you copied earlier.
5. Back in the terminal, navigate into the reference, and initialize the CLI. When prompted, select `self-hosted` and enter `localhost:3030` if you are testing against the local instance of Trigger.dev, or you can just use the Trigger.dev cloud. When asked for an API key, use the key you copied earlier.
```sh
cd ./test-cli
@@ -179,14 +183,14 @@ To run the end-to-end tests, follow the steps below:
```sh
cp ./.env.example ./.env
cp ./examples/nextjs-test/.env.example ./examples/nextjs-test/.env.local
cp ./references/nextjs-test/.env.example ./references/nextjs-test/.env.local
```
2. Set up dependencies
```sh
# Build packages
pnpm run build --filter @examples/nextjs-test^...
pnpm run build --filter @references/nextjs-test^...
pnpm --filter @trigger.dev/database generate
# Move trigger-cli bin to correct place
@@ -221,11 +225,11 @@ pnpm run db:studio
## Add sample jobs
The [examples/jobs-starter](./examples/jobs-starter/) project defines simple jobs you can get started with.
The [references/job-catalog](./references/job-catalog/) project defines simple jobs you can get started with.
1. `cd` into `examples/jobs-starter`
2. Create a `.env.local` file with the following content,
replacing `[TRIGGER_DEV_API_KEY]` with an actual key:
1. `cd` into `references/job-catalog`
2. Create a `.env` file with the following content,
replacing `<TRIGGER_DEV_API_KEY>` with an actual key:
```env
TRIGGER_API_KEY=[TRIGGER_DEV_API_KEY]
@@ -235,12 +239,20 @@ TRIGGER_API_URL=http://localhost:3030
`TRIGGER_API_URL` is used to configure the URL for your Trigger.dev instance,
where the jobs will be registered.
3. Run the `jobs-starter` app:
3. Run one of the the `job-catalog` files:
```sh
pnpm dev
pnpm run events
```
This will open up a local server using `express` on port 8080. Then in a new terminal window you can run the trigger-cli dev command:
```sh
pnpm run dev:trigger
```
See the [Job Catalog](./references/job-catalog/README.md) file for more.
4. Navigate to your trigger.dev instance ([http://localhost:3030](http://localhost:3030/)), to see the jobs.
You can use the test feature to trigger them.
+48 -10
View File
@@ -5,7 +5,7 @@
<img alt="Trigger.dev logo" src="https://imagedelivery.net/3TbraffuDZ4aEf8KWOmI_w/a45d1fa2-0ae8-4a39-4409-f4f934bfae00/public">
</picture>
### The background jobs framework for Next.js
### The open source background jobs framework
[Discord](https://discord.gg/JtBAxBr2m3) | [Website](https://trigger.dev) | [Issues](https://github.com/triggerdotdev/trigger.dev/issues) | [Docs](https://trigger.dev/docs)
@@ -14,11 +14,23 @@
</div>
# ✨🎃 Get involved with Hacktoberfest 2023! 🎃✨
All of October we're participating in Hacktoberfest and invite you to join us! We have a bunch of issues labeled `🎃 Hacktoberfest` that are ready for you to work on which will count towards Hacktoberfest. We are also running our own game, earn 💎 points to win swag!
- Check out our [Hacktoberfest landing page](https://trigger.dev/hacktoberfest) for how to participate and win swag.
- Contribute to either our [/trigger.dev](https://github.com/triggerdotdev/trigger.dev/labels/%F0%9F%8E%83%20hacktoberfest), [/api-reference](https://github.com/triggerdotdev/api-reference/issues?q=is%3Aopen+is%3Aissue+label%3A%F0%9F%8E%83hacktoberfest) or [/jobs-showcase](https://github.com/triggerdotdev/jobs-showcase/labels/%F0%9F%8E%83%20hacktoberfest) repositories and complete issues marked `🎃 Hacktoberfest` to be eligible for swag.
- Join our [Discord](https://discord.gg/JtBAxBr2m3) and get involved in with the community.
_New to Hacktober? Check out the [Hacktoberfest website](https://hacktoberfest.digitalocean.com/) for more information._
🎃 **Happy Hacking!** 🎃
# About Trigger.dev
Create long-running jobs directly in your codebase with features like API integrations, webhooks, scheduling and delays.
### Long running Jobs on serverless
## Long running Jobs on serverless
Reliably run jobs and dont worry about function timeouts, we handle those for you.
@@ -26,31 +38,51 @@ Reliably run jobs and dont worry about function timeouts, we handle those for
- Auto-resume after a server outage
- Add delays of up to a year
### In your codebase
## In your codebase
Create Jobs where they belong: in your codebase. Version control, localhost, test, review, and deploy like you're already used to.
### Secure by design
## Secure by design
We only receive Triggers and the data you choose to send to us. You can even completely self-host the entire platform.
### Don't worry about deployment
## Don't worry about deployment
Just use our SDK to write Jobs in your Next.js codebase. There's nothing extra to deploy and no CI to configure, your Jobs just connect to our cloud. Or you can always self-host.
Just use our SDK to write Jobs in your codebase. There's nothing extra to deploy and no CI to configure, your Jobs just connect to our cloud. Or you can always self-host.
### Full visibility of every job run
## Full visibility of every job run
View every Task in every Run so you can tell exactly what happened.
![image](https://www.trigger.dev/build/_assets/web-app-2QFKXFLW.png)
### Built-in integrations
## Built-in integrations
Easily integrate with hundreds of third-party APIs including your own. Use API keys (which never leave your server) or let us handle OAuth for you. Install our integration packages and easily subscribe to webhooks and perform common tasks, or you can easily use your existing favorite Node.JS SDKs and get resumability and idempotency through our `runTask` function.
### Trigger.dev Connect (coming soon)
## Our progress
Easily add integrations for your users.
Were building the most comprehensive and easy-to-use background jobs framework for developers.
Click the links to join the discussions about our upcoming features.
| Feature | What it does | Status |
| ------------------------------------------------------------------------------------ | --------------------------------------------------- | ------ |
| Integration kit | Official Trigger.dev integrations or build your own | ✅ |
| Self-hosting | Host the platform yourself | ✅ |
| Cloud | Just write code, no deployment required | ✅ |
| Dashboard | View every Task in every Run | ✅ |
| Serverless | Long-running Jobs on your serverless backend | ✅ |
| React hooks | Easily update your UI with Job progress | ✅ |
| React frameworks | Support for Remix, Astro, RedwoodJS & more | ✅ |
| [Background tasks](https://github.com/triggerdotdev/trigger.dev/discussions/400) | Offload long or intense Tasks to our infrastructure | 🛠️ |
| [Long-running servers](https://github.com/triggerdotdev/trigger.dev/discussions/430) | Run Jobs on your long-running backend | 🛠️ |
| Polling Triggers | Subscribe to changes without webhooks | 🕝 |
| Vercel integration | Easy deploy and preview environment support | 🕝 |
| Streaming | Receive data from your Jobs in realtime | 🕝 |
| 100+ integrations | Comprehensive support for popular APIs | 🕝 |
| [Trigger.dev Connect](https://github.com/triggerdotdev/trigger.dev/discussions/441) | Use integrations signed in as your users | 🕝 |
| File IO | Create Tasks that have file outputs | 🕝 |
# Getting started
@@ -63,3 +95,9 @@ We provide an official trigger.dev docker image you can use to easily self-host
## Development
To setup and develop locally or contribute to the open source project, follow our [development guide](./CONTRIBUTING.md).
## Meet the Amazing People Behind This Project 🚀
<a href="https://github.com/triggerdotdev/trigger.dev/graphs/contributors">
<img src="https://contrib.rocks/image?repo=triggerdotdev/trigger.dev" />
</a>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 181 KiB

After

Width:  |  Height:  |  Size: 151 KiB

@@ -0,0 +1,57 @@
export function AstroLogo({ className }: { className?: string }) {
return (
<svg className={className} viewBox="0 0 184 49" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clipPath="url(#clip0_5336_22429)">
<mask id="mask0_5336_22429" maskUnits="userSpaceOnUse" x="0" y="0" width="184" height="49">
<path d="M184 0H0V48.4533H184V0Z" fill="white" />
</mask>
<g mask="url(#mask0_5336_22429)">
<path
d="M12.4424 40.9986C10.2625 39.0108 9.62608 34.8341 10.5343 31.8083C12.1092 33.716 14.2912 34.3203 16.5514 34.6615C20.0406 35.1879 23.4674 34.991 26.7087 33.4002C27.0795 33.218 27.4221 32.9759 27.8273 32.7306C28.1315 33.6107 28.2106 34.4993 28.1044 35.4037C27.8461 37.6063 26.7472 39.3077 24.9995 40.5974C24.3006 41.1133 23.5611 41.5744 22.8393 42.0609C20.6218 43.5559 20.0219 45.3089 20.8551 47.8589C20.8749 47.921 20.8926 47.9831 20.9374 48.1347C19.8053 47.6293 18.9783 46.8934 18.3481 45.9258C17.6825 44.9046 17.3659 43.7749 17.3492 42.5525C17.3409 41.9577 17.3409 41.3576 17.2607 40.7711C17.0649 39.3413 16.3921 38.7013 15.1245 38.6644C13.8236 38.6265 12.7945 39.4287 12.5216 40.6921C12.5008 40.789 12.4706 40.8849 12.4404 40.9975L12.4424 40.9986Z"
fill="url(#paint0_linear_5336_22429)"
/>
<path
d="M0 31.3041C0 31.3041 6.45527 28.1673 12.9286 28.1673L17.8093 13.1001C17.992 12.3714 18.5256 11.8762 19.1278 11.8762C19.7302 11.8762 20.2637 12.3714 20.4464 13.1001L25.3271 28.1673C32.9938 28.1673 38.2557 31.3041 38.2557 31.3041C38.2557 31.3041 27.2909 1.50808 27.2694 1.44829C26.9547 0.567361 26.4234 0 25.7072 0H12.5496C11.8333 0 11.3235 0.567361 10.9874 1.44829C10.9637 1.50695 0 31.3041 0 31.3041Z"
fill="white"
/>
<path
d="M68.0598 26.9653C68.0598 29.6056 64.7674 31.1825 60.2089 31.1825C57.2422 31.1825 56.1929 30.4491 56.1929 28.9089C56.1929 27.2954 57.4954 26.5253 60.4622 26.5253C63.1396 26.5253 65.4188 26.5619 68.0598 26.892V26.9653ZM68.096 23.7016C66.4682 23.3349 64.0081 23.1149 61.0773 23.1149C52.5388 23.1149 48.5228 25.1318 48.5228 29.8257C48.5228 34.7029 51.2725 36.5731 57.6402 36.5731C63.031 36.5731 66.6853 35.2163 68.0236 31.8792H68.2407C68.2045 32.6859 68.1683 33.4927 68.1683 34.1161C68.1683 35.8396 68.4578 35.9864 69.8691 35.9864H76.5262C76.1644 34.9596 75.9472 32.0626 75.9472 29.5689C75.9472 26.892 76.0558 24.8751 76.0558 22.1615C76.0558 16.6241 72.7272 13.1037 62.3073 13.1037C57.821 13.1037 52.8282 13.8738 49.0293 15.0106C49.3911 16.5141 49.8977 19.5578 50.1509 21.538C53.4433 19.9979 58.1105 19.3378 61.7283 19.3378C66.7215 19.3378 68.096 20.4745 68.096 22.7848V23.7016Z"
fill="white"
/>
<path
d="M86.3622 28.5055C85.4576 28.6155 84.2278 28.6155 82.9613 28.6155C81.6224 28.6155 80.3927 28.5788 79.5604 28.4688C79.5604 28.7622 79.5242 29.0922 79.5242 29.3856C79.5242 33.9695 82.5271 36.6464 93.0917 36.6464C103.041 36.6464 106.261 34.0062 106.261 29.3489C106.261 24.9484 104.127 22.7848 94.6833 22.3081C87.3393 21.9781 86.6879 21.1713 86.6879 20.2545C86.6879 19.1911 87.6288 18.641 92.5489 18.641C97.6506 18.641 99.0251 19.3378 99.0251 20.8046V21.1346C99.7489 21.098 101.052 21.0613 102.39 21.0613C103.656 21.0613 105.031 21.098 105.827 21.1713C105.827 20.8413 105.863 20.5479 105.863 20.2912C105.863 14.9006 101.377 13.1404 92.6937 13.1404C82.9251 13.1404 79.6327 15.524 79.6327 20.1812C79.6327 24.3617 82.2738 26.9653 91.6443 27.3687C98.5547 27.5887 99.3146 28.3588 99.3146 29.4223C99.3146 30.559 98.1928 31.0725 93.345 31.0725C87.7735 31.0725 86.3622 30.3024 86.3622 28.7255V28.5055Z"
fill="white"
/>
<path
d="M118.203 9.17995C115.562 11.6369 110.822 14.0939 108.181 14.7539C108.217 16.1107 108.217 18.6044 108.217 19.9612L110.641 19.9979C110.605 22.6015 110.569 25.7552 110.569 27.8454C110.569 32.7226 113.137 36.3897 121.133 36.3897C124.498 36.3897 126.741 36.023 129.527 35.4363C129.237 33.6394 128.912 30.8891 128.804 28.7988C127.139 29.3489 125.041 29.6423 122.725 29.6423C119.505 29.6423 118.203 28.7622 118.203 26.2319C118.203 24.0316 118.203 21.9781 118.239 20.0712C122.364 20.1078 126.488 20.1812 128.912 20.2545C128.876 18.3477 128.948 15.5973 129.057 13.7638C125.547 13.8371 121.604 13.8738 118.348 13.8738C118.384 12.2603 118.42 10.7201 118.456 9.17995H118.203Z"
fill="white"
/>
<path
d="M139.812 18.861C139.848 16.9541 139.884 15.3406 139.92 13.7638H132.648C132.757 16.9175 132.757 20.1445 132.757 24.8751C132.757 29.6056 132.72 32.8693 132.648 35.9864H140.969C140.824 33.7861 140.788 30.0823 140.788 26.9286C140.788 21.9414 142.815 20.5112 147.409 20.5112C149.544 20.5112 151.063 20.768 152.402 21.2446C152.438 19.3745 152.8 15.744 153.017 14.1305C151.642 13.7271 150.123 13.4705 148.278 13.4705C144.334 13.4338 141.44 15.0473 140.101 18.8977L139.812 18.861Z"
fill="white"
/>
<path
d="M176.038 24.7284C176.038 28.7255 173.143 30.5957 168.584 30.5957C164.062 30.5957 161.167 28.8355 161.167 24.7284C161.167 20.6213 164.098 19.0811 168.584 19.0811C173.107 19.0811 176.038 20.7313 176.038 24.7284ZM183.599 24.5451C183.599 16.5875 177.376 13.0304 168.584 13.0304C159.757 13.0304 153.75 16.5875 153.75 24.5451C153.75 32.4659 159.359 36.7198 168.548 36.7198C177.81 36.7198 183.599 32.4659 183.599 24.5451Z"
fill="white"
/>
</g>
</g>
<defs>
<linearGradient
id="paint0_linear_5336_22429"
x1="10.1338"
y1="48.1347"
x2="31.1641"
y2="38.1736"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#D83333" />
<stop offset="1" stopColor="#F041FF" />
</linearGradient>
<clipPath id="clip0_5336_22429">
<rect width="184" height="48.4533" fill="white" />
</clipPath>
</defs>
</svg>
);
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,45 @@
export function FastifyLogo({ className }: { className?: string }) {
return (
<svg className={className} viewBox="0 0 184 55" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clipPath="url(#clip0_5342_22458)">
<path
d="M181.319 7.73806L184 0.829078L183.889 0.386903L157.47 7.35116C160.288 3.26104 159.321 0 159.321 0C159.321 0 150.892 5.38901 144.508 5.25083C138.124 5.11265 136.079 3.39922 126.296 6.52208C116.513 9.64494 113.749 19.207 110.903 21.2797C108.084 23.3247 99.213 30.1508 99.213 30.1508L107.227 27.5807C107.227 27.5807 104.961 29.7363 100.291 36.0096V36.0372C101.037 37.0874 104.326 41.4263 107.587 40.4866C107.946 40.3761 108.36 40.1826 108.83 39.9615C110.295 40.7906 112.257 41.5921 114.385 41.8132C114.385 41.8132 112.948 40.155 111.732 38.2205L112.727 37.5849L112.561 37.6954L115.629 38.8008L115.297 35.9267H115.325L118.309 37.0321L117.95 34.4067L119.083 33.854L122.206 22.0258L135.14 13.1823L134.117 15.7801C131.492 22.2193 126.573 23.7393 126.573 23.7393L124.527 24.5407C122.98 26.337 122.344 26.7792 121.819 32.8591C123.063 32.5275 124.223 32.4722 125.301 32.7486C130.828 34.2409 132.735 40.9012 131.243 42.7528C130.884 43.195 129.999 43.9964 128.866 44.9084H126.628L126.6 46.7324L126.379 46.9258H124.085L124.058 48.6945L123.45 49.1367C121.322 49.1919 118.586 47.3127 118.586 47.3127C118.613 49.0261 120.023 51.6515 120.023 51.6515L120.272 51.5134L120.05 51.6792C120.05 51.6792 125.799 55.4929 129.419 54.0835C132.625 52.8123 140.943 46.2625 148.129 43.1673L169.85 37.419L172.725 30.0126L156.171 34.3791V27.6912L175.599 22.5786L178.473 15.1445L156.171 21.0309V14.3707L181.319 7.73806ZM141.883 21.86L147.051 20.5059L147.106 20.7546L145.503 24.9276L140.169 26.337L141.883 21.86ZM143.652 30.7864L138.318 32.1959L140.059 27.7188L145.199 26.3647L145.282 26.6134L143.652 30.7864ZM150.616 29.2941L145.282 30.7035L147.023 26.2265L152.163 24.8723L152.246 25.1211L150.616 29.2941Z"
fill="white"
/>
<path
d="M4.00721 16.7197L4.17302 15.863C4.64284 13.3758 5.58246 11.2478 7.32352 9.64495C8.59477 8.4566 10.474 7.73807 12.602 7.73807C13.9561 7.73807 14.9787 7.93152 15.6143 8.15261L14.426 12.2427C13.9285 12.0769 13.4587 11.994 12.7678 11.994C10.8609 11.994 9.75548 13.9838 9.39621 15.8078L9.2304 16.7197H13.2652L12.5467 20.4506H8.59477L5.3061 37.5296H0L3.26104 20.4506"
fill="white"
/>
<path
d="M21.4178 37.5296L21.5837 34.0475H21.4455C19.7873 36.8111 17.7975 37.8612 16.1394 37.8612C13.0994 37.8612 11.6071 35.2634 11.6071 31.6155C11.6071 25.3145 14.7576 16.3605 23.7116 16.3605C25.7843 16.3605 27.8846 16.7197 29.1559 17.2172L26.8621 28.7966C26.3647 31.2286 25.9778 35.2634 26.0054 37.5296H21.4178ZM23.3247 20.4506C22.9102 20.3677 22.5233 20.34 22.2193 20.34C18.7372 20.34 16.8579 27.2767 16.8026 30.3443C16.8026 32.1682 17.079 33.4947 18.3779 33.4947C19.8426 33.4947 21.1968 31.0904 21.9706 27.3043L23.3247 20.4506Z"
fill="white"
/>
<path
d="M29.7915 32.9697C30.6482 33.4395 31.6708 33.854 33.1631 33.8264C34.7107 33.7711 35.5398 32.8038 35.5398 31.4773C35.5398 30.3166 34.9871 29.5152 33.55 28.3821C31.7537 26.9174 30.897 25.0934 30.897 23.2971C30.897 19.4833 33.8816 16.3605 38.6074 16.3605C40.459 16.3605 41.7579 16.6921 42.5317 17.1343L41.371 21.0033C40.7906 20.6717 39.7957 20.3677 38.9114 20.3677C37.198 20.3677 36.1478 21.252 36.1478 22.6615C36.1478 23.7393 36.7558 24.3749 37.723 25.1763C40.0721 26.9727 40.8459 29.0177 40.8459 30.6206C40.8459 35.2358 37.6401 37.7783 32.8591 37.7783C30.9522 37.7783 29.2388 37.2256 28.5203 36.7282L29.7915 32.9697Z"
fill="white"
/>
<path
d="M53.3097 11.082L52.2319 16.7197H60.4121L59.7212 20.4506H51.5134L49.6894 30.1232C49.5512 30.8417 49.5236 31.4773 49.5236 31.8642C49.5236 33.1355 50.1592 33.6053 51.1265 33.6053C51.5134 33.6053 52.0661 33.6053 52.5635 33.5224L51.9279 37.5296C50.9606 37.7783 49.7723 37.8612 48.7498 37.8612C45.544 37.8612 43.9688 36.0925 43.9688 33.2736C43.9688 32.334 44.1346 31.1733 44.3557 30.1508L46.1796 20.4506H43.7753L44.4938 16.6921H46.9258L47.7549 12.4085L53.3097 11.082Z"
fill="white"
/>
<path
d="M54.581 37.5296L58.5882 16.7197H63.8943L59.9147 37.5296H54.581ZM59.5554 11.386C59.5554 9.83838 60.6609 8.09732 62.5401 8.09732C64.2812 8.09732 65.1103 9.42384 65.055 10.8609C64.9997 12.9889 63.5626 14.2049 61.9874 14.2049C60.274 14.2049 59.5278 12.9612 59.5554 11.386Z"
fill="white"
/>
<path
d="M67.2106 16.7197L67.3764 15.863C67.8462 13.3758 68.7858 11.2478 70.5269 9.64495C71.7981 8.4566 73.6774 7.73807 75.8054 7.73807C77.1595 7.73807 78.182 7.93152 78.8177 8.15261L77.6293 12.2427C77.1319 12.0769 76.6621 11.994 75.9712 11.994C74.0643 11.994 72.9589 13.9838 72.6272 15.8078L72.4338 16.7197H78.6242L77.9057 20.4506H71.7981L68.5371 37.5296H63.2034L66.492 20.4506"
fill="white"
/>
<path
d="M81.9405 16.7197L82.0787 26.7239C82.1063 28.6861 82.1616 30.1232 82.1063 31.6431H82.1892C82.6314 29.9574 83.046 28.5479 83.7645 26.337L86.915 16.6921H92.2764L85.4779 33.1078C83.4329 37.8612 81.0838 41.8684 78.5413 44.2175C77.2977 45.3506 75.8606 46.2625 74.9763 46.6218L72.8483 42.283C73.7603 41.8132 74.7552 41.2604 75.6119 40.5972C76.8002 39.6023 77.9333 38.4139 78.4584 37.2532C78.5413 36.9769 78.6242 36.7558 78.5689 36.3413L76.3581 16.6921H81.9405V16.7197Z"
fill="white"
/>
</g>
<defs>
<clipPath id="clip0_5342_22458">
<rect width="184" height="54.4151" fill="white" />
</clipPath>
</defs>
</svg>
);
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,47 @@
export function NextjsLogo({ className }: { className?: string }) {
return (
<svg className={className} viewBox="0 0 184 38" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clipPath="url(#clip0_5291_19580)">
<path
d="M122.318 0.0154419H154.367V5.93096H141.653V37.0517H135.296V5.93096H122.318V0.0154419Z"
fill="white"
/>
<path
d="M69.608 0.0154419V5.93096H43.9181V15.4472H64.5779V21.3627H43.9181V31.1362H69.608V37.0517H37.5612L37.5586 0.0154419H69.608Z"
fill="white"
/>
<path
d="M85.6114 0.0308914H77.2921L107.09 37.0672H115.433L100.533 18.5618L115.41 0.0591477L107.09 0.0720044L96.3674 13.3889L85.6114 0.0308914Z"
fill="white"
/>
<path
d="M94.1482 26.4861L89.9821 21.3061L77.2683 37.0954H85.6114L94.1482 26.4861Z"
fill="white"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M37.784 37.0517L7.94614 0H0V37.0363H6.35692V7.91648L29.7981 37.0517H37.784Z"
fill="white"
/>
<path
d="M155.796 36.8255C155.331 36.8255 154.935 36.6642 154.603 36.3417C154.271 36.0191 154.107 35.6286 154.112 35.166C154.107 34.7161 154.271 34.3298 154.603 34.0073C154.935 33.6847 155.331 33.5234 155.796 33.5234C156.244 33.5234 156.636 33.6847 156.967 34.0073C157.304 34.3298 157.471 34.7161 157.476 35.166C157.471 35.4716 157.394 35.7517 157.239 36.0021C157.079 36.2568 156.877 36.4563 156.623 36.6006C156.373 36.7491 156.097 36.8255 155.796 36.8255Z"
fill="white"
/>
<path
d="M166.646 21.2232H169.463V32.0761C169.459 33.0735 169.243 33.9266 168.821 34.6439C168.395 35.3612 167.805 35.9087 167.047 36.2949C166.293 36.6769 165.41 36.8722 164.406 36.8722C163.489 36.8722 162.666 36.7066 161.934 36.3841C161.202 36.0615 160.62 35.5777 160.194 34.941C159.763 34.3043 159.552 33.5107 159.552 32.5599H162.373C162.378 32.9759 162.472 33.3366 162.653 33.638C162.834 33.9393 163.084 34.1685 163.403 34.3298C163.725 34.4911 164.096 34.5717 164.514 34.5717C164.966 34.5717 165.354 34.4783 165.668 34.2873C165.982 34.1006 166.224 33.8205 166.392 33.447C166.555 33.0777 166.642 32.6193 166.646 32.0761V21.2232Z"
fill="white"
/>
<path
d="M181.054 25.4676C180.985 24.8097 180.683 24.2961 180.158 23.9311C179.628 23.5619 178.943 23.3793 178.103 23.3793C177.513 23.3793 177.005 23.4685 176.583 23.6425C176.161 23.8208 175.833 24.0584 175.609 24.3598C175.386 24.6611 175.274 25.0049 175.265 25.3912C175.265 25.7138 175.342 25.9939 175.493 26.2273C175.644 26.465 175.846 26.6645 176.109 26.8258C176.367 26.9913 176.656 27.1271 176.971 27.2375C177.289 27.3478 177.608 27.4412 177.927 27.5176L179.395 27.8784C179.986 28.0142 180.559 28.1967 181.105 28.4301C181.652 28.6594 182.148 28.9522 182.583 29.3045C183.018 29.6568 183.363 30.0812 183.617 30.5778C183.871 31.0744 184 31.6558 184 32.3265C184 33.2305 183.767 34.0242 183.298 34.7118C182.828 35.3951 182.152 35.9299 181.265 36.3162C180.382 36.6982 179.314 36.8934 178.056 36.8934C176.841 36.8934 175.782 36.7067 174.89 36.3332C173.994 35.9639 173.296 35.4206 172.792 34.7075C172.288 33.9945 172.017 33.1244 171.978 32.1015H174.77C174.808 32.6363 174.981 33.082 175.274 33.4427C175.571 33.7993 175.958 34.0624 176.432 34.2407C176.91 34.4147 177.444 34.5038 178.034 34.5038C178.65 34.5038 179.193 34.4104 179.662 34.2279C180.128 34.0454 180.494 33.7908 180.757 33.4597C181.024 33.1329 181.157 32.7467 181.162 32.3053C181.157 31.902 181.036 31.5667 180.804 31.3035C180.567 31.0404 180.24 30.8197 179.822 30.6415C179.4 30.4632 178.909 30.3019 178.349 30.1618L176.566 29.7119C175.278 29.3851 174.257 28.8886 173.512 28.2222C172.762 27.5558 172.392 26.673 172.392 25.5652C172.392 24.6569 172.641 23.859 173.146 23.1756C173.645 22.4923 174.33 21.9618 175.196 21.584C176.066 21.202 177.048 21.0152 178.142 21.0152C179.253 21.0152 180.227 21.202 181.067 21.584C181.906 21.9618 182.566 22.4881 183.044 23.1586C183.522 23.8293 183.772 24.5975 183.785 25.4676H181.054Z"
fill="white"
/>
</g>
<defs>
<clipPath id="clip0_5291_19580">
<rect width="184" height="37.3604" fill="white" />
</clipPath>
</defs>
</svg>
);
}
+21
View File
@@ -0,0 +1,21 @@
export function NuxtLogo({ className }: { className?: string }) {
return (
<svg className={className} viewBox="0 0 184 46" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clipPath="url(#clip0_5336_22448)">
<path
d="M38.7097 46H64.3598C65.1746 46 65.9748 45.7875 66.6805 45.3838C67.3846 44.9814 67.9704 44.4006 68.379 43.7C68.7859 43.0017 69.0002 42.208 69 41.3998C68.9994 40.5916 68.7844 39.7981 68.3769 39.1002L51.1511 9.52867C50.7425 8.82816 50.1568 8.24752 49.4528 7.84507C48.7462 7.44109 47.9464 7.22869 47.1325 7.2289C46.3181 7.2289 45.5179 7.44165 44.8125 7.8453C44.1084 8.24768 43.5227 8.82834 43.1142 9.5289L38.7097 17.095L30.0978 2.29954C29.6891 1.59892 29.1031 1.01826 28.3988 0.61594C27.6921 0.212089 26.8922 -0.000228035 26.0783 1.8379e-07C25.2637 1.8379e-07 24.4633 0.21252 23.7576 0.61617C23.0534 1.01847 22.4674 1.59904 22.0586 2.29954L0.623071 39.1C0.215509 39.7979 0.000499188 40.5915 7.38785e-07 41.3998C-0.000459261 42.2073 0.213901 43.0006 0.621001 43.7C1.0296 44.4006 1.61541 44.9813 2.31955 45.3838C3.02626 45.7878 3.82623 46.0002 4.64025 46H20.7412C27.1207 46 31.8253 43.2228 35.0624 37.8044L42.9217 24.3144L47.1314 17.095L59.7653 38.7805H42.9217L38.7097 46ZM20.4787 38.7732L9.24232 38.7706L26.0857 9.85826L34.4901 24.3144L28.8629 33.9768C26.7131 37.4923 24.271 38.7732 20.4787 38.7732Z"
fill="#00DC82"
/>
<path
d="M86.71 46C86.954 46 87.188 45.9031 87.3605 45.7305C87.5331 45.558 87.63 45.324 87.63 45.08V23.69C87.63 23.69 88.8361 25.5958 91.08 29.44L99.9826 44.841C100.394 45.5584 101.152 46 101.972 46H108.1V11.5H101.89C101.646 11.5 101.412 11.5969 101.239 11.7695C101.067 11.942 100.97 12.176 100.97 12.42V34.04L97.06 27.14L88.6448 12.6546C88.2326 11.9398 87.4761 11.5 86.6578 11.5H80.5V46H86.71ZM155.527 33.0871L163.427 21.16H157.509C157.128 21.1607 156.754 21.2561 156.419 21.4377C156.084 21.6193 155.8 21.8813 155.592 22.2001L151.974 27.715L148.356 22.2001C148.148 21.8813 147.864 21.6193 147.529 21.4377C147.195 21.2561 146.82 21.1607 146.439 21.16H140.568L148.468 33.0379L139.961 46H145.703C146.08 45.9993 146.452 45.9054 146.785 45.7265C147.117 45.5477 147.401 45.2894 147.609 44.9747L152.021 38.3608L156.386 44.9664C156.595 45.2834 156.878 45.5438 157.212 45.7242C157.546 45.9046 157.919 45.9993 158.298 46H163.988L155.527 33.0871ZM166.658 21.16H171.192V13.8163H177.689V21.16H184V26.8771H177.689V36.685C177.689 39.1 178.905 40.2337 181.008 40.2337H184V46H180.12C174.698 46 171.192 42.7471 171.192 36.9808V26.8771H166.658V21.16ZM135.7 21.16H132.25C131.448 21.16 130.82 21.1934 130.295 21.7403C129.77 22.2569 129.72 22.5752 129.72 23.3655V35.4372C129.72 37.2906 129.634 38.4185 128.8 39.33C127.966 40.2111 126.818 40.48 125.12 40.48C123.453 40.48 122.274 40.2111 121.44 39.33C120.606 38.4185 120.52 37.2906 120.52 35.4372V23.3655C120.52 22.5754 120.47 22.2569 119.945 21.7403C119.42 21.1934 118.792 21.16 117.99 21.16H114.54V35.5171C114.54 38.738 115.435 41.2903 117.225 43.1742C119.047 45.0582 121.694 46 125.12 46C128.546 46 131.147 45.0582 132.968 43.1742C134.789 41.2903 135.7 38.738 135.7 35.5171V21.16Z"
fill="white"
/>
</g>
<defs>
<clipPath id="clip0_5336_22448">
<rect width="184" height="46" fill="white" />
</clipPath>
</defs>
</svg>
);
}
File diff suppressed because one or more lines are too long
+199
View File
@@ -0,0 +1,199 @@
export function RemixLogo({ className }: { className?: string }) {
return (
<svg className={className} viewBox="0 0 204 66" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_5334_22407)">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M47.4777 45.058C47.8835 50.3106 47.8835 52.7727 47.8835 55.4603H35.8237C35.8237 54.8748 35.8341 54.3393 35.8445 53.7962C35.8771 52.1081 35.9111 50.3479 35.6397 46.7928C35.2811 41.5885 33.0571 40.4319 28.9676 40.4319H25.3444H10V30.9627H29.5415C34.7071 30.9627 37.2898 29.379 37.2898 25.1865C37.2898 21.5001 34.7071 19.2659 29.5415 19.2659H10V10H31.6937C43.3882 10 49.1997 15.5659 49.1997 24.457C49.1997 31.1071 45.1102 35.4441 39.5857 36.167C44.2492 37.1068 46.9754 39.7813 47.4777 45.058Z"
fill="#E5F3FF"
/>
</g>
<path
d="M10 55.4604V48.4012H22.7516C24.8815 48.4012 25.3439 49.9932 25.3439 50.9423V55.4604H10Z"
fill="#E5F3FF"
/>
<g filter="url(#filter1_d_5334_22407)">
<path
d="M192.998 23.7133H181.045L175.606 31.3573L170.309 23.7133H157.498L169.021 39.5059L156.496 55.8753H168.448L174.819 47.1497L181.188 55.8753H194L181.403 39.0011L192.998 23.7133Z"
fill="#FFF1F1"
/>
</g>
<g filter="url(#filter2_d_5334_22407)">
<path
d="M117.711 29.0434C116.351 25.2935 113.416 22.6975 107.762 22.6975C102.966 22.6975 99.5309 24.861 97.8132 28.3943V23.5629H86.2185V55.7246H97.8132V39.9322C97.8132 35.1008 99.1731 31.9279 102.966 31.9279C106.474 31.9279 107.333 34.2354 107.333 38.6343V55.7246H118.927V39.9322C118.927 35.1008 120.215 31.9279 124.08 31.9279C127.588 31.9279 128.375 34.2354 128.375 38.6343V55.7246H139.97V35.5335C139.97 28.827 137.393 22.6975 128.59 22.6975C123.222 22.6975 119.428 25.4377 117.711 29.0434Z"
fill="#FFFAEA"
/>
</g>
<g filter="url(#filter3_d_5334_22407)">
<path
d="M74.1446 43.2432C73.071 45.7671 71.067 46.8487 67.9178 46.8487C64.4107 46.8487 61.5477 44.9738 61.2614 41.0076H83.6637V37.7628C83.6637 29.0372 78.0096 21.6817 67.345 21.6817C57.3964 21.6817 49.9529 28.9651 49.9529 39.1328C49.9529 49.3725 57.2534 55.5742 67.4883 55.5742C75.934 55.5742 81.803 51.464 83.4491 44.1084L74.1446 43.2432ZM61.4047 35.3829C61.8339 32.3542 63.4803 30.0466 67.202 30.0466C70.6375 30.0466 72.4983 32.4984 72.6415 35.3829H61.4047Z"
fill="#F1FFF0"
/>
</g>
<g filter="url(#filter4_d_5334_22407)">
<path
d="M143.762 23.7765V55.9383H155.357V23.7765H143.762ZM143.691 20.7478H155.429V10.5078H143.691V20.7478Z"
fill="white"
/>
</g>
<defs>
<filter
id="filter0_d_5334_22407"
x="0"
y="0"
width="59.1997"
height="65.4604"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
/>
<feOffset />
<feGaussianBlur stdDeviation="5" />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0.203922 0 0 0 0 0.45098 0 0 0 0 0.74902 0 0 0 1 0"
/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_5334_22407" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_5334_22407"
result="shape"
/>
</filter>
<filter
id="filter1_d_5334_22407"
x="146.496"
y="13.7133"
width="57.5044"
height="52.162"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
/>
<feOffset />
<feGaussianBlur stdDeviation="5" />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0.882353 0 0 0 0 0.180392 0 0 0 0 0.227451 0 0 0 1 0"
/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_5334_22407" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_5334_22407"
result="shape"
/>
</filter>
<filter
id="filter2_d_5334_22407"
x="78.2185"
y="14.6975"
width="69.7512"
height="49.0271"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
/>
<feOffset />
<feGaussianBlur stdDeviation="4" />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0.937255 0 0 0 0 0.72549 0 0 0 0 0.117647 0 0 0 1 0"
/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_5334_22407" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_5334_22407"
result="shape"
/>
</filter>
<filter
id="filter3_d_5334_22407"
x="41.9529"
y="13.6817"
width="49.7108"
height="49.8926"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
/>
<feOffset />
<feGaussianBlur stdDeviation="4" />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0.384314 0 0 0 0 0.788235 0 0 0 0 0.372549 0 0 0 1 0"
/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_5334_22407" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_5334_22407"
result="shape"
/>
</filter>
<filter
id="filter4_d_5334_22407"
x="133.691"
y="0.507791"
width="31.738"
height="65.4305"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
/>
<feOffset />
<feGaussianBlur stdDeviation="5" />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0.596078 0 0 0 0 0.192157 0 0 0 0 0.556863 0 0 0 1 0"
/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_5334_22407" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_5334_22407"
result="shape"
/>
</filter>
</defs>
</svg>
);
}
@@ -0,0 +1,29 @@
export function SvelteKitLogo({ className }: { className?: string }) {
return (
<svg className={className} viewBox="0 0 184 34" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clipPath="url(#clip0_5341_22451)">
<path
d="M153.928 25.3304L149.002 16.1776L145.901 19.929V25.3304H143.3V7.82486H145.901V16.3027L152.653 7.82486H155.654L150.753 13.977L156.98 25.3304H153.928ZM162.606 25.3304V7.82486H165.206V25.3304H162.606ZM178.761 10.3257V25.3304H176.16V10.3257H171.208V7.82486H183.712V10.3257H178.761Z"
fill="#8D8D93"
/>
<path
d="M43.8554 25.6303C42.4293 25.6662 41.0258 25.2695 39.8294 24.4926C38.7117 23.7554 37.8816 22.6561 37.4785 21.3792L39.9292 20.4789C40.2691 21.2628 40.8241 21.9343 41.53 22.4157C42.2466 22.8959 43.0933 23.1447 43.9558 23.1285C44.7848 23.1719 45.603 22.9242 46.2688 22.4283C46.5585 22.1851 46.7873 21.8776 46.9371 21.5302C47.0869 21.1829 47.1535 20.8054 47.1316 20.4278C47.1349 20.076 47.0534 19.7285 46.8939 19.4148C46.7552 19.1342 46.5738 18.8768 46.3563 18.6518C46.0811 18.4012 45.7691 18.1946 45.431 18.0391C45.0139 17.8311 44.6679 17.6727 44.393 17.5639C44.1181 17.4552 43.7138 17.3093 43.1801 17.1264C42.5134 16.893 42.0133 16.7097 41.68 16.5764C41.2284 16.3842 40.7898 16.1628 40.367 15.9135C39.912 15.6721 39.4983 15.3598 39.1415 14.9882C38.8329 14.6257 38.5839 14.2162 38.4041 13.7754C38.0584 12.9348 37.9858 12.0069 38.1964 11.1229C38.4071 10.2388 38.8904 9.44335 39.5779 8.84903C40.5782 7.96552 41.9368 7.52366 43.6538 7.52347C45.0876 7.52347 46.2672 7.84021 47.1926 8.47369C48.0908 9.07097 48.7503 9.96521 49.0555 10.9998L46.655 11.7998C46.4138 11.258 46.0065 10.807 45.492 10.5121C44.8698 10.1667 44.1651 9.99797 43.4539 10.024C42.7565 9.98411 42.0657 10.1777 41.4907 10.5743C41.2559 10.7563 41.0685 10.9924 40.9445 11.2623C40.8204 11.5323 40.7634 11.8282 40.7782 12.1249C40.7802 12.3524 40.8303 12.5769 40.9251 12.7837C41.0198 12.9906 41.1572 13.1751 41.3281 13.3252C41.6604 13.6524 42.0504 13.9153 42.4785 14.1005C42.8791 14.2672 43.4878 14.4922 44.3044 14.7755C44.8041 14.9592 45.1749 15.0967 45.4169 15.1881C45.6589 15.2794 46.0132 15.4336 46.4798 15.6506C46.8539 15.816 47.2136 16.0123 47.555 16.2375C47.8608 16.4574 48.1532 16.6954 48.4304 16.9503C48.732 17.2117 48.9896 17.5199 49.1934 17.863C49.3877 18.2188 49.5387 18.5965 49.6433 18.9881C49.771 19.4482 49.8342 19.9239 49.8311 20.4014C49.8311 22.0354 49.2726 23.3149 48.1555 24.2399C47.0384 25.1649 45.605 25.6283 43.8554 25.6303ZM59.8851 25.3304L53.8832 7.82485H56.6843L60.6604 20.0287C60.8801 20.6851 61.0638 21.3531 61.2107 22.0295C61.357 21.3529 61.5407 20.685 61.7609 20.0287L65.6868 7.82485H68.4627L62.4858 25.3304H59.8851ZM73.764 25.3304V7.82485H84.6174V10.2758H76.365V15.0772H81.6916V17.5281H76.365V22.8794H85.1688V25.3304H73.764ZM91.7943 25.3304V7.82485H94.3955V22.8295H102.948V25.3304H91.7943ZM112.75 10.3257V25.3304H110.149V10.3257H105.198V7.82485H117.702V10.3257H112.75ZM123.078 25.3304V7.82485H133.931V10.2758H125.679V15.0772H131.006V17.5281H125.679V22.8794H134.483V25.3304H123.078Z"
fill="#4A4A55"
/>
<path
d="M25.615 4.49554C22.563 0.127376 16.5351 -1.16825 12.1769 1.60935L4.52282 6.48785C3.48875 7.13833 2.6018 7.99743 1.91867 9.01023C1.23553 10.023 0.771258 11.1672 0.555527 12.3697C0.190411 14.395 0.51127 16.4843 1.46731 18.3067C0.812002 19.3005 0.365144 20.417 0.153779 21.5885C-0.0643107 22.8151 -0.0352588 24.073 0.239231 25.2882C0.51372 26.5035 1.02812 27.6517 1.75226 28.6656C4.80425 33.0343 10.8325 34.3294 15.1901 31.5518L22.8445 26.6733C23.8786 26.0228 24.7655 25.1637 25.4487 24.1509C26.1318 23.1381 26.5961 21.9939 26.8118 20.7914C27.1767 18.766 26.856 16.6768 25.9003 14.8541C26.5553 13.8603 27.0019 12.744 27.2132 11.5726C27.4315 10.346 27.4025 9.08811 27.128 7.87282C26.8535 6.65752 26.3393 5.5093 25.615 4.49554Z"
fill="#FF3E00"
/>
<path
d="M11.4291 29.0767C10.2246 29.3898 8.95296 29.3257 7.78598 28.8932C6.619 28.4606 5.61287 27.6803 4.90345 26.6577C4.46805 26.0481 4.15874 25.3578 3.99365 24.6271C3.82857 23.8964 3.81103 23.1401 3.94207 22.4025C3.98642 22.1604 4.04751 21.9216 4.1249 21.6879L4.26898 21.2478L4.66134 21.5356C5.56664 22.2013 6.57896 22.7074 7.65464 23.0323L7.93901 23.1186L7.91289 23.4026C7.87805 23.8066 7.98742 24.2097 8.22161 24.5407C8.43522 24.849 8.73834 25.0842 9.08998 25.2146C9.44162 25.345 9.82483 25.3644 10.1878 25.2699C10.3539 25.2258 10.5122 25.1565 10.6573 25.0645L18.312 20.1845C18.4992 20.0666 18.6599 19.9109 18.7837 19.7275C18.9075 19.544 18.9917 19.3368 19.0309 19.119C19.0702 18.8966 19.0648 18.6687 19.015 18.4485C18.9652 18.2282 18.8721 18.0201 18.741 17.8363C18.5274 17.528 18.2243 17.2928 17.8727 17.1622C17.521 17.0317 17.1379 17.0122 16.7748 17.1064C16.6087 17.1505 16.4504 17.2198 16.3053 17.3119L13.3842 19.1739C12.9035 19.4793 12.379 19.7095 11.8288 19.8565C10.6243 20.1696 9.35266 20.1055 8.18568 19.6729C7.01869 19.2403 6.01256 18.4601 5.30314 17.4375C4.86762 16.8279 4.55821 16.1376 4.39307 15.4069C4.22793 14.6762 4.21039 13.9198 4.34147 13.1823C4.47158 12.4591 4.75119 11.7711 5.16242 11.1622C5.57365 10.5533 6.10744 10.0369 6.72965 9.64607L14.3834 4.76787C14.8639 4.46198 15.3885 4.23149 15.9388 4.0844C17.1433 3.77125 18.4149 3.8353 19.5819 4.26789C20.7489 4.70048 21.755 5.48077 22.4644 6.5034C22.8999 7.11296 23.2093 7.80332 23.3744 8.53401C23.5395 9.2647 23.5571 10.021 23.4261 10.7586C23.3812 11.0011 23.3197 11.2402 23.2421 11.4743L23.098 11.9145L22.706 11.6272C21.8007 10.9615 20.7884 10.4553 19.7127 10.1306L19.428 10.0443L19.4544 9.76023C19.4889 9.35635 19.3795 8.95328 19.1457 8.62219C18.9322 8.31419 18.6293 8.07913 18.278 7.94872C17.9266 7.81831 17.5437 7.79884 17.181 7.89294C17.0149 7.93707 16.8566 8.00635 16.7114 8.09836L9.05592 12.9766C8.86868 13.0944 8.70806 13.25 8.58432 13.4335C8.46058 13.6169 8.37643 13.8241 8.33723 14.0418C8.29778 14.2642 8.30305 14.4922 8.35274 14.7125C8.40242 14.9328 8.49551 15.1409 8.62659 15.3248C8.84026 15.6331 9.14336 15.8683 9.49496 15.9988C9.84656 16.1293 10.2297 16.1488 10.5928 16.0547C10.7588 16.0104 10.9171 15.9411 11.0623 15.8493L13.9828 13.9881C14.4633 13.6822 14.9878 13.4518 15.5382 13.3049C16.7424 12.9919 18.0136 13.0559 19.1803 13.4882C20.347 13.9205 21.3529 14.7004 22.0624 15.7225C22.4979 16.332 22.8073 17.0224 22.9725 17.7531C23.1376 18.4838 23.1552 19.2401 23.0241 19.9777C22.8943 20.7008 22.615 21.3889 22.2042 21.998C21.7934 22.607 21.26 23.1237 20.6382 23.515L12.9845 28.3932C12.504 28.6992 11.9795 28.9297 11.4291 29.0767Z"
fill="white"
/>
</g>
<defs>
<clipPath id="clip0_5341_22451">
<rect width="184" height="33.1611" fill="white" />
</clipPath>
</defs>
</svg>
);
}
+2 -1
View File
@@ -36,7 +36,8 @@ export function Feedback({ button, defaultValue = "bug" }: FeedbackProps) {
const [form, { path, feedbackType, message }] = useForm({
id: "accept-invite",
lastSubmission,
// TODO: type this
lastSubmission: lastSubmission as any,
onValidate({ formData }) {
return parse(formData, { schema });
},
@@ -0,0 +1,12 @@
import gradientBackground from "~/assets/images/gradient-background.png";
export function PageGradient({ children }: { children: React.ReactNode }) {
return (
<div
className="-mt-4 h-full w-full bg-cover bg-no-repeat pt-20"
style={{ backgroundImage: `url("${gradientBackground}")` }}
>
{children}
</div>
);
}
@@ -0,0 +1,130 @@
import { InlineCode } from "./code/InlineCode";
import {
ClientTabs,
ClientTabsContent,
ClientTabsList,
ClientTabsTrigger,
} from "./primitives/ClientTabs";
import { ClipboardField } from "./primitives/ClipboardField";
import { Paragraph } from "./primitives/Paragraph";
export function InitCommand({ appOrigin, apiKey }: { appOrigin: string; apiKey: string }) {
return (
<ClientTabs defaultValue="npm">
<ClientTabsList>
<ClientTabsTrigger value={"npm"}>npm</ClientTabsTrigger>
<ClientTabsTrigger value={"pnpm"}>pnpm</ClientTabsTrigger>
<ClientTabsTrigger value={"yarn"}>yarn</ClientTabsTrigger>
</ClientTabsList>
<ClientTabsContent value={"npm"}>
<ClipboardField
variant="primary/medium"
className="mb-4"
secure={`npx @trigger.dev/cli@latest init -k ••••••••• -t ${appOrigin}`}
value={`npx @trigger.dev/cli@latest init -k ${apiKey} -t ${appOrigin}`}
/>
</ClientTabsContent>
<ClientTabsContent value={"pnpm"}>
<ClipboardField
variant="primary/medium"
className="mb-4"
secure={`pnpm dlx @trigger.dev/cli@latest init -k ••••••••• -t ${appOrigin}`}
value={`pnpm dlx @trigger.dev/cli@latest init -k ${apiKey} -t ${appOrigin}`}
/>
</ClientTabsContent>
<ClientTabsContent value={"yarn"}>
<ClipboardField
variant="primary/medium"
className="mb-4"
secure={`yarn dlx @trigger.dev/cli@latest init -k ••••••••• -t ${appOrigin}`}
value={`yarn dlx @trigger.dev/cli@latest init -k ${apiKey} -t ${appOrigin}`}
/>
</ClientTabsContent>
</ClientTabs>
);
}
export function RunDevCommand({ extra }: { extra?: string }) {
return (
<ClientTabs defaultValue="npm">
<ClientTabsList>
<ClientTabsTrigger value={"npm"}>npm</ClientTabsTrigger>
<ClientTabsTrigger value={"pnpm"}>pnpm</ClientTabsTrigger>
<ClientTabsTrigger value={"yarn"}>yarn</ClientTabsTrigger>
</ClientTabsList>
<ClientTabsContent value={"npm"}>
<ClipboardField
variant="primary/medium"
className="mb-4"
value={`npm run dev${extra ? ` ${extra}` : ""}`}
/>
</ClientTabsContent>
<ClientTabsContent value={"pnpm"}>
<ClipboardField
variant="primary/medium"
className="mb-4"
value={`pnpm run dev${extra ? ` ${extra}` : ""}`}
/>
</ClientTabsContent>
<ClientTabsContent value={"yarn"}>
<ClipboardField
variant="primary/medium"
className="mb-4"
value={`yarn run dev${extra ? ` ${extra}` : ""}`}
/>
</ClientTabsContent>
</ClientTabs>
);
}
export function TriggerDevCommand({ extra }: { extra?: string }) {
return (
<ClientTabs defaultValue="npm">
<ClientTabsList>
<ClientTabsTrigger value={"npm"}>npm</ClientTabsTrigger>
<ClientTabsTrigger value={"pnpm"}>pnpm</ClientTabsTrigger>
<ClientTabsTrigger value={"yarn"}>yarn</ClientTabsTrigger>
</ClientTabsList>
<ClientTabsContent value={"npm"}>
<ClipboardField
variant="primary/medium"
className="mb-4"
value={`npx @trigger.dev/cli@latest dev${extra ? ` ${extra}` : ""}`}
/>
</ClientTabsContent>
<ClientTabsContent value={"pnpm"}>
<ClipboardField
variant="primary/medium"
className="mb-4"
value={`pnpm dlx @trigger.dev/cli@latest dev${extra ? ` ${extra}` : ""}`}
/>
</ClientTabsContent>
<ClientTabsContent value={"yarn"}>
<ClipboardField
variant="primary/medium"
className="mb-4"
value={`yarn dlx @trigger.dev/cli@latest dev${extra ? ` ${extra}` : ""}`}
/>
</ClientTabsContent>
</ClientTabs>
);
}
export function TriggerDevStep({ extra }: { extra?: string }) {
return (
<>
<Paragraph spacing>
In a <span className="text-amber-400">separate terminal window or tab</span> run:
</Paragraph>
<TriggerDevCommand extra={extra} />
<Paragraph spacing variant="small">
If youre not running on the default you can specify the port by adding{" "}
<InlineCode variant="extra-small">--port 3001</InlineCode> to the end.
</Paragraph>
<Paragraph spacing variant="small">
You should leave the <InlineCode variant="extra-small">dev</InlineCode> command running when
you're developing.
</Paragraph>
</>
);
}
@@ -0,0 +1,11 @@
import { cn } from "~/utils/cn";
export function StepContentContainer({
children,
className,
}: {
children: React.ReactNode;
className?: string;
}) {
return <div className={cn("mb-6 ml-9 mt-1", className)}>{children}</div>;
}
+103 -87
View File
@@ -1,10 +1,9 @@
import { Clipboard, ClipboardCheck } from "lucide-react";
import type { Language, PrismTheme } from "prism-react-renderer";
import Highlight, { defaultProps } from "prism-react-renderer";
import { forwardRef, useCallback, useState } from "react";
import { cn } from "~/utils/cn";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../primitives/Tooltip";
import { ClipboardDocumentCheckIcon, ClipboardIcon } from "@heroicons/react/24/solid";
import { Clipboard, ClipboardCheck, ClipboardCheckIcon } from "lucide-react";
//This is a fork of https://github.com/mantinedev/mantine/blob/master/src/mantine-prism/src/Prism/Prism.tsx
//it didn't support highlighting lines by dimming the rest of the code, or animations on the highlighting
@@ -192,6 +191,9 @@ export const CodeBlock = forwardRef<HTMLDivElement, CodeBlockProps>(
Array.from({ length: end - start + 1 }, (_, i) => start + i)
);
// if there are more than 1000 lines, don't highlight
const shouldHighlight = lineCount <= 1000;
return (
<div
className={cn("relative overflow-hidden rounded-md border border-slate-800", className)}
@@ -229,99 +231,113 @@ export const CodeBlock = forwardRef<HTMLDivElement, CodeBlockProps>(
</TooltipProvider>
)}
<Highlight {...defaultProps} theme={theme} code={code} language={language}>
{({
className: inheritedClassName,
style: inheritedStyle,
tokens,
getLineProps,
getTokenProps,
}) => (
<div
dir="ltr"
className="overflow-auto px-2 py-3 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-slate-700"
style={{
maxHeight,
}}
>
<pre
className={cn(
"relative mr-2 font-mono text-xs leading-relaxed",
inheritedClassName
)}
style={inheritedStyle}
{shouldHighlight ? (
<Highlight {...defaultProps} theme={theme} code={code} language={language}>
{({
className: inheritedClassName,
style: inheritedStyle,
tokens,
getLineProps,
getTokenProps,
}) => (
<div
dir="ltr"
className="overflow-auto px-2 py-3 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-slate-700"
style={{
maxHeight,
}}
>
{tokens
.map((line, index) => {
if (
index === tokens.length - 1 &&
line.length === 1 &&
line[0].content === "\n"
) {
return null;
}
<pre
className={cn(
"relative mr-2 font-mono text-xs leading-relaxed",
inheritedClassName
)}
style={inheritedStyle}
dir="ltr"
>
{tokens
.map((line, index) => {
if (
index === tokens.length - 1 &&
line.length === 1 &&
line[0].content === "\n"
) {
return null;
}
const lineNumber = index + 1;
const lineProps = getLineProps({ line, key: index });
const lineNumber = index + 1;
const lineProps = getLineProps({ line, key: index });
let hasAnyHighlights = highlightLines ? highlightLines.length > 0 : false;
let hasAnyHighlights = highlightLines ? highlightLines.length > 0 : false;
let shouldDim = hasAnyHighlights;
if (hasAnyHighlights && highlightLines?.includes(lineNumber)) {
shouldDim = false;
}
let shouldDim = hasAnyHighlights;
if (hasAnyHighlights && highlightLines?.includes(lineNumber)) {
shouldDim = false;
}
return (
<div
key={lineProps.key}
{...lineProps}
className={cn(
"flex w-full justify-start transition-opacity duration-500",
lineProps.className
)}
style={{
opacity: shouldDim ? dimAmount : undefined,
...lineProps.style,
}}
>
{showLineNumbers && (
<div
className={
"mr-2 flex-none select-none text-right text-slate-500 transition-opacity duration-500"
}
style={{
width: `calc(8 * ${maxLineWidth / 16}rem)`,
}}
>
{lineNumber}
return (
<div
key={lineProps.key}
{...lineProps}
className={cn(
"flex w-full justify-start transition-opacity duration-500",
lineProps.className
)}
style={{
opacity: shouldDim ? dimAmount : undefined,
...lineProps.style,
}}
>
{showLineNumbers && (
<div
className={
"mr-2 flex-none select-none text-right text-slate-500 transition-opacity duration-500"
}
style={{
width: `calc(8 * ${maxLineWidth / 16}rem)`,
}}
>
{lineNumber}
</div>
)}
<div className="flex-1">
{line.map((token, key) => {
const tokenProps = getTokenProps({ token, key });
return (
<span
key={tokenProps.key}
{...tokenProps}
style={{
color: tokenProps?.style?.color as string,
...tokenProps.style,
}}
/>
);
})}
</div>
)}
<div className="flex-1">
{line.map((token, key) => {
const tokenProps = getTokenProps({ token, key });
return (
<span
key={tokenProps.key}
{...tokenProps}
style={{
color: tokenProps?.style?.color as string,
...tokenProps.style,
}}
/>
);
})}
<div className="w-4 flex-none" />
</div>
<div className="w-4 flex-none" />
</div>
);
})
.filter(Boolean)}
</pre>
</div>
)}
</Highlight>
);
})
.filter(Boolean)}
</pre>
</div>
)}
</Highlight>
) : (
<div
dir="ltr"
className="overflow-auto px-2 py-3 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-slate-700"
style={{
maxHeight,
}}
>
<pre className="relative mr-2 p-2 font-mono text-xs leading-relaxed" dir="ltr">
{code}
</pre>
</div>
)}
</div>
);
}
@@ -0,0 +1,44 @@
import {
ClientTabs,
ClientTabsList,
ClientTabsTrigger,
ClientTabsContent,
} from "../primitives/ClientTabs";
import { ClipboardField } from "../primitives/ClipboardField";
type InstallPackagesProps = {
packages: string[];
};
export function InstallPackages({ packages }: InstallPackagesProps) {
return (
<ClientTabs defaultValue="npm">
<ClientTabsList>
<ClientTabsTrigger value={"npm"}>npm</ClientTabsTrigger>
<ClientTabsTrigger value={"pnpm"}>pnpm</ClientTabsTrigger>
<ClientTabsTrigger value={"yarn"}>yarn</ClientTabsTrigger>
</ClientTabsList>
<ClientTabsContent value={"npm"}>
<ClipboardField
variant="primary/medium"
className="mb-4"
value={`npm install ${packages.join(" ")}`}
/>
</ClientTabsContent>
<ClientTabsContent value={"pnpm"}>
<ClipboardField
variant="primary/medium"
className="mb-4"
value={`pnpm install ${packages.join(" ")}`}
/>
</ClientTabsContent>
<ClientTabsContent value={"yarn"}>
<ClipboardField
variant="primary/medium"
className="mb-4"
value={`yarn add ${packages.join(" ")}`}
/>
</ClientTabsContent>
</ClientTabs>
);
}
+72 -18
View File
@@ -1,11 +1,13 @@
import { json as jsonLang } from "@codemirror/lang-json";
import type { ViewUpdate } from "@codemirror/view";
import { CheckIcon, ClipboardIcon } from "@heroicons/react/20/solid";
import type { ReactCodeMirrorProps, UseCodeMirror } from "@uiw/react-codemirror";
import { useCodeMirror } from "@uiw/react-codemirror";
import { useRef, useEffect } from "react";
import { useCallback, useEffect, useRef, useState } from "react";
import { cn } from "~/utils/cn";
import { Button } from "../primitives/Buttons";
import { getEditorSetup } from "./codeMirrorSetup";
import { darkTheme } from "./codeMirrorTheme";
import { cn } from "~/utils/cn";
export interface JSONEditorProps extends Omit<ReactCodeMirrorProps, "onBlur"> {
defaultValue?: string;
@@ -14,6 +16,8 @@ export interface JSONEditorProps extends Omit<ReactCodeMirrorProps, "onBlur"> {
onChange?: (value: string) => void;
onUpdate?: (update: ViewUpdate) => void;
onBlur?: (code: string) => void;
showCopyButton?: boolean;
showClearButton?: boolean;
}
const languages = {
@@ -38,6 +42,8 @@ export function JSONEditor(opts: JSONEditorProps) {
onBlur,
basicSetup,
autoFocus,
showCopyButton = true,
showClearButton = true,
} = {
...defaultProps,
...opts,
@@ -65,7 +71,8 @@ export function JSONEditor(opts: JSONEditorProps) {
onChange,
onUpdate,
};
const { setContainer, state } = useCodeMirror(settings);
const { setContainer, view } = useCodeMirror(settings);
const [copied, setCopied] = useState(false);
useEffect(() => {
if (editor.current) {
@@ -75,24 +82,71 @@ export function JSONEditor(opts: JSONEditorProps) {
//if the defaultValue changes update the editor
useEffect(() => {
if (state !== undefined) {
state.update({
changes: { from: 0, to: state.doc.length, insert: defaultValue },
if (view !== undefined) {
if (view.state.doc.toString() === defaultValue) return;
view.dispatch({
changes: { from: 0, to: view.state.doc.length, insert: defaultValue },
});
}
}, [defaultValue, state]);
}, [defaultValue, view]);
const clear = useCallback(() => {
if (view === undefined) return;
view.dispatch({
changes: { from: 0, to: view.state.doc.length, insert: undefined },
});
onChange?.("");
}, [view]);
const copy = useCallback(() => {
if (view === undefined) return;
navigator.clipboard.writeText(view.state.doc.toString());
setCopied(true);
setTimeout(() => {
setCopied(false);
}, 1500);
}, [view]);
return (
<div
className={cn(
"overflow-y-auto scrollbar-thin scrollbar-track-transparent scrollbar-thumb-slate-700",
opts.className
)}
ref={editor}
onBlur={() => {
if (!onBlur) return;
onBlur(editor.current?.textContent ?? "");
}}
/>
<div className={cn(opts.className, "relative")}>
<div
className="h-full w-full"
ref={editor}
onBlur={() => {
if (!onBlur) return;
onBlur(editor.current?.textContent ?? "");
}}
/>
<div className="absolute right-3 top-3 flex items-center gap-2">
{showClearButton && (
<Button
type="button"
variant="secondary/small"
onClick={(event) => {
event.preventDefault();
event.stopPropagation();
clear();
}}
>
Clear
</Button>
)}
{showCopyButton && (
<Button
type="button"
variant="secondary/small"
LeadingIcon={copied ? CheckIcon : ClipboardIcon}
leadingIconClassName={copied ? "text-green-500 group-hover:text-green-500" : undefined}
onClick={(event) => {
event.preventDefault();
event.stopPropagation();
copy();
}}
>
Copy
</Button>
)}
</div>
</div>
);
}
@@ -1,34 +1,19 @@
import {
highlightSpecialChars,
drawSelection,
highlightActiveLine,
dropCursor,
lineNumbers,
highlightActiveLineGutter,
keymap,
} from "@codemirror/view";
import type { Extension } from "@codemirror/state";
import { highlightSelectionMatches } from "@codemirror/search";
import { json as jsonLang } from "@codemirror/lang-json";
import { closeBrackets } from "@codemirror/autocomplete";
import { bracketMatching } from "@codemirror/language";
import { indentWithTab } from "@codemirror/commands";
export function getPreviewSetup(): Array<Extension> {
return [
jsonLang(),
highlightSpecialChars(),
drawSelection(),
dropCursor(),
bracketMatching(),
highlightSelectionMatches(),
lineNumbers(),
];
}
export function getViewerSetup(): Array<Extension> {
return [drawSelection(), dropCursor(), bracketMatching(), lineNumbers()];
}
import { jsonParseLinter } from "@codemirror/lang-json";
import { bracketMatching } from "@codemirror/language";
import { lintGutter, lintKeymap, linter } from "@codemirror/lint";
import { highlightSelectionMatches } from "@codemirror/search";
import { Prec, type Extension } from "@codemirror/state";
import {
drawSelection,
dropCursor,
highlightActiveLine,
highlightActiveLineGutter,
highlightSpecialChars,
keymap,
lineNumbers,
} from "@codemirror/view";
export function getEditorSetup(showLineNumbers = true, showHighlights = true): Array<Extension> {
const options = [
@@ -36,7 +21,20 @@ export function getEditorSetup(showLineNumbers = true, showHighlights = true): A
dropCursor(),
bracketMatching(),
closeBrackets(),
keymap.of([indentWithTab]),
lintGutter(),
linter(jsonParseLinter()),
Prec.highest(
keymap.of([
{
key: "Mod-Enter",
run: () => {
return true;
},
preventDefault: false,
},
])
),
keymap.of([indentWithTab, ...lintKeymap]),
];
if (showLineNumbers) {
@@ -17,10 +17,15 @@ export function darkTheme(): Extension {
violet = "#c678dd",
darkBackground = "#21252b",
highlightBackground = "rgba(71,85,105,0.2)",
background = "#0f172a",
background = "rgba(11, 16, 24 ,100)",
tooltipBackground = "#353a42",
selection = "rgb(71 85 105)",
cursor = "#528bff";
cursor = "#528bff",
scrollbarTrack = "#0E1521",
scrollbarTrackActive = "#131B2B",
scrollbarThumb = "#293649",
scrollbarThumbActive = "#3C4B62",
scrollbarBg = "#0E1521";
const jsonHeroEditorTheme = EditorView.theme(
{
@@ -94,6 +99,45 @@ export function darkTheme(): Extension {
color: ivory,
},
},
".cm-scroller": {
scrollbarWidth: "thin",
scrollbarColor: `${scrollbarThumb} ${scrollbarTrack}`,
},
".cm-scroller::-webkit-scrollbar": {
display: "block",
width: "8px",
height: "8px",
},
".cm-scroller::-webkit-scrollbar-track": {
backgroundColor: scrollbarTrack,
borderRadius: "0",
},
".cm-scroller::-webkit-scrollbar-track:hover": {
backgroundColor: scrollbarTrackActive,
},
".cm-scroller::-webkit-scrollbar-track:active": {
backgroundColor: scrollbarTrackActive,
},
".cm-scroller::-webkit-scrollbar-thumb": {
backgroundColor: scrollbarThumb,
borderRadius: "0",
},
".cm-scroller::-webkit-scrollbar-thumb:hover": {
backgroundColor: scrollbarThumbActive,
},
".cm-scroller::-webkit-scrollbar-thumb:active": {
backgroundColor: scrollbarThumbActive,
},
".cm-scroller::-webkit-scrollbar-corner": {
backgroundColor: scrollbarBg,
borderRadius: "0",
},
".cm-scroller::-webkit-scrollbar-corner:hover": {
backgroundColor: scrollbarBg,
},
".cm-scroller::-webkit-scrollbar-corner:active": {
backgroundColor: scrollbarBg,
},
},
{ dark: true }
);
@@ -155,157 +199,3 @@ export function darkTheme(): Extension {
return [jsonHeroEditorTheme, syntaxHighlighting(jsonHeroHighlightStyle)];
}
export function lightTheme(): Extension[] {
const stringColor = "text-[#53a053]",
numberColor = "text-[#447bef]",
variableColor = "text-[#a42ea2]",
booleanColor = "text-[#e2574e]",
coral = "text-[#e06c75]",
invalid = "text-[#ffffff]",
ivory = "text-[#abb2bf]",
stone = "text-[#7d8799]",
malibu = "text-[#61afef]",
whiskey = "text-[#d19a66]",
violet = "text-[#c678dd]",
darkBackground = "text-[#21252b]",
highlightBackground = "text-[#D0D0D0]",
background = "text-[#ffffff]",
tooltipBackground = "text-[#353a42]",
selection = "text-[#D0D0D0]",
cursor = "text-[#528bff]";
const jsonHeroEditorTheme = EditorView.theme(
{
"&": {
color: ivory,
backgroundColor: background,
},
".cm-content": {
caretColor: cursor,
fontFamily: "monospace",
fontSize: "14px",
},
".cm-cursor, .cm-dropCursor": { borderLeftColor: cursor },
"&.cm-focused .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection": {
backgroundColor: selection,
},
".cm-panels": { backgroundColor: darkBackground, color: ivory },
".cm-panels.cm-panels-top": { borderBottom: "2px solid black" },
".cm-panels.cm-panels-bottom": { borderTop: "2px solid black" },
".cm-searchMatch": {
backgroundColor: "#72a1ff59",
outline: "1px solid #457dff",
},
".cm-searchMatch.cm-searchMatch-selected": {
backgroundColor: "#6199ff2f",
},
".cm-activeLine": { backgroundColor: highlightBackground },
".cm-selectionMatch": { backgroundColor: "#aafe661a" },
"&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket": {
backgroundColor: "#bad0f847",
outline: "1px solid #515a6b",
},
".cm-gutters": {
backgroundColor: background,
color: stone,
border: "none",
},
".cm-activeLineGutter": {
backgroundColor: highlightBackground,
},
".cm-foldPlaceholder": {
backgroundColor: "transparent",
border: "none",
color: "#ddd",
},
".cm-tooltip": {
border: "none",
backgroundColor: tooltipBackground,
},
".cm-tooltip .cm-tooltip-arrow:before": {
borderTopColor: "transparent",
borderBottomColor: "transparent",
},
".cm-tooltip .cm-tooltip-arrow:after": {
borderTopColor: tooltipBackground,
borderBottomColor: tooltipBackground,
},
".cm-tooltip-autocomplete": {
"& > ul > li[aria-selected]": {
backgroundColor: highlightBackground,
color: ivory,
},
},
},
{ dark: false }
);
/// The highlighting style for code in the JSON Hero theme.
const jsonHeroHighlightStyle = tagHighlighter([
{ tag: tags.keyword, class: violet },
{
tag: [tags.name, tags.deleted, tags.character, tags.propertyName, tags.macroName],
class: variableColor,
},
{
tag: [tags.function(tags.variableName), tags.labelName],
class: malibu,
},
{
tag: [tags.color, tags.constant(tags.name), tags.standard(tags.name)],
class: whiskey,
},
{ tag: [tags.definition(tags.name), tags.separator], class: ivory },
{
tag: [
tags.typeName,
tags.className,
tags.number,
tags.changed,
tags.annotation,
tags.modifier,
tags.self,
tags.namespace,
],
class: numberColor,
},
{
tag: [
tags.operator,
tags.operatorKeyword,
tags.url,
tags.escape,
tags.regexp,
tags.link,
tags.special(tags.string),
],
class: stringColor,
},
{ tag: [tags.meta, tags.comment], class: stone },
{ tag: tags.link, class: stone },
{ tag: tags.heading, class: coral },
{
tag: [tags.atom, tags.bool, tags.special(tags.variableName)],
class: booleanColor,
},
{
tag: [tags.processingInstruction, tags.string, tags.inserted],
class: stringColor,
},
{ tag: tags.invalid, class: invalid },
]);
return [jsonHeroEditorTheme, syntaxHighlighting(jsonHeroHighlightStyle)];
}
@@ -0,0 +1,74 @@
import { CheckCircleIcon, ClockIcon, XCircleIcon } from "@heroicons/react/20/solid";
import { EndpointIndexStatus } from "@trigger.dev/database";
import { cn } from "~/utils/cn";
import { Spinner } from "../primitives/Spinner";
export function EndpointIndexStatusIcon({ status }: { status: EndpointIndexStatus }) {
switch (status) {
case "PENDING":
return <ClockIcon className={cn("h-4 w-4", endpointIndexStatusClassNameColor(status))} />;
case "STARTED":
return <Spinner className={cn("h-4 w-4", endpointIndexStatusClassNameColor(status))} />;
case "SUCCESS":
return (
<CheckCircleIcon className={cn("h-4 w-4", endpointIndexStatusClassNameColor(status))} />
);
case "FAILURE":
return <XCircleIcon className={cn("h-4 w-4", endpointIndexStatusClassNameColor(status))} />;
}
}
export function EndpointIndexStatusLabel({ status }: { status: EndpointIndexStatus }) {
switch (status) {
case "PENDING":
return (
<span className={endpointIndexStatusClassNameColor(status)}>
{endpointIndexStatusTitle(status)}
</span>
);
case "STARTED":
return (
<span className={endpointIndexStatusClassNameColor(status)}>
{endpointIndexStatusTitle(status)}
</span>
);
case "SUCCESS":
return (
<span className={endpointIndexStatusClassNameColor(status)}>
{endpointIndexStatusTitle(status)}
</span>
);
case "FAILURE":
return (
<span className={endpointIndexStatusClassNameColor(status)}>
{endpointIndexStatusTitle(status)}
</span>
);
}
}
export function endpointIndexStatusTitle(status: EndpointIndexStatus): string {
switch (status) {
case "PENDING":
return "Pending";
case "STARTED":
return "Started";
case "SUCCESS":
return "Success";
case "FAILURE":
return "Failure";
}
}
export function endpointIndexStatusClassNameColor(status: EndpointIndexStatus): string {
switch (status) {
case "PENDING":
return "text-dimmed";
case "STARTED":
return "text-blue-500";
case "SUCCESS":
return "text-green-500";
case "FAILURE":
return "text-rose-500";
}
}
@@ -0,0 +1,107 @@
import { Button } from "../primitives/Buttons";
import { Dialog, DialogContent, DialogTrigger } from "~/components/primitives/Dialog";
import { Header1, Header2 } from "../primitives/Headers";
import { Input } from "../primitives/Input";
import { NamedIcon } from "../primitives/NamedIcon";
import { Paragraph } from "../primitives/Paragraph";
import { Spinner } from "../primitives/Spinner";
import { useState } from "react";
import { useFetcher } from "@remix-run/react";
import { generateTwoRandomWords } from "~/utils/randomWords";
type ModalProps = {
id: string;
title: string;
};
type ModalContentProps = ModalProps & {
randomWord: string;
closeModal: () => void;
};
export function RegenerateApiKeyModal({ id, title }: ModalProps) {
const randomWord = generateTwoRandomWords();
const [open, setOpen] = useState(false);
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button variant="tertiary/small" leadingIconClassName="text-dimmed" LeadingIcon="key">
Regenerate
</Button>
</DialogTrigger>
<DialogContent>
<RegenerateApiKeyModalContent
id={id}
title={title}
randomWord={randomWord}
closeModal={() => setOpen(false)}
/>
</DialogContent>
</Dialog>
);
}
const RegenerateApiKeyModalContent = ({ id, title, randomWord, closeModal }: ModalContentProps) => {
const [confirmationText, setConfirmationText] = useState("");
const fetcher = useFetcher();
const isSubmitting = fetcher.state === "submitting";
// form submission completed
if (fetcher.state === "loading") {
closeModal();
}
return (
<div className="flex w-full flex-col items-center gap-y-6">
<div className="flex justify-center">
<Header1>{title} Environment</Header1>
</div>
<Header2 className="rounded border border-rose-500 bg-rose-500/10 px-3.5 py-2 text-center text-bright">
Are you sure you want to regenerate the keys <br />
for this environment?
</Header2>
<Paragraph variant="small" className="px-6 text-center">
<>
This will temporarily break any live jobs in the
<span className="strong text-bright"> {title} Environment</span> until the new API keys
are set in the relevant environment variables.
</>
</Paragraph>
<fetcher.Form
method="post"
action={`/resources/environments/${id}/regenerate-api-key`}
className="mt-2 flex w-full flex-col items-center gap-2"
>
<Paragraph variant="small" className="font-medium">
To confirm, please enter the text:{" "}
<span className="font-bold text-bright">{randomWord}</span>
</Paragraph>
<Input
type="text"
placeholder="Confirmation Text"
fullWidth={false}
value={confirmationText}
onChange={(e) => setConfirmationText(e.target.value)}
/>
<Button
variant="primary/large"
fullWidth
className="mt-4"
disabled={confirmationText !== randomWord}
>
{isSubmitting ? (
<Spinner color="white" />
) : (
<>
<NamedIcon
name="key"
className="mr-1.5 h-4 w-4 text-bright transition group-hover:text-bright"
/>
Regenerate API Keys
</>
)}
</Button>
</fetcher.Form>
</div>
);
};
@@ -0,0 +1,67 @@
import { Squares2X2Icon } from "@heroicons/react/20/solid";
import { GitHubDarkIcon } from "@trigger.dev/companyicons";
import { useOrganization } from "~/hooks/useOrganizations";
import { useProject } from "~/hooks/useProject";
import { projectSetupPath } from "~/utils/pathBuilder";
import { PageGradient } from "../PageGradient";
import { LinkButton } from "../primitives/Buttons";
import { Header1 } from "../primitives/Headers";
import { Paragraph } from "../primitives/Paragraph";
import { NamedIcon } from "../primitives/NamedIcon";
export type FrameworkComingSoonProps = {
frameworkName: string;
githubIssueUrl: string;
githubIssueNumber: number;
children: React.ReactNode;
};
export function FrameworkComingSoon({
frameworkName,
githubIssueUrl,
githubIssueNumber,
children,
}: FrameworkComingSoonProps) {
const organization = useOrganization();
const project = useProject();
return (
<PageGradient>
<div className="mx-auto max-w-3xl">
<div className="mb-6 grid place-items-center pb-6">{children}</div>
<div className="flex items-center justify-between">
<Header1 spacing>{frameworkName} is coming soon!</Header1>
<LinkButton
to={projectSetupPath(organization, project)}
variant="tertiary/small"
LeadingIcon={Squares2X2Icon}
>
Choose a different framework
</LinkButton>
</div>
<Paragraph spacing className="border-b border-slate-800 pb-4">
We're working hard to bring support for {frameworkName} in Trigger.dev. Follow along with
the GitHub issue or contribute and help us bring it to Trigger.dev faster.
</Paragraph>
<a
href={githubIssueUrl}
target="_blank"
className="group mt-4 block max-w-sm rounded-md bg-bright px-10 py-8 transition hover:bg-slate-100"
>
<Paragraph spacing>triggerdotdev/trigger.dev</Paragraph>
<h2 className="text-2xl font-semibold text-black">
<span className="mr-1 font-normal text-dimmed">#{githubIssueNumber}</span>Framework:
support for {frameworkName}
</h2>
<div className="mt-4 flex items-center gap-1.5">
<GitHubDarkIcon className="h-4 w-4" />
<Paragraph variant="small">View on GitHub</Paragraph>
<NamedIcon
name="arrow-right"
className="h-4 w-4 text-dimmed transition group-hover:translate-x-1"
/>
</div>
</a>
</div>
</PageGradient>
);
}
@@ -0,0 +1,103 @@
import { ChatBubbleLeftRightIcon } from "@heroicons/react/20/solid";
import { Link } from "@remix-run/react";
import { AstroLogo } from "~/assets/logos/AstroLogo";
import { ExpressLogo } from "~/assets/logos/ExpressLogo";
import { FastifyLogo } from "~/assets/logos/FastifyLogo";
import { NestjsLogo } from "~/assets/logos/NestjsLogo";
import { NextjsLogo } from "~/assets/logos/NextjsLogo";
import { NuxtLogo } from "~/assets/logos/NuxtLogo";
import { RedwoodLogo } from "~/assets/logos/RedwoodLogo";
import { RemixLogo } from "~/assets/logos/RemixLogo";
import { SvelteKitLogo } from "~/assets/logos/SveltekitLogo";
import { useOrganization } from "~/hooks/useOrganizations";
import { useProject } from "~/hooks/useProject";
import { cn } from "~/utils/cn";
import {
projectSetupAstroPath,
projectSetupExpressPath,
projectSetupFastifyPath,
projectSetupNestjsPath,
projectSetupNextjsPath,
projectSetupNuxtPath,
projectSetupRedwoodPath,
projectSetupRemixPath,
projectSetupSvelteKitPath,
} from "~/utils/pathBuilder";
import { Feedback } from "../Feedback";
import { PageGradient } from "../PageGradient";
import { Button } from "../primitives/Buttons";
import { Header1 } from "../primitives/Headers";
export function FrameworkSelector() {
const organization = useOrganization();
const project = useProject();
return (
<PageGradient>
<div className="mx-auto max-w-3xl">
<div className="flex items-center justify-between">
<Header1 spacing>Choose a framework to get started</Header1>
<Feedback
button={
<Button variant="tertiary/small" LeadingIcon={ChatBubbleLeftRightIcon}>
Request a framework
</Button>
}
defaultValue="feature"
/>
</div>
<div className="grid grid-cols-3 place-items-center gap-2">
<FrameworkLink to={projectSetupNextjsPath(organization, project)} supported>
<NextjsLogo className="w-32" />
</FrameworkLink>
<FrameworkLink to={projectSetupExpressPath(organization, project)} supported>
<ExpressLogo className="w-36" />
</FrameworkLink>
<FrameworkLink to={projectSetupRemixPath(organization, project)} supported>
<RemixLogo className="w-32" />
</FrameworkLink>
<FrameworkLink to={projectSetupAstroPath(organization, project)} supported>
<AstroLogo className="w-32" />
</FrameworkLink>
<FrameworkLink to={projectSetupRedwoodPath(organization, project)}>
<RedwoodLogo className="w-44" />
</FrameworkLink>
<FrameworkLink to={projectSetupNuxtPath(organization, project)}>
<NuxtLogo className="w-32" />
</FrameworkLink>
<FrameworkLink to={projectSetupSvelteKitPath(organization, project)} supported>
<SvelteKitLogo className="w-44" />
</FrameworkLink>
<FrameworkLink to={projectSetupFastifyPath(organization, project)}>
<FastifyLogo className="w-36" />
</FrameworkLink>
<FrameworkLink to={projectSetupNestjsPath(organization, project)} supported>
<NestjsLogo className="w-36" />
</FrameworkLink>
</div>
</div>
</PageGradient>
);
}
type FrameworkLinkProps = {
children: React.ReactNode;
to: string;
supported?: boolean;
};
function FrameworkLink({ children, to, supported = false }: FrameworkLinkProps) {
return (
<Link
to={to}
className={cn(
"flex h-28 w-full items-center justify-center rounded-md border border-slate-750 px-8 py-4 transition hover:bg-slate-850",
!supported &&
"border-dashed opacity-50 grayscale transition hover:opacity-100 hover:grayscale-0"
)}
>
{children}
</Link>
);
}
@@ -1,268 +1,26 @@
import { ChatBubbleLeftRightIcon } from "@heroicons/react/20/solid";
import { Link, useRevalidator } from "@remix-run/react";
import { useEffect, useState } from "react";
import { useEventSource } from "remix-utils";
import invariant from "tiny-invariant";
import gradientBackground from "~/assets/images/gradient-background.png";
import { Link } from "@remix-run/react";
import { Paragraph } from "~/components/primitives/Paragraph";
import { StepNumber } from "~/components/primitives/StepNumber";
import { useAppOrigin } from "~/hooks/useAppOrigin";
import { useDevEnvironment } from "~/hooks/useEnvironments";
import { useJob } from "~/hooks/useJob";
import { useOrganization } from "~/hooks/useOrganizations";
import { useProject } from "~/hooks/useProject";
import { IntegrationIcon } from "~/routes/_app.orgs.$organizationSlug.projects.$projectParam.integrations/route";
import { jobTestPath, projectStreamingPath } from "~/utils/pathBuilder";
import { Feedback } from "../Feedback";
import { jobTestPath } from "~/utils/pathBuilder";
import { CodeBlock } from "../code/CodeBlock";
import { InlineCode } from "../code/InlineCode";
import { EnvironmentLabel } from "../environments/EnvironmentLabel";
import { HelpPanelProps } from "../integrations/ApiKeyHelp";
import { HelpInstall } from "../integrations/HelpInstall";
import { HelpSamples } from "../integrations/HelpSamples";
import { Button, LinkButton } from "../primitives/Buttons";
import { LinkButton } from "../primitives/Buttons";
import { Callout, variantClasses } from "../primitives/Callout";
import {
ClientTabs,
ClientTabsContent,
ClientTabsList,
ClientTabsTrigger,
} from "../primitives/ClientTabs";
import { ClipboardField } from "../primitives/ClipboardField";
import { Header1, Header2 } from "../primitives/Headers";
import { NamedIcon } from "../primitives/NamedIcon";
import { RadioGroup, RadioGroupItem } from "../primitives/RadioButton";
import { Header2 } from "../primitives/Headers";
import { TextLink } from "../primitives/TextLink";
import integrationButton from "./integration-button.png";
import selectEnvironment from "./select-environment.png";
import selectExample from "./select-example.png";
type SelectionChoices = "use-existing-project" | "create-new-next-app";
export function HowToSetupYourProject() {
const project = useProject();
const devEnvironment = useDevEnvironment();
const appOrigin = useAppOrigin();
const [selectedValue, setSelectedValue] = useState<SelectionChoices | null>(null);
invariant(devEnvironment, "devEnvironment is required");
const revalidator = useRevalidator();
const events = useEventSource(projectStreamingPath(project.id), {
event: "message",
});
useEffect(() => {
if (events !== null) {
// This uses https://www.npmjs.com/package/canvas-confetti
if ("confetti" in window && typeof window.confetti !== "undefined") {
const duration = 3.5 * 1000;
const animationEnd = Date.now() + duration;
const defaults = {
startVelocity: 30,
spread: 360,
ticks: 60,
zIndex: 0,
colors: [
"#E7FF52",
"#41FF54",
"rgb(245 158 11)",
"rgb(22 163 74)",
"rgb(37 99 235)",
"rgb(67 56 202)",
"rgb(219 39 119)",
"rgb(225 29 72)",
"rgb(217 70 239)",
],
};
function randomInRange(min: number, max: number): number {
return Math.random() * (max - min) + min;
}
// @ts-ignore
const interval = setInterval(function () {
const timeLeft = animationEnd - Date.now();
if (timeLeft <= 0) {
return clearInterval(interval);
}
const particleCount = 50 * (timeLeft / duration);
// since particles fall down, start a bit higher than random
// @ts-ignore
window.confetti(
Object.assign({}, defaults, {
particleCount,
origin: { x: randomInRange(0.1, 0.4), y: Math.random() - 0.2 },
})
);
// @ts-ignore
window.confetti(
Object.assign({}, defaults, {
particleCount,
origin: { x: randomInRange(0.6, 0.9), y: Math.random() - 0.2 },
})
);
}, 250);
}
revalidator.revalidate();
}
// WARNING Don't put the revalidator in the useEffect deps array or bad things will happen
}, [events]); // eslint-disable-line react-hooks/exhaustive-deps
return (
<div
className="-ml-4 -mt-4 h-full w-[calc(100%+32px)] bg-cover bg-no-repeat pt-20"
style={{ backgroundImage: `url("${gradientBackground}")` }}
>
<div className="mx-auto max-w-3xl">
<div className="flex items-center justify-between">
<Header1 spacing className="text-bright">
Get setup in {selectedValue === "create-new-next-app" ? "5" : "2"} minutes
</Header1>
<Feedback
button={
<Button variant="secondary/small" LeadingIcon={ChatBubbleLeftRightIcon}>
I'm stuck!
</Button>
}
defaultValue="help"
/>
</div>
<RadioGroup
className="mb-4 flex gap-x-2"
onValueChange={(value) => setSelectedValue(value as SelectionChoices)}
>
<RadioGroupItem
label="Use an existing Next.js project"
description="Use Trigger.dev in an existing Next.js project in less than 2 mins."
value="use-existing-project"
checked={selectedValue === "use-existing-project"}
variant="icon"
data-action="use-existing-project"
icon={<NamedIcon className="h-12 w-12 text-green-600" name={"tree"} />}
/>
<RadioGroupItem
label="Create a new Next.js project"
description="This is the quickest way to try out Trigger.dev in a new Next.js project and takes 5 mins."
value="create-new-next-app"
checked={selectedValue === "create-new-next-app"}
variant="icon"
data-action="create-new-next-app"
icon={<NamedIcon className="h-8 w-8 text-green-600" name={"sapling"} />}
/>
</RadioGroup>
{selectedValue && (
<>
{selectedValue === "create-new-next-app" ? (
<>
<StepNumber stepNumber="1" title="Create a new Next.js project" />
<StepContentContainer>
<ClientTabs defaultValue="npm">
<ClientTabsList>
<ClientTabsTrigger value={"npm"}>npm</ClientTabsTrigger>
<ClientTabsTrigger value={"pnpm"}>pnpm</ClientTabsTrigger>
<ClientTabsTrigger value={"yarn"}>yarn</ClientTabsTrigger>
</ClientTabsList>
<ClientTabsContent value={"npm"}>
<ClipboardField
variant="primary/medium"
className="mb-4"
value={`npx create-next-app@latest`}
/>
</ClientTabsContent>
<ClientTabsContent value={"pnpm"}>
<ClipboardField
variant="primary/medium"
className="mb-4"
value={`pnpm create next-app`}
/>
</ClientTabsContent>
<ClientTabsContent value={"yarn"}>
<ClipboardField
variant="primary/medium"
className="mb-4"
value={`yarn create next-app`}
/>
</ClientTabsContent>
</ClientTabs>
<Paragraph spacing variant="small">
Trigger.dev works with either the Pages or App Router configuration.
</Paragraph>
</StepContentContainer>
<StepNumber stepNumber="2" title="Navigate to your new Next.js project" />
<StepContentContainer>
<Paragraph spacing>
You have now created a new Next.js project. Lets <InlineCode>cd</InlineCode>{" "}
into it using the project name you just provided:
</Paragraph>
<ClipboardField
value={"cd [replace with your project name]"}
variant={"primary/medium"}
></ClipboardField>
</StepContentContainer>
<StepNumber
stepNumber="3"
title="Run the CLI 'init' command in your new Next.js project"
/>
<StepContentContainer>
<InitCommand appOrigin={appOrigin} apiKey={devEnvironment.apiKey} />
<Paragraph spacing variant="small">
Youll notice a new folder in your project called 'jobs'. Weve added a very
simple example Job in <InlineCode variant="extra-small">examples.ts</InlineCode>{" "}
to help you get started.
</Paragraph>
</StepContentContainer>
<StepNumber stepNumber="4" title="Run your Next.js app" />
<StepContentContainer>
<NextDevCommand />
</StepContentContainer>
<StepNumber stepNumber="5" title="Run the CLI 'dev' command" />
<StepContentContainer>
<TriggerDevStep />
</StepContentContainer>
<StepNumber stepNumber="6" title="Wait for Jobs" displaySpinner />
<StepContentContainer>
<Paragraph>This page will automatically refresh.</Paragraph>
</StepContentContainer>
</>
) : (
<>
<StepNumber
stepNumber="1"
title="Run the CLI 'init' command in an existing Next.js project"
/>
<StepContentContainer>
<InitCommand appOrigin={appOrigin} apiKey={devEnvironment.apiKey} />
<Paragraph spacing variant="small">
Youll notice a new folder in your project called 'jobs'. Weve added a very
simple example Job in <InlineCode variant="extra-small">examples.ts</InlineCode>{" "}
to help you get started.
</Paragraph>
</StepContentContainer>
<StepNumber stepNumber="2" title="Run your Next.js app" />
<StepContentContainer>
<NextDevCommand />
</StepContentContainer>
<StepNumber stepNumber="3" title="Run the CLI 'dev' command" />
<StepContentContainer>
<TriggerDevStep />
</StepContentContainer>
<StepNumber stepNumber="4" title="Wait for Jobs" displaySpinner />
<StepContentContainer>
<Paragraph>This page will automatically refresh.</Paragraph>
</StepContentContainer>
</>
)}
</>
)}
</div>
</div>
);
}
import { StepContentContainer } from "../StepContentContainer";
import { TriggerDevCommand } from "../SetupCommands";
export function HowToRunYourJob() {
const organization = useOrganization();
@@ -271,20 +29,6 @@ export function HowToRunYourJob() {
return (
<>
<Callout variant="info" className="mb-6">
<Paragraph variant={"small"} className={variantClasses.info.textColor}>
Scheduled Triggers <strong>do not</strong> trigger Jobs in the DEV Environment. When
developing locally you should use the{" "}
<Link
to={jobTestPath(organization, project, job)}
className="underline underline-offset-2 transition hover:text-blue-100"
>
Test feature
</Link>{" "}
to trigger any scheduled Jobs.
</Paragraph>
</Callout>
<Paragraph spacing>There are two ways to run your Job:</Paragraph>
<StepNumber stepNumber="1" title="Trigger a test Run" />
@@ -318,36 +62,18 @@ export function HowToRunYourJob() {
How to run a Job
</LinkButton>
</StepContentContainer>
</>
);
}
export function HowToRunATest() {
return (
<>
<StepNumber
stepNumber="1"
title="Select an environment
"
/>
<StepContentContainer>
<Paragraph spacing>Select the environment youd like the test to run against.</Paragraph>
<img src={selectEnvironment} className="mt-2 w-52" />
</StepContentContainer>
<StepNumber stepNumber="2" title="Write your test payload" />
<StepContentContainer>
<Paragraph spacing>
Write your own payload specific to your Job. Some Triggers also provide example payloads
that you can select from. This will populate the code editor below.
<Callout variant="info">
<Paragraph variant={"small"} className={variantClasses.info.textColor}>
Scheduled Triggers <strong>do not</strong> trigger Jobs in the DEV Environment. When
developing locally you should use the{" "}
<Link
to={jobTestPath(organization, project, job)}
className="underline underline-offset-2 transition hover:text-blue-100"
>
Test feature
</Link>{" "}
to trigger any scheduled Jobs.
</Paragraph>
<img src={selectExample} className="mt-2 h-40" />
</StepContentContainer>
<StepNumber stepNumber="3" title="Run your test" />
<StepContentContainer>
<Paragraph spacing>When youre happy with the payload, click Run test.</Paragraph>
</StepContentContainer>
<Callout variant="docs" to="https://trigger.dev/docs/documentation/guides/testing-jobs">
Learn more about running tests.
</Callout>
</>
);
@@ -515,6 +241,21 @@ export function HowToUseApiKeysAndEndpoints() {
you should use the Test feature to trigger any scheduled Jobs.
</Callout>
</StepContentContainer>
<StepNumber
stepNumber="→"
title={
<span className="flex items-center gap-x-2">
<span>Staging</span>
<EnvironmentLabel environment={{ type: "STAGING" }} />
</span>
}
/>
<StepContentContainer>
<Paragraph spacing>
The <InlineCode>STAGING</InlineCode> environment is where your Jobs will run in a staging
environment, meant to mirror your production environment.
</Paragraph>
</StepContentContainer>
<StepNumber
stepNumber="→"
title={
@@ -553,116 +294,3 @@ export function HowToUseApiKeysAndEndpoints() {
</>
);
}
function StepContentContainer({ children }: { children: React.ReactNode }) {
return <div className="mb-6 ml-9 mt-1">{children}</div>;
}
function InitCommand({ appOrigin, apiKey }: { appOrigin: string; apiKey: string }) {
return (
<ClientTabs defaultValue="npm">
<ClientTabsList>
<ClientTabsTrigger value={"npm"}>npm</ClientTabsTrigger>
<ClientTabsTrigger value={"pnpm"}>pnpm</ClientTabsTrigger>
<ClientTabsTrigger value={"yarn"}>yarn</ClientTabsTrigger>
</ClientTabsList>
<ClientTabsContent value={"npm"}>
<ClipboardField
variant="primary/medium"
className="mb-4"
secure={`npx @trigger.dev/cli@latest init -k ••••••••• -t ${appOrigin}`}
value={`npx @trigger.dev/cli@latest init -k ${apiKey} -t ${appOrigin}`}
/>
</ClientTabsContent>
<ClientTabsContent value={"pnpm"}>
<ClipboardField
variant="primary/medium"
className="mb-4"
secure={`pnpm dlx @trigger.dev/cli@latest init -k ••••••••• -t ${appOrigin}`}
value={`pnpm dlx @trigger.dev/cli@latest init -k ${apiKey} -t ${appOrigin}`}
/>
</ClientTabsContent>
<ClientTabsContent value={"yarn"}>
<ClipboardField
variant="primary/medium"
className="mb-4"
secure={`yarn dlx @trigger.dev/cli@latest init -k ••••••••• -t ${appOrigin}`}
value={`yarn dlx @trigger.dev/cli@latest init -k ${apiKey} -t ${appOrigin}`}
/>
</ClientTabsContent>
</ClientTabs>
);
}
function NextDevCommand() {
return (
<ClientTabs defaultValue="npm">
<ClientTabsList>
<ClientTabsTrigger value={"npm"}>npm</ClientTabsTrigger>
<ClientTabsTrigger value={"pnpm"}>pnpm</ClientTabsTrigger>
<ClientTabsTrigger value={"yarn"}>yarn</ClientTabsTrigger>
</ClientTabsList>
<ClientTabsContent value={"npm"}>
<ClipboardField variant="primary/medium" className="mb-4" value={`npm run dev`} />
</ClientTabsContent>
<ClientTabsContent value={"pnpm"}>
<ClipboardField variant="primary/medium" className="mb-4" value={`pnpm run dev`} />
</ClientTabsContent>
<ClientTabsContent value={"yarn"}>
<ClipboardField variant="primary/medium" className="mb-4" value={`yarn run dev`} />
</ClientTabsContent>
</ClientTabs>
);
}
function TriggerDevCommand() {
return (
<ClientTabs defaultValue="npm">
<ClientTabsList>
<ClientTabsTrigger value={"npm"}>npm</ClientTabsTrigger>
<ClientTabsTrigger value={"pnpm"}>pnpm</ClientTabsTrigger>
<ClientTabsTrigger value={"yarn"}>yarn</ClientTabsTrigger>
</ClientTabsList>
<ClientTabsContent value={"npm"}>
<ClipboardField
variant="primary/medium"
className="mb-4"
value={`npx @trigger.dev/cli@latest dev`}
/>
</ClientTabsContent>
<ClientTabsContent value={"pnpm"}>
<ClipboardField
variant="primary/medium"
className="mb-4"
value={`pnpm dlx @trigger.dev/cli@latest dev`}
/>
</ClientTabsContent>
<ClientTabsContent value={"yarn"}>
<ClipboardField
variant="primary/medium"
className="mb-4"
value={`yarn dlx @trigger.dev/cli@latest dev`}
/>
</ClientTabsContent>
</ClientTabs>
);
}
function TriggerDevStep() {
return (
<>
<Paragraph spacing>
In a <span className="text-amber-400">separate terminal window or tab</span> run:
</Paragraph>
<TriggerDevCommand />
<Paragraph spacing variant="small">
If youre not running on port 3000 you can specify the port by adding{" "}
<InlineCode variant="extra-small">--port 3001</InlineCode> to the end.
</Paragraph>
<Paragraph spacing variant="small">
You should leave the <InlineCode variant="extra-small">dev</InlineCode> command running when
you're developing.
</Paragraph>
</>
);
}
@@ -46,7 +46,8 @@ export function ConnectToOAuthForm({
const [form, { title, slug, scopes, hasCustomClient, customClientId, customClientSecret }] =
useForm({
lastSubmission: fetcher.data,
// TODO: type this
lastSubmission: fetcher.data as any,
shouldRevalidate: "onSubmit",
onValidate({ formData }) {
return parse(formData, {
@@ -25,8 +25,6 @@ client.defineJob({
//wrap an SDK call in io.runTask so it's resumable and displays in logs
const repo = await io.runTask(
"Get repo",
//you can add metadata to the task to improve the display in the logs
{ name: "Get repo", icon: "github" },
async () => {
//this is the regular GitHub SDK
const response = await octokit.rest.repos.get({
@@ -34,7 +32,9 @@ client.defineJob({
repo: "trigger.dev",
});
return response.data;
}
},
//you can add metadata to the task to improve the display in the logs
{ name: "Get repo", icon: "github" }
);
},
});
@@ -60,13 +60,13 @@ client.defineJob({
//wrap anything in io.runTask so it's resumable and displays in logs
const repo = await io.runTask(
"Get org",
//you can add metadata to the task to improve the display in the logs
{ name: "Get org", icon: "github" },
async () => {
//you can use fetch, axios, or any other library to make requests
const response = await fetch('https://api.github.com/orgs/nodejs');
return response.json();
}
},
//you can add metadata to the task to improve the display in the logs
{ name: "Get org", icon: "github" }
);
},
});
@@ -7,6 +7,7 @@ import { ConnectToOAuthForm } from "./ConnectToOAuthForm";
import { Paragraph } from "../primitives/Paragraph";
import { Client } from "~/presenters/IntegrationsPresenter.server";
import { UpdateOAuthForm } from "./UpdateOAuthForm";
import { LinkButton } from "../primitives/Buttons";
export function SelectOAuthMethod({
integration,
@@ -76,7 +77,7 @@ export function SelectOAuthMethod({
id="EXTERNAL"
value="EXTERNAL"
label="Your users"
description="We will give you OAuth React components so you can connect as your users."
description="Use an external authentication provider or your own user database to provide auth credentails of your users."
variant="description"
/>
</RadioGroup>
@@ -108,14 +109,19 @@ export function SelectOAuthMethod({
)
) : (
<>
<Header2 className="mb-1 mt-4">User OAuth coming soon</Header2>
<Header2 className="mb-1 mt-4">BYO Auth</Header2>
<Paragraph spacing>
End-user OAuth is going to be released soon. If you are interested in being an early
beta tester then please{" "}
<a href="mailto:founders@trigger.dev" className="text-indigo-500 underline">
message us
</a>
.
We support external authentication providers through Auth Resolvers. Read the docs to
learn more:{" "}
<LinkButton
variant="secondary/small"
LeadingIcon={"docs"}
TrailingIcon={"external-link"}
to="https://trigger.dev/docs/documentation/guides/using-integrations-byo-auth"
target="_blank"
>
Bring your own Auth
</LinkButton>
</Paragraph>
</>
))}
@@ -45,7 +45,8 @@ export function UpdateOAuthForm({
const { isManagedCloud } = useFeatures();
const [form, { title, scopes, hasCustomClient, customClientId, customClientSecret }] = useForm({
lastSubmission: fetcher.data,
// TODO: type this
lastSubmission: fetcher.data as any,
onValidate({ formData }) {
return parse(formData, {
schema,
@@ -197,6 +197,8 @@ function classForJobStatus(status: JobRunStatus) {
case "TIMED_OUT":
case "WAITING_ON_CONNECTIONS":
case "PENDING":
case "UNRESOLVED_AUTH":
case "INVALID_PAYLOAD":
return "text-rose-500";
default:
return "";
@@ -40,8 +40,14 @@ export function BackgroundGradient({
}
/** This container should be placed around the content on a page */
export function PageContainer({ children }: { children: React.ReactNode }) {
return <div className={cn("grid h-full grid-rows-[auto_1fr]")}>{children}</div>;
export function PageContainer({
children,
className,
}: {
children: React.ReactNode;
className?: string;
}) {
return <div className={cn("grid h-full grid-rows-[auto_1fr]", className)}>{children}</div>;
}
export function PageBody({
@@ -1,11 +1,12 @@
import { RouteMatch, useMatches } from "@remix-run/react";
import { UIMatch, useMatches } from "@remix-run/react";
import { Fragment, ReactNode } from "react";
import { BreadcrumbIcon } from "../primitives/BreadcrumbIcon";
import { Handle } from "~/utils/handle";
export type BreadcrumbItem = (match: RouteMatch, allMatches: RouteMatch[]) => ReactNode;
export type BreadcrumbItem = (match: UIMatch, allMatches: UIMatch[]) => ReactNode;
export function Breadcrumb() {
const matches = useMatches();
const matches = useMatches() as UIMatch<unknown, Handle>[];
return (
<div className="hidden items-center md:flex">
@@ -1,4 +1,4 @@
import { Link, RouteMatch } from "@remix-run/react";
import { Link, UIMatch } from "@remix-run/react";
import { useState } from "react";
import { useJob } from "~/hooks/useJob";
import { useOrganization } from "~/hooks/useOrganizations";
@@ -15,7 +15,7 @@ import {
PopoverSectionHeader,
} from "../primitives/Popover";
export function JobsMenu({ matches }: { matches: RouteMatch[] }) {
export function JobsMenu({ matches }: { matches: UIMatch[] }) {
const [isOpen, setIsOpen] = useState(false);
const organization = useOrganization(matches);
const project = useProject(matches);
@@ -17,7 +17,6 @@ export function NavBar() {
<LogoIcon className="h-5 w-5" />
</Link>
<Breadcrumb />
<MobileDropdownMenu />
</div>
<div className="hidden items-center gap-2 sm:flex">
<LinkButton to={docsRoot()} variant="secondary/small" LeadingIcon={BookOpenIcon}>
@@ -46,83 +45,3 @@ export function BreadcrumbLink({ title, to }: { title: string; to: string }) {
</LinkButton>
);
}
function MobileDropdownMenu() {
return (
<Popover className="block sm:hidden">
<Popover.Button
className="bg-slate-70 relative z-10 flex h-8 w-8 items-center justify-center rounded border-none bg-opacity-50 focus-visible:border-none focus-visible:outline-none"
aria-label="Toggle Navigation"
>
{({ open }) => <MobileNavIcon open={open} />}
</Popover.Button>
<Transition.Root>
<Transition.Child
as={Fragment}
enter="duration-150 ease-out"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="duration-150 ease-in"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Popover.Overlay className="absolute left-0 top-0 h-full w-full origin-top bg-midnight-900/80" />
</Transition.Child>
<Transition.Child
as={Fragment}
enter="duration-150 ease-out"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
leave="duration-100 ease-in"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Popover.Panel
as="div"
className="absolute inset-x-6 top-0 mt-20 flex origin-top flex-col gap-4 rounded-md bg-slate-800 p-4 text-lg tracking-tight text-slate-900 shadow-xl ring-1 ring-slate-700"
>
{/* <PrimaryA
href={docsRoot()}
target="_blank"
className="max-w-full"
>
<ArrowTopRightOnSquareIcon className="-ml-1 h-4 w-4" />
Documentation
</PrimaryA>
<PrimaryButton
data-attr="posthog-feedback-button"
className="max-w-full"
>
<ChatBubbleLeftRightIcon className="-ml-1 h-4 w-4" />
Send us feedback
</PrimaryButton>
<SecondaryLink to="/logout" className="max-w-full">
Logout
</SecondaryLink> */}
</Popover.Panel>
</Transition.Child>
</Transition.Root>
</Popover>
);
}
function MobileNavIcon({ open }: { open: boolean }) {
return (
<svg
aria-hidden="true"
className="h-3.5 w-3.5 overflow-visible stroke-slate-300"
fill="none"
strokeWidth={2}
strokeLinecap="round"
>
<path
d="M0 1H14M0 7H14M0 13H14"
className={cn("origin-center transition", open && "scale-90 opacity-0")}
/>
<path
d="M2 2L12 12M12 2L2 12"
className={cn("origin-center transition", !open && "scale-90 opacity-0")}
/>
</svg>
);
}
@@ -12,6 +12,7 @@ import {
projectEnvironmentsPath,
projectIntegrationsPath,
projectPath,
projectSetupPath,
projectTriggersPath,
} from "~/utils/pathBuilder";
import { UserProfilePhoto } from "../UserProfilePhoto";
@@ -57,8 +58,9 @@ export function ProjectSideMenu() {
animate={isCollapsed ? "collapsed" : "expanded"}
variants={menuVariants}
initial={isCollapsed ? "collapsed" : "expanded"}
transition={{ type: "spring", duration: 0.5 }}
className={cn(
"flex h-full flex-col justify-between overflow-hidden border-r border-uiBorder p-1 transition duration-300 ease-in-out"
"flex h-full flex-col justify-between overflow-hidden border-r border-uiBorder p-1 transition"
)}
>
<div className="flex flex-col gap-1">
@@ -94,7 +96,7 @@ export function ProjectSideMenu() {
data-action="environments & api keys"
/>
</div>
<div className="flex flex-col">
<div className="flex flex-col gap-1">
<SideMenuItem
name="Team"
icon="team"
@@ -109,6 +111,21 @@ export function ProjectSideMenu() {
isCollapsed={isCollapsed}
data-action="usage & billing"
/>
<SideMenuItem
name="Onboarding"
icon="clipboard-checked"
to={projectSetupPath(organization, project)}
isCollapsed={isCollapsed}
data-action="onboarding"
/>
<SideMenuItem
name="Changelog"
icon="list"
to="https://trigger.dev/changelog"
isCollapsed={isCollapsed}
data-action="changelog"
target="_blank"
/>
<SideMenuItem
name="Account"
icon={UserProfilePhoto}
@@ -137,6 +154,7 @@ function SideMenuItem({
isCollapsed,
forceActive,
hasWarning = false,
target,
}: {
icon: IconNames | React.ComponentType<any>;
name: string;
@@ -144,6 +162,7 @@ function SideMenuItem({
isCollapsed: boolean;
hasWarning?: boolean;
forceActive?: boolean;
target?: string;
}) {
return (
<SimpleTooltip
@@ -155,13 +174,14 @@ function SideMenuItem({
LeadingIcon={icon}
leadingIconClassName="text-dimmed"
to={to}
target={target}
className={({ isActive, isPending }) => {
if (forceActive !== undefined) {
isActive = forceActive;
}
return cn(
"relative",
isActive
isActive || isPending
? "bg-slate-800 text-bright group-hover:bg-slate-800"
: "text-dimmed group-hover:bg-slate-850 group-hover:text-bright"
);
@@ -1,4 +1,4 @@
import { RouteMatch } from "@remix-run/react";
import { UIMatch } from "@remix-run/react";
import { Fragment, useState } from "react";
import simplur from "simplur";
import { Badge } from "~/components/primitives/Badge";
@@ -13,7 +13,7 @@ import {
PopoverSectionHeader,
} from "../primitives/Popover";
export function ProjectsMenu({ matches }: { matches: RouteMatch[] }) {
export function ProjectsMenu({ matches }: { matches: UIMatch[] }) {
const [isOpen, setIsOpen] = useState(false);
const organizations = useOrganizations(matches);
const isNewOrgPage = useIsNewOrganizationPage(matches);
@@ -144,7 +144,7 @@ export function ButtonContent(props: ButtonContentPropsType) {
const textColorClassName = variation.textColor;
return (
<div className={cn(fullWidth ? "flex" : "inline-flex text-xxs", btnClassName, className)}>
<div className={cn("flex", fullWidth ? "" : "w-fit text-xxs", btnClassName, className)}>
<div
className={cn(
textAlignLeft ? "text-left" : "justify-center",
@@ -286,9 +286,13 @@ type NavLinkPropsType = Pick<NavLinkProps, "to" | "target"> &
Omit<React.ComponentProps<typeof ButtonContent>, "className"> & {
className?: (props: { isActive: boolean; isPending: boolean }) => string | undefined;
};
export const NavLinkButton = ({ to, className, ...props }: NavLinkPropsType) => {
export const NavLinkButton = ({ to, className, target, ...props }: NavLinkPropsType) => {
return (
<NavLink to={to} className={cn("group outline-none", props.fullWidth ? "w-full" : "")}>
<NavLink
to={to}
className={cn("group outline-none", props.fullWidth ? "w-full" : "")}
target={target}
>
{({ isActive, isPending }) => (
<ButtonContent className={className && className({ isActive, isPending })} {...props} />
)}
@@ -13,13 +13,14 @@ import {
import { Link } from "@remix-run/react";
import { cn } from "~/utils/cn";
import { Paragraph } from "./Paragraph";
import { Spinner } from "./Spinner";
export const variantClasses = {
info: {
className: "border-blue-400/20 bg-blue-400/30",
icon: <InformationCircleIcon className="h-5 w-5 shrink-0 text-blue-400" />,
textColor: "text-blue-200",
linkClassName: "transition hover:bg-blue-400/40",
className: "border-slate-700 bg-slate-800",
icon: <InformationCircleIcon className="h-5 w-5 shrink-0 text-dimmed" />,
textColor: "text-bright",
linkClassName: "transition hover:bg-slate-750",
},
warning: {
className: "border-yellow-400/20 bg-yellow-400/30",
@@ -51,8 +52,16 @@ export const variantClasses = {
textColor: "text-blue-200",
linkClassName: "transition hover:bg-blue-400/40",
},
pending: {
className: "border-blue-400/20 bg-blue-800/30",
icon: <Spinner className="h-5 w-5 shrink-0 " />,
textColor: "text-blue-300",
linkClassName: "transition hover:bg-blue-400/40",
},
} as const;
export type CalloutVariant = keyof typeof variantClasses;
export function Callout({
children,
className,
@@ -63,7 +72,7 @@ export function Callout({
children?: React.ReactNode;
className?: string;
icon?: React.ReactNode;
variant: keyof typeof variantClasses;
variant: CalloutVariant;
to?: string;
}) {
const variantDefinition = variantClasses[variant];
@@ -63,16 +63,17 @@ export const DateTimeAccurate = ({ date, timeZone = "UTC" }: DateTimeProps) => {
};
function formatDateTimeAccurate(date: Date, timeZone: string, locales: string[]): string {
const milliseconds = `00${date.getMilliseconds()}`.slice(-3);
const formattedDateTime = new Intl.DateTimeFormat(locales, {
year: "numeric",
month: "short",
day: "2-digit",
day: "numeric",
hour: "numeric",
minute: "2-digit",
second: "2-digit",
minute: "numeric",
second: "numeric",
timeZone,
// @ts-ignore this works in 92.5% of browsers https://caniuse.com/mdn-javascript_builtins_intl_datetimeformat_datetimeformat_options_parameter_options_fractionalseconddigits_parameter
fractionalSecondDigits: 3,
}).format(date);
return `${formatDateTime}.${milliseconds}`;
return formattedDateTime;
}
@@ -0,0 +1,95 @@
import { cn } from "~/utils/cn";
import { Icon, IconInBox, RenderIcon } from "./Icon";
import { Paragraph } from "./Paragraph";
const variations = {
small: {
label: {
variant: "small" as const,
className: "m-0 leading-[1.1rem]",
},
description: {
variant: "extra-small" as const,
className: "m-0",
},
},
base: {
label: {
variant: "base" as const,
className: "m-0 leading-[1.1rem] ",
},
description: {
variant: "small" as const,
className: "m-0",
},
},
};
type DetailCellProps = {
leadingIcon?: RenderIcon;
leadingIconClassName?: string;
trailingIcon?: RenderIcon;
trailingIconClassName?: string;
label: string | React.ReactNode;
description?: string | React.ReactNode;
className?: string;
variant?: keyof typeof variations;
};
export function DetailCell({
leadingIcon,
leadingIconClassName,
trailingIcon,
trailingIconClassName,
label,
description,
className,
variant = "small",
}: DetailCellProps) {
const variation = variations[variant];
return (
<div
className={cn(
"group flex h-11 w-full items-center gap-3 rounded-md p-1 pr-3 transition hover:bg-slate-900",
className
)}
>
<IconInBox
icon={leadingIcon}
className={cn("flex-none transition group-hover:border-slate-750", leadingIconClassName)}
/>
<div className="flex flex-1 flex-col">
<Paragraph
variant={variation.label.variant}
className={cn(
"flex-1 text-left transition group-hover:text-bright",
variation.label.className
)}
>
{label}
</Paragraph>
{description && (
<Paragraph
variant={variation.description.variant}
className={cn(
"flex-1 text-left text-dimmed transition group-hover:text-bright",
variation.description.className
)}
>
{description}
</Paragraph>
)}
</div>
<div className="flex flex-none items-center gap-1">
<Icon
icon={trailingIcon}
className={cn(
"h-6 w-6 flex-none transition group-hover:border-slate-750",
trailingIconClassName
)}
/>
</div>
</div>
);
}
@@ -2,8 +2,17 @@ import type { z } from "zod";
import { Paragraph } from "./Paragraph";
import { NamedIcon } from "./NamedIcon";
import { motion } from "framer-motion";
import { cn } from "~/utils/cn";
export function FormError({ children, id }: { children: React.ReactNode; id?: string }) {
export function FormError({
children,
id,
className,
}: {
children: React.ReactNode;
id?: string;
className?: string;
}) {
return (
<>
{children && (
@@ -11,7 +20,7 @@ export function FormError({ children, id }: { children: React.ReactNode; id?: st
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.3 }}
className="flex items-start gap-0.5"
className={cn("flex items-start gap-0.5", className)}
>
<NamedIcon name="error" className="h-4 w-4 shrink-0 justify-start" />
<Paragraph id={id} variant="extra-small" className="text-rose-500">
@@ -0,0 +1,37 @@
import { IconNamesOrString, NamedIcon } from "./NamedIcon";
import { cn } from "~/utils/cn";
export type RenderIcon = IconNamesOrString | React.ComponentType<any>;
type IconProps = {
icon?: RenderIcon;
className?: string;
};
/** Use this icon to either render a passed in React component, or a NamedIcon/CompanyIcon */
export function Icon(props: IconProps) {
if (typeof props.icon === "string") {
return <NamedIcon name={props.icon} className={props.className ?? ""} fallback={<></>} />;
}
const Icon = props.icon;
if (!Icon) {
return <></>;
}
return <Icon className={props.className} />;
}
export function IconInBox({ boxClassName, ...props }: IconProps & { boxClassName?: string }) {
return (
<div
className={cn(
"grid h-9 w-9 place-content-center rounded-sm border border-slate-750 bg-slate-850",
boxClassName
)}
>
<Icon icon={props.icon} className={cn("h-6 w-6", props.className)} />
</div>
);
}
@@ -21,6 +21,7 @@ import {
ChevronLeftIcon,
ChevronRightIcon,
ChevronUpIcon,
ClipboardDocumentCheckIcon,
ClockIcon,
CloudIcon,
CodeBracketSquareIcon,
@@ -34,12 +35,15 @@ import {
GlobeAltIcon,
HandRaisedIcon,
HeartIcon,
HomeIcon,
KeyIcon,
LightBulbIcon,
ListBulletIcon,
MagnifyingGlassIcon,
PlusIcon,
PlusSmallIcon,
QrCodeIcon,
Square2StackIcon,
SquaresPlusIcon,
StarIcon,
TrashIcon,
@@ -47,6 +51,7 @@ import {
UserGroupIcon,
UserIcon,
UserPlusIcon,
WindowIcon,
WrenchScrewdriverIcon,
XCircleIcon,
XMarkIcon,
@@ -63,6 +68,8 @@ import { Spinner } from "./Spinner";
import { SaplingIcon } from "~/assets/icons/SaplingIcon";
import { TwoTreesIcon } from "~/assets/icons/TwoTreesIcon";
import { OneTreeIcon } from "~/assets/icons/OneTreeIcon";
import { tablerIcons } from "~/utils/tablerIcons";
import tablerSpritePath from "./tabler-sprite.svg";
const icons = {
account: (className: string) => <UserCircleIcon className={cn("text-slate-400", className)} />,
@@ -71,7 +78,9 @@ const icons = {
"arrow-left": (className: string) => <ArrowLeftIcon className={cn("text-white", className)} />,
background: (className: string) => <CloudIcon className={cn("text-sky-400", className)} />,
beaker: (className: string) => <BeakerIcon className={cn("text-purple-500", className)} />,
bell: (className: string) => <BellAlertIcon className={cn("text-amber-500", className)} />,
billing: (className: string) => <CreditCardIcon className={cn("text-teal-500", className)} />,
browser: (className: string) => <WindowIcon className={cn("text-dimmed", className)} />,
calendar: (className: string) => (
<CalendarDaysIcon className={cn("text-purple-500", className)} />
),
@@ -108,6 +117,7 @@ const icons = {
<HandRaisedIcon className={cn("text-amber-400", className)} />
),
heart: (className: string) => <HeartIcon className={cn("text-rose-500", className)} />,
house: (className: string) => <HomeIcon className={cn("text-dimmed", className)} />,
id: (className: string) => <FingerPrintIcon className={cn("text-rose-200", className)} />,
inactive: (className: string) => <XCircleIcon className={cn("text-rose-500", className)} />,
info: (className: string) => <InformationCircleIcon className={cn("text-blue-500", className)} />,
@@ -120,6 +130,10 @@ const icons = {
job: (className: string) => <WrenchScrewdriverIcon className={cn("text-teal-500", className)} />,
key: (className: string) => <KeyIcon className={cn("text-amber-400", className)} />,
lightbulb: (className: string) => <LightBulbIcon className={cn("text-amber-400", className)} />,
"clipboard-checked": (className: string) => (
<ClipboardDocumentCheckIcon className={cn("text-dimmed", className)} />
),
list: (className: string) => <ListBulletIcon className={cn("text-slate-400", className)} />,
log: (className: string) => (
<ChatBubbleLeftEllipsisIcon className={cn("text-slate-400", className)} />
),
@@ -140,6 +154,7 @@ const icons = {
settings: (className: string) => <Cog8ToothIcon className={cn("text-slate-600", className)} />,
spinner: (className: string) => <Spinner className={className} color="blue" />,
"spinner-white": (className: string) => <Spinner className={className} color="white" />,
squares: (className: string) => <Square2StackIcon className={cn("text-dimmed", className)} />,
star: (className: string) => <StarIcon className={cn("text-yellow-500", className)} />,
stop: (className: string) => <StopIcon className={cn("text-rose-500", className)} />,
team: (className: string) => <UserGroupIcon className={cn("text-blue-500", className)} />,
@@ -202,7 +217,15 @@ export function NamedIcon({
);
}
console.log(`Icon ${name} not found`);
if (tablerIcons.has("tabler-" + name)) {
return <TablerIcon name={"tabler-" + name} className={className} />;
} else if (name.startsWith("tabler-") && tablerIcons.has(name)) {
return <TablerIcon name={name} className={className} />;
}
if (name === "supabase-management") {
return <NamedIcon name="supabase" className={className} />;
}
if (fallback) {
return fallback;
@@ -234,3 +257,11 @@ export function NamedIconInBox({
</div>
);
}
export function TablerIcon({ name, className }: { name: string; className?: string }) {
return (
<svg className={cn("stroke-[1.5]", className)}>
<use xlinkHref={`${tablerSpritePath}#${name}`} />
</svg>
);
}
@@ -23,7 +23,7 @@ export function ShortcutKey({ shortcut, variant, className }: ShortcutKeyProps)
const isMac = platform === "mac";
let relevantShortcut = "mac" in shortcut ? (isMac ? shortcut.mac : shortcut.windows) : shortcut;
const modifiers = relevantShortcut.modifiers ?? [];
const character = relevantShortcut.key;
const character = keyString(relevantShortcut.key, isMac);
return (
<span className={cn(variants[variant], className)}>
@@ -35,6 +35,15 @@ export function ShortcutKey({ shortcut, variant, className }: ShortcutKeyProps)
);
}
function keyString(key: String, isMac: boolean) {
switch (key) {
case "enter":
return isMac ? "↵" : key;
default:
return key;
}
}
function modifierString(modifier: Modifier, isMac: boolean) {
switch (modifier) {
case "alt":
@@ -42,8 +51,10 @@ function modifierString(modifier: Modifier, isMac: boolean) {
case "ctrl":
return isMac ? "⌃" : "Ctrl+";
case "meta":
return isMac ? "⌘" : "⊞";
return isMac ? "⌘" : "⊞+";
case "shift":
return isMac ? "⇧" : "Shift+";
case "mod":
return isMac ? "⌘" : "Ctrl+";
}
}
@@ -15,7 +15,7 @@ const variations = {
container: "flex items-center gap-x-1.5 rounded hover:bg-slate-850 pr-1 py-[0.1rem] pl-1.5",
root: "h-3 w-6",
thumb: "h-2.5 w-2.5 data-[state=checked]:translate-x-2.5 data-[state=unchecked]:translate-x-0",
text: "text-xs text-slate-400 group-hover:text-slate-200 mt-0.5",
text: "text-xs text-slate-400 group-hover:text-slate-200 hover:cursor-pointer",
},
};
+41 -65
View File
@@ -1,7 +1,7 @@
import { ExclamationCircleIcon, XMarkIcon } from "@heroicons/react/20/solid";
import { CheckCircleIcon } from "@heroicons/react/24/solid";
import { AnimatePresence, motion } from "framer-motion";
import toast, { Toaster, resolveValue, useToasterStore } from "react-hot-toast";
import { Toaster, toast } from "sonner";
import { useTypedLoaderData } from "remix-typedjson";
import { loader } from "~/root";
import { useEffect } from "react";
@@ -11,79 +11,55 @@ const permanentToastDuration = 60 * 60 * 24 * 1000;
export function Toast() {
const { toastMessage } = useTypedLoaderData<typeof loader>();
useEffect(() => {
if (!toastMessage) {
return;
}
const { message, type, options } = toastMessage;
switch (type) {
case "success":
toast.success(message, {
duration: options.ephemeral ? defaultToastDuration : permanentToastDuration,
});
break;
case "error":
toast.error(message, {
duration: options.ephemeral ? defaultToastDuration : permanentToastDuration,
});
break;
default:
throw new Error(`${type} is not handled`);
}
toast.custom((t) => <ToastUI variant={type} message={message} t={t as string} />, {
duration: options.ephemeral ? defaultToastDuration : permanentToastDuration,
});
}, [toastMessage]);
return <Toaster />;
}
export function ToastUI({
variant,
message,
t,
toastWidth = 356, // Default width, matches what sonner provides by default
}: {
variant: "error" | "success";
message: string;
t: string;
toastWidth?: string | number;
}) {
return (
<Toaster
position="bottom-right"
toastOptions={{
success: {
icon: <CheckCircleIcon className="h-6 w-6 text-green-600" />,
},
error: {
icon: <ExclamationCircleIcon className="h-6 w-6 text-rose-600" />,
},
<div
className={`self-end rounded-lg border border-slate-750 bg-midnight-900 shadow-md`}
style={{
width: toastWidth,
}}
>
{(t) => (
<AnimatePresence>
<motion.div
className="flex gap-2 rounded-lg border border-slate-750 bg-no-repeat p-4 text-bright shadow-md"
style={{
opacity: t.visible ? 1 : 0,
background:
"radial-gradient(at top, hsla(271, 91%, 65%, 0.18), hsla(221, 83%, 53%, 0.18)) hsla(221, 83%, 53%, 0.18)",
}}
initial={{ opacity: 0, y: 100 }}
animate={t.visible ? "visible" : "hidden"}
variants={{
hidden: {
opacity: 0,
y: 0,
transition: {
duration: 0.15,
ease: "easeInOut",
},
},
visible: {
opacity: 1,
y: 0,
transition: {
duration: 0.3,
ease: "easeInOut",
},
},
}}
>
{t.icon}
{resolveValue(t.message, t)}
<button className="p-1" onClick={() => toast.dismiss(t.id)}>
<XMarkIcon className="h-4 w-4 text-bright" />
</button>
</motion.div>
</AnimatePresence>
)}
</Toaster>
<div
className="flex w-full gap-2 rounded-lg bg-no-repeat p-4 text-bright"
style={{
background:
"radial-gradient(at top, hsla(271, 91%, 65%, 0.18), hsla(221, 83%, 53%, 0.18)) hsla(221, 83%, 53%, 0.18)",
}}
>
{variant === "success" ? (
<CheckCircleIcon className="h-6 w-6 text-green-600" />
) : (
<ExclamationCircleIcon className="h-6 w-6 text-rose-600" />
)}
{message}
<button className="ms-auto p-1" onClick={() => toast.dismiss(t)}>
<XMarkIcon className="h-4 w-4 text-bright" />
</button>
</div>
</div>
);
}
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 2.0 MiB

@@ -2,7 +2,7 @@ import { CodeBlock } from "~/components/code/CodeBlock";
import { DateTime } from "~/components/primitives/DateTime";
import { Paragraph } from "~/components/primitives/Paragraph";
import { RunStatusIcon, RunStatusLabel } from "~/components/runs/RunStatuses";
import { MatchedRun, useRun } from "~/hooks/useRun";
import { MatchedRun } from "~/hooks/useRun";
import { formatDuration } from "~/utils";
import {
RunPanel,
@@ -54,7 +54,7 @@ export function RunCompletedDetail({ run }: { run: MatchedRun }) {
<RunPanelDivider />
{run.error && <RunPanelError text={run.error.message} stackTrace={run.error.stack} />}
{run.output ? (
<CodeBlock language="json" code={run.output} />
<CodeBlock language="json" code={run.output} maxLines={36} />
) : (
run.output === null && <Paragraph variant="small">This run returned nothing</Paragraph>
)}
+13 -5
View File
@@ -12,7 +12,7 @@ import {
import { JobRunStatus, RuntimeEnvironmentType } from "@trigger.dev/database";
import { useMemo } from "react";
import { usePathName } from "~/hooks/usePathName";
import { Run } from "~/presenters/RunPresenter.server";
import { ViewRun } from "~/presenters/RunPresenter.server";
import { cancelSchema } from "~/routes/resources.runs.$runId.cancel";
import { schema } from "~/routes/resources.runs.$runId.rerun";
import { formatDuration } from "~/utils";
@@ -59,7 +59,7 @@ import { TaskCard } from "./TaskCard";
import { TaskCardSkeleton } from "./TaskCardSkeleton";
type RunOverviewProps = {
run: Run;
run: ViewRun;
trigger: {
icon: string;
title: string;
@@ -167,7 +167,13 @@ export function RunOverview({ run, trigger, showRerun, paths }: RunOverviewProps
<RunPanelHeader icon={trigger.icon} title={trigger.title} />
<RunPanelBody>
<RunPanelProperties
properties={[{ label: "Event name", text: run.event.name }, ...run.properties]}
properties={[{ label: "Event name", text: run.event.name }]
.concat(
run.event.externalAccount
? [{ label: "Account ID", text: run.event.externalAccount.identifier }]
: []
)
.concat(run.properties)}
/>
</RunPanelBody>
</RunPanel>
@@ -307,7 +313,8 @@ function RerunPopover({
const [form, { successRedirect }] = useForm({
id: "rerun",
lastSubmission,
// TODO: type this
lastSubmission: lastSubmission as any,
onValidate({ formData }) {
return parse(formData, { schema });
},
@@ -380,7 +387,8 @@ export function CancelRun({ runId }: { runId: string }) {
const [form, { redirectUrl }] = useForm({
id: "cancel-run",
lastSubmission,
// TODO: type this
lastSubmission: lastSubmission as any,
onValidate({ formData }) {
return parse(formData, { schema: cancelSchema });
},
+2 -2
View File
@@ -3,7 +3,7 @@ import { AnimatePresence, motion } from "framer-motion";
import { Fragment, useState } from "react";
import simplur from "simplur";
import { Paragraph } from "~/components/primitives/Paragraph";
import { Task } from "~/presenters/RunPresenter.server";
import { ViewTask } from "~/presenters/RunPresenter.server";
import { formatDuration } from "~/utils";
import { cn } from "~/utils/cn";
import {
@@ -22,7 +22,7 @@ import {
} from "./RunCard";
import { TaskStatusIcon } from "./TaskStatus";
type TaskCardProps = Task & {
type TaskCardProps = ViewTask & {
selectedId?: string;
selectedTask: (id: string) => void;
isLast: boolean;
+11 -16
View File
@@ -1,4 +1,3 @@
import { DetailedTask } from "~/presenters/TaskDetailsPresenter.server";
import {
RunPanel,
RunPanelBody,
@@ -29,22 +28,16 @@ import {
} from "../primitives/Table";
import { TaskAttemptStatusLabel } from "./TaskAttemptStatus";
import { TaskStatusIcon } from "./TaskStatus";
import { ClientOnly } from "remix-utils/client-only";
import { Spinner } from "../primitives/Spinner";
import type { DetailedTask } from "~/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam.tasks.$taskParam/route";
export function TaskDetail({ task }: { task: DetailedTask }) {
const {
name,
description,
icon,
startedAt,
completedAt,
status,
delayUntil,
params,
properties,
output,
style,
attempts,
} = task;
const { name, description, icon, status, params, properties, output, style, attempts } = task;
const startedAt = task.startedAt ? new Date(task.startedAt) : undefined;
const completedAt = task.completedAt ? new Date(task.completedAt) : undefined;
const delayUntil = task.delayUntil ? new Date(task.delayUntil) : undefined;
return (
<RunPanel selected={false}>
@@ -150,7 +143,9 @@ export function TaskDetail({ task }: { task: DetailedTask }) {
<div className="mt-4 flex flex-col gap-2">
<Header3>Output</Header3>
{output ? (
<CodeBlock code={JSON.stringify(output, null, 2)} />
<ClientOnly fallback={<Spinner />}>
{() => <CodeBlock code={output} maxLines={35} />}
</ClientOnly>
) : (
<Paragraph variant="small">No output</Paragraph>
)}
@@ -25,7 +25,7 @@ export function TriggerDetail({
};
properties: DisplayProperty[];
}) {
const { id, name, payload, timestamp, deliveredAt } = trigger;
const { id, name, payload, context, timestamp, deliveredAt } = trigger;
return (
<RunPanel selected={false}>
@@ -45,6 +45,14 @@ export function TriggerDetail({
/>
)}
<RunPanelIconProperty icon="id" label="Event name" value={name} />
<RunPanelIconProperty icon="account" label="Event ID" value={id} />
{trigger.externalAccount && (
<RunPanelIconProperty
icon="account"
label="Account ID"
value={trigger.externalAccount.identifier}
/>
)}
</RunPanelIconSection>
<RunPanelDivider />
<div className="mt-4 flex flex-col gap-2">
@@ -55,7 +63,9 @@ export function TriggerDetail({
</div>
)}
<Header3>Payload</Header3>
<CodeBlock code={JSON.stringify(payload, null, 2)} />
<CodeBlock code={payload} />
<Header3>Context</Header3>
<CodeBlock code={context} />
</div>
</RunPanelBody>
</RunPanel>
+30 -16
View File
@@ -1,15 +1,14 @@
import type { JobRunExecution, JobRunStatus } from "@trigger.dev/database";
import { NoSymbolIcon } from "@heroicons/react/20/solid";
import {
CheckCircleIcon,
ClockIcon,
ExclamationTriangleIcon,
StopIcon,
WrenchIcon,
XCircleIcon,
} from "@heroicons/react/24/solid";
import type { JobRunStatus } from "@trigger.dev/database";
import { cn } from "~/utils/cn";
import { Spinner } from "../primitives/Spinner";
import { HandRaisedIcon, NoSymbolIcon } from "@heroicons/react/20/solid";
export function hasFinished(status: JobRunStatus): boolean {
return (
@@ -17,7 +16,9 @@ export function hasFinished(status: JobRunStatus): boolean {
status === "FAILURE" ||
status === "ABORTED" ||
status === "TIMED_OUT" ||
status === "CANCELED"
status === "CANCELED" ||
status === "UNRESOLVED_AUTH" ||
status === "INVALID_PAYLOAD"
);
}
@@ -48,6 +49,9 @@ export function RunStatusIcon({ status, className }: { status: JobRunStatus; cla
return <XCircleIcon className={cn(runStatusClassNameColor(status), className)} />;
case "TIMED_OUT":
return <ExclamationTriangleIcon className={cn(runStatusClassNameColor(status), className)} />;
case "UNRESOLVED_AUTH":
case "INVALID_PAYLOAD":
return <XCircleIcon className={cn(runStatusClassNameColor(status), className)} />;
case "WAITING_ON_CONNECTIONS":
return <WrenchIcon className={cn(runStatusClassNameColor(status), className)} />;
case "ABORTED":
@@ -63,26 +67,26 @@ export type RunBasicStatus = "WAITING" | "PENDING" | "RUNNING" | "COMPLETED" | "
export function runBasicStatus(status: JobRunStatus): RunBasicStatus {
switch (status) {
case "SUCCESS":
return "COMPLETED";
case "WAITING_ON_CONNECTIONS":
case "QUEUED":
case "PREPROCESSING":
case "PENDING":
return "PENDING";
case "STARTED":
return "RUNNING";
case "QUEUED":
return "PENDING";
case "FAILURE":
return "FAILED";
case "TIMED_OUT":
return "FAILED";
case "WAITING_ON_CONNECTIONS":
return "PENDING";
case "ABORTED":
return "FAILED";
case "PREPROCESSING":
return "PENDING";
case "UNRESOLVED_AUTH":
case "CANCELED":
case "ABORTED":
case "INVALID_PAYLOAD":
return "FAILED";
case "SUCCESS":
return "COMPLETED";
default: {
const _exhaustiveCheck: never = status;
throw new Error(`Non-exhaustive match for value: ${status}`);
}
}
}
@@ -108,6 +112,14 @@ export function runStatusTitle(status: JobRunStatus): string {
return "Preprocessing";
case "CANCELED":
return "Canceled";
case "UNRESOLVED_AUTH":
return "Unresolved auth";
case "INVALID_PAYLOAD":
return "Invalid payload";
default: {
const _exhaustiveCheck: never = status;
throw new Error(`Non-exhaustive match for value: ${status}`);
}
}
}
@@ -122,6 +134,8 @@ export function runStatusClassNameColor(status: JobRunStatus): string {
case "QUEUED":
return "text-amber-300";
case "FAILURE":
case "UNRESOLVED_AUTH":
case "INVALID_PAYLOAD":
return "text-rose-500";
case "TIMED_OUT":
return "text-amber-300";
@@ -0,0 +1,46 @@
import type { Meta, StoryObj } from "@storybook/react";
import { DetailCell } from "../primitives/DetailCell";
import { ClockIcon, CodeBracketIcon } from "@heroicons/react/24/outline";
import { DateTime, DateTimeAccurate } from "../primitives/DateTime";
const meta: Meta = {
title: "Primitives/DetailCells",
};
export default meta;
type Story = StoryObj<typeof Examples>;
export const Basic: Story = {
render: () => <Examples />,
};
function Examples() {
return (
<div className="flex max-w-xl flex-col items-start gap-y-8 p-8">
<DetailCell
leadingIcon="integration"
leadingIconClassName="text-dimmed"
label="Learn how to create your own API Integrations"
variant="base"
trailingIcon="external-link"
trailingIconClassName="text-slate-700 group-hover:text-bright"
/>
<DetailCell
leadingIcon={CodeBracketIcon}
leadingIconClassName="text-blue-500"
label="Issue comment created"
trailingIcon="check"
trailingIconClassName="text-green-500 group-hover:text-green-400"
/>
<DetailCell
leadingIcon={ClockIcon}
leadingIconClassName="text-slate-400"
label={<DateTime date={new Date()} />}
description="Run #42 complete"
trailingIcon="plus"
trailingIconClassName="text-slate-500 group-hover:text-bright"
/>
</div>
);
}
@@ -1,6 +1,8 @@
import type { Meta, StoryObj } from "@storybook/react";
import { withDesign } from "storybook-addon-designs";
import { NamedIcon, iconNames } from "../primitives/NamedIcon";
import { tablerIcons } from "~/utils/tablerIcons";
import { Header1 } from "../primitives/Headers";
const meta: Meta<typeof NamedIcons> = {
title: "Icons",
@@ -25,17 +27,35 @@ export const Basic: Story = {
function NamedIcons() {
return (
<div className="grid grid-cols-8 gap-4">
{iconNames
.sort((a, b) => a.localeCompare(b))
.map((iconName) => (
<div key={iconName} className="flex items-center gap-2">
<div>
<NamedIcon name={iconName} className={"h-6 w-6"} />
<div className="flex flex-col gap-4">
<div>
<Header1 spacing>Internal</Header1>
<div className="grid grid-cols-8 gap-4">
{iconNames
.sort((a, b) => a.localeCompare(b))
.map((iconName) => (
<div key={iconName} className="flex items-center gap-2">
<div>
<NamedIcon name={iconName} className={"h-6 w-6"} />
</div>
<span className="text-xs text-dimmed">{iconName}</span>
</div>
))}
</div>
</div>
<div>
<Header1 spacing>Tabler</Header1>
<div className="grid grid-cols-8 gap-4">
{Array.from(tablerIcons).map((iconName) => (
<div key={iconName} className="flex items-center gap-2">
<div>
<NamedIcon name={iconName} className={"h-6 w-6 text-indigo-500"} />
</div>
<span className="text-xs text-dimmed">{iconName}</span>
</div>
<span className="text-xs text-dimmed">{iconName}</span>
</div>
))}
))}
</div>
</div>
</div>
);
}
@@ -24,6 +24,8 @@ const shortcuts: ShortcutDefinition[] = [
{ key: "f", modifiers: ["meta"] },
{ key: "k", modifiers: ["meta"] },
{ key: "del", modifiers: ["ctrl", "alt"] },
{ key: "enter", modifiers: ["meta"] },
{ key: "enter", modifiers: ["mod"] },
];
function Collection() {
@@ -67,6 +69,9 @@ function Set({ platform }: { platform: "mac" | "windows" }) {
<Button variant="danger/medium" shortcut={shortcut}>
Danger medium
</Button>
<Button variant="danger/medium" shortcut={shortcut}>
Danger medium
</Button>
</div>
))}
</OperatingSystemContextProvider>
@@ -0,0 +1,47 @@
import type { Meta, StoryObj } from "@storybook/react";
import { Toaster, toast } from "sonner";
import { ToastUI } from "../primitives/Toast";
import { Button } from "../primitives/Buttons";
const meta: Meta = {
title: "Primitives/Toast",
};
export default meta;
type Story = StoryObj<typeof Collection>;
export const Toasts: Story = {
render: () => <Collection />,
};
function Collection() {
return (
<div className="flex flex-col items-start gap-y-4 p-4">
<ToastUI variant="success" message="Success UI" t="-" />
<ToastUI variant="error" message="Error UI" t="-" />
<br />
<Button
variant="primary/large"
onClick={() =>
toast.custom((t) => <ToastUI variant="success" message="Success" t={t as string} />, {
duration: Infinity, // Prevents auto-dismissal for demo purposes
})
}
>
Success
</Button>
<Button
variant="primary/large"
onClick={() =>
toast.custom((t) => <ToastUI variant="error" message="Error" t={t as string} />, {
duration: Infinity,
})
}
>
Error
</Button>
<Toaster />
</div>
);
}
+4
View File
@@ -5,3 +5,7 @@ export const DEFAULT_MAX_CONCURRENT_RUNS = 10;
export const MAX_CONCURRENT_RUNS_LIMIT = 20;
export const PREPROCESS_RETRY_LIMIT = 2;
export const EXECUTE_JOB_RETRY_LIMIT = 10;
export const MAX_RUN_YIELDED_EXECUTIONS = 100;
export const RUN_CHUNK_EXECUTION_BUFFER = 350;
export const MAX_RUN_CHUNK_EXECUTION_LIMIT = 120000; // 2 minutes
export const RESPONSE_TIMEOUT_STATUS_CODES = [408, 504];
+7 -5
View File
@@ -31,7 +31,7 @@ export type PrismaTransactionOptions = {
/** Sets the transaction isolation level. By default this is set to the value currently configured in your database. */
isolationLevel?: Prisma.TransactionIsolationLevel;
rethrowPrismaErrors?: boolean;
swallowPrismaErrors?: boolean;
};
export async function $transaction<R>(
@@ -55,11 +55,9 @@ export async function $transaction<R>(
name: error.name,
});
if (options?.rethrowPrismaErrors) {
throw error;
if (options?.swallowPrismaErrors) {
return;
}
return;
}
throw error;
@@ -124,6 +122,10 @@ function getClient() {
emit: "stdout",
level: "warn",
},
// {
// emit: "stdout",
// level: "query",
// },
],
});
+80 -56
View File
@@ -1,6 +1,9 @@
import { H } from "@highlight-run/node";
import type { DataFunctionArgs, EntryContext, Headers } from "@remix-run/node"; // or cloudflare/deno
import { Response } from "@remix-run/node"; // or cloudflare/deno
import {
createReadableStreamFromReadable,
type DataFunctionArgs,
type EntryContext,
} from "@remix-run/node"; // or cloudflare/deno
import { RemixServer } from "@remix-run/react";
import { parseAcceptLanguage } from "intl-parse-accept-language";
import isbot from "isbot";
@@ -36,7 +39,7 @@ export default function handleRequest(
// response to render before sending it to the client. This
// ensures that bots can see the full page content.
if (isbot(request.headers.get("user-agent"))) {
return serveTheBots(
return handleBotRequest(
request,
responseStatusCode,
responseHeaders,
@@ -46,7 +49,7 @@ export default function handleRequest(
);
}
return serveBrowsers(
return handleBrowserRequest(
request,
responseStatusCode,
responseHeaders,
@@ -56,7 +59,7 @@ export default function handleRequest(
);
}
function serveTheBots(
function handleBotRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
@@ -65,76 +68,97 @@ function serveTheBots(
platform: OperatingSystemPlatform
) {
return new Promise((resolve, reject) => {
let shellRendered = false;
const { pipe, abort } = renderToPipeableStream(
<OperatingSystemContextProvider platform={platform}>
<LocaleContextProvider locales={locales}>
<RemixServer context={remixContext} url={request.url} abortDelay={ABORT_DELAY} />
<RemixServer context={remixContext} url={request.url} abortDelay={ABORT_DELAY} />,
</LocaleContextProvider>
</OperatingSystemContextProvider>,
{
// Use onAllReady to wait for the entire document to be ready
onAllReady() {
responseHeaders.set("Content-Type", "text/html; charset=utf-8");
let body = new PassThrough();
pipe(body);
resolve(
new Response(body, {
status: responseStatusCode,
headers: responseHeaders,
})
);
},
onShellError(err: unknown) {
reject(err);
},
}
);
setTimeout(abort, ABORT_DELAY);
});
}
shellRendered = true;
const body = new PassThrough();
const stream = createReadableStreamFromReadable(body);
responseHeaders.set("Content-Type", "text/html");
function serveBrowsers(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext,
locales: string[],
platform: OperatingSystemPlatform
) {
return new Promise((resolve, reject) => {
let didError = false;
let shellReady = false;
const { pipe, abort } = renderToPipeableStream(
<OperatingSystemContextProvider platform={platform}>
<LocaleContextProvider locales={locales}>
<RemixServer context={remixContext} url={request.url} abortDelay={ABORT_DELAY} />
</LocaleContextProvider>
</OperatingSystemContextProvider>,
{
// use onShellReady to wait until a suspense boundary is triggered
onShellReady() {
shellReady = true;
responseHeaders.set("Content-Type", "text/html; charset=utf-8");
let body = new PassThrough();
pipe(body);
resolve(
new Response(body, {
status: didError ? 500 : responseStatusCode,
new Response(stream, {
headers: responseHeaders,
status: responseStatusCode,
})
);
pipe(body);
},
onShellError(err: unknown) {
reject(err);
onShellError(error: unknown) {
reject(error);
},
onError(error: unknown) {
didError = true;
if (shellReady) {
logError(error, request);
responseStatusCode = 500;
// Log streaming rendering errors from inside the shell. Don't log
// errors encountered during initial shell rendering since they'll
// reject and get logged in handleDocumentRequest.
if (shellRendered) {
console.error(error);
}
},
}
);
setTimeout(abort, ABORT_DELAY);
});
}
function handleBrowserRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext,
locales: string[],
platform: OperatingSystemPlatform
) {
return new Promise((resolve, reject) => {
let shellRendered = false;
const { pipe, abort } = renderToPipeableStream(
<OperatingSystemContextProvider platform={platform}>
<LocaleContextProvider locales={locales}>
<RemixServer context={remixContext} url={request.url} abortDelay={ABORT_DELAY} />
</LocaleContextProvider>
</OperatingSystemContextProvider>,
{
onShellReady() {
shellRendered = true;
const body = new PassThrough();
const stream = createReadableStreamFromReadable(body);
responseHeaders.set("Content-Type", "text/html");
resolve(
new Response(stream, {
headers: responseHeaders,
status: responseStatusCode,
})
);
pipe(body);
},
onShellError(error: unknown) {
reject(error);
},
onError(error: unknown) {
responseStatusCode = 500;
// Log streaming rendering errors from inside the shell. Don't log
// errors encountered during initial shell rendering since they'll
// reject and get logged in handleDocumentRequest.
if (shellRendered) {
console.error(error);
}
},
}
);
setTimeout(abort, ABORT_DELAY);
});
}
+1
View File
@@ -40,6 +40,7 @@ const EnvironmentSchema = z.object({
EXECUTION_WORKER_POLL_INTERVAL: z.coerce.number().int().default(1000),
WORKER_ENABLED: z.string().default("true"),
EXECUTION_WORKER_ENABLED: z.string().default("true"),
GRACEFUL_SHUTDOWN_TIMEOUT: z.coerce.number().int().default(60000),
});
export type Environment = z.infer<typeof EnvironmentSchema>;
+9 -5
View File
@@ -1,23 +1,27 @@
import { RouteMatch } from "@remix-run/react";
import { UIMatch } from "@remix-run/react";
import { MatchedProject, useOptionalProject } from "./useProject";
import { useUser } from "./useUser";
export type ProjectJobEnvironment = MatchedProject["environments"][number];
export function useEnvironments(matches?: RouteMatch[]) {
export function useEnvironments(matches?: UIMatch[]) {
const project = useOptionalProject(matches);
if (!project) return;
return project.environments;
}
export function useDevEnvironment(matches?: RouteMatch[]) {
export function useDevEnvironment(matches?: UIMatch[]) {
const user = useUser();
const environments = useEnvironments(matches);
if (!environments) return;
return environments.find((environment) => environment.type === "DEVELOPMENT");
return environments.find(
(environment) => environment.type === "DEVELOPMENT" && environment.userId === user.id
);
}
export function useProdEnvironment(matches?: RouteMatch[]) {
export function useProdEnvironment(matches?: UIMatch[]) {
const environments = useEnvironments(matches);
if (!environments) return;
+21 -3
View File
@@ -1,9 +1,21 @@
import { ProjectJob } from "./useJobs";
import { useTextFilter } from "./useTextFilter";
import { useToggleFilter } from "./useToggleFilter";
export function useFilterJobs(jobs: ProjectJob[]) {
const { filterText, setFilterText, filteredItems } = useTextFilter<ProjectJob>({
export function useFilterJobs(jobs: ProjectJob[], onlyActiveJobs = false) {
const toggleFilterRes = useToggleFilter<ProjectJob>({
items: jobs,
filter: (job, onlyActiveJobs) => {
if (onlyActiveJobs && job.status !== "ACTIVE") {
return false;
}
return true;
},
defaultValue: onlyActiveJobs,
});
const textFilterRes = useTextFilter<ProjectJob>({
items: toggleFilterRes.filteredItems,
filter: (job, text) => {
if (job.slug.toLowerCase().includes(text.toLowerCase())) return true;
if (job.title.toLowerCase().includes(text.toLowerCase())) return true;
@@ -24,5 +36,11 @@ export function useFilterJobs(jobs: ProjectJob[]) {
},
});
return { filterText, setFilterText, filteredItems };
return {
filteredItems: textFilterRes.filteredItems,
filterText: textFilterRes.filterText,
setFilterText: textFilterRes.setFilterText,
onlyActiveJobs: toggleFilterRes.isToggleActive,
setOnlyActiveJobs: toggleFilterRes.setToggleActive,
};
}
@@ -1,4 +1,4 @@
import { RouteMatch } from "@remix-run/react";
import { UIMatch } from "@remix-run/react";
import { UseDataFunctionReturn } from "remix-typedjson";
import invariant from "tiny-invariant";
import type { loader } from "~/routes/_app.orgs.$organizationSlug.projects.$projectParam.integrations_.$clientParam/route";
@@ -6,7 +6,7 @@ import { useTypedMatchesData } from "./useTypedMatchData";
export type MatchedClient = UseDataFunctionReturn<typeof loader>["client"];
export function useOptionalIntegrationClient(matches?: RouteMatch[]) {
export function useOptionalIntegrationClient(matches?: UIMatch[]) {
const routeMatch = useTypedMatchesData<typeof loader>({
id: "routes/_app.orgs.$organizationSlug.projects.$projectParam.integrations_.$clientParam",
matches,
@@ -15,7 +15,7 @@ export function useOptionalIntegrationClient(matches?: RouteMatch[]) {
return routeMatch?.client;
}
export function useIntegrationClient(matches?: RouteMatch[]) {
export function useIntegrationClient(matches?: UIMatch[]) {
const integration = useOptionalIntegrationClient(matches);
invariant(integration, "Integration must be defined");
return integration;
@@ -1,6 +1,6 @@
import { RouteMatch, useMatches } from "@remix-run/react";
import { UIMatch, useMatches } from "@remix-run/react";
export function useIsProjectChildPage(matches?: RouteMatch[]) {
export function useIsProjectChildPage(matches?: UIMatch[]) {
if (!matches) {
matches = useMatches();
}
+3 -3
View File
@@ -2,14 +2,14 @@ import { UseDataFunctionReturn } from "remix-typedjson";
import invariant from "tiny-invariant";
import type { loader } from "~/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam/route";
import { useChanged } from "./useChanged";
import { RouteMatch } from "@remix-run/react";
import { UIMatch } from "@remix-run/react";
import { useTypedMatchesData } from "./useTypedMatchData";
export type MatchedJob = UseDataFunctionReturn<typeof loader>["job"];
export const jobMatchId =
"routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam";
export function useOptionalJob(matches?: RouteMatch[]) {
export function useOptionalJob(matches?: UIMatch[]) {
const routeMatch = useTypedMatchesData<typeof loader>({
id: jobMatchId,
matches,
@@ -22,7 +22,7 @@ export function useOptionalJob(matches?: RouteMatch[]) {
return routeMatch.projectJobs.find((j) => j.id === routeMatch.job.id);
}
export function useJob(matches?: RouteMatch[]) {
export function useJob(matches?: UIMatch[]) {
const job = useOptionalJob(matches);
invariant(job, "Job must be defined");
return job;
+3 -3
View File
@@ -1,7 +1,7 @@
import { UseDataFunctionReturn } from "remix-typedjson";
import invariant from "tiny-invariant";
import type { loader } from "~/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam/route";
import { RouteMatch } from "@remix-run/react";
import { UIMatch } from "@remix-run/react";
import { useTypedMatchesData } from "./useTypedMatchData";
export type ProjectJob = UseDataFunctionReturn<typeof loader>["projectJobs"][number];
@@ -12,7 +12,7 @@ export const jobsMatchId =
// This is only used in the JobsMenu component, which is the breadcrumb job list dropdown.
// This dropdown is only shown once you have selected a job, so we can assume that
// the route above has loaded and we can use the data from it.
export function useOptionalJobs(matches?: RouteMatch[]) {
export function useOptionalJobs(matches?: UIMatch[]) {
const routeMatch = useTypedMatchesData<typeof loader>({
id: jobsMatchId,
matches,
@@ -21,7 +21,7 @@ export function useOptionalJobs(matches?: RouteMatch[]) {
return routeMatch?.projectJobs;
}
export function useJobs(matches?: RouteMatch[]) {
export function useJobs(matches?: UIMatch[]) {
const jobs = useOptionalJobs(matches);
invariant(jobs, "Jobs must be defined");
return jobs;
+6 -6
View File
@@ -4,12 +4,12 @@ import type { loader as orgLoader } from "~/routes/_app.orgs.$organizationSlug/r
import type { loader as appLoader } from "~/routes/_app/route";
import { hydrateObject, useMatchesData } from "~/utils";
import { useChanged } from "./useChanged";
import { RouteMatch } from "@remix-run/react";
import { UIMatch } from "@remix-run/react";
import { useTypedMatchesData } from "./useTypedMatchData";
export type MatchedOrganization = UseDataFunctionReturn<typeof appLoader>["organizations"][number];
export function useOptionalOrganizations(matches?: RouteMatch[]) {
export function useOptionalOrganizations(matches?: UIMatch[]) {
const data = useTypedMatchesData<typeof appLoader>({
id: "routes/_app",
matches,
@@ -17,13 +17,13 @@ export function useOptionalOrganizations(matches?: RouteMatch[]) {
return data?.organizations;
}
export function useOrganizations(matches?: RouteMatch[]) {
export function useOrganizations(matches?: UIMatch[]) {
const orgs = useOptionalOrganizations(matches);
invariant(orgs, "No organizations found in loader.");
return orgs;
}
export function useOptionalOrganization(matches?: RouteMatch[]) {
export function useOptionalOrganization(matches?: UIMatch[]) {
const orgs = useOptionalOrganizations(matches);
const org = useTypedMatchesData<typeof orgLoader>({
id: "routes/_app.orgs.$organizationSlug",
@@ -37,13 +37,13 @@ export function useOptionalOrganization(matches?: RouteMatch[]) {
return orgs.find((o) => o.id === org.organization.id);
}
export function useOrganization(matches?: RouteMatch[]) {
export function useOrganization(matches?: UIMatch[]) {
const org = useOptionalOrganization(matches);
invariant(org, "No organization found in loader.");
return org;
}
export function useIsNewOrganizationPage(matches?: RouteMatch[]): boolean {
export function useIsNewOrganizationPage(matches?: UIMatch[]): boolean {
const data = useTypedMatchesData<any>({
id: "routes/_app.orgs.new",
matches,
+3 -3
View File
@@ -1,4 +1,4 @@
import { RouteMatch } from "@remix-run/react";
import { UIMatch } from "@remix-run/react";
import { UseDataFunctionReturn } from "remix-typedjson";
import invariant from "tiny-invariant";
import type { loader } from "~/routes/_app.orgs.$organizationSlug.projects.$projectParam/route";
@@ -9,7 +9,7 @@ export type MatchedProject = UseDataFunctionReturn<typeof loader>["project"];
export const projectMatchId = "routes/_app.orgs.$organizationSlug.projects.$projectParam";
export function useOptionalProject(matches?: RouteMatch[]) {
export function useOptionalProject(matches?: UIMatch[]) {
const routeMatch = useTypedMatchesData<typeof loader>({
id: projectMatchId,
matches,
@@ -18,7 +18,7 @@ export function useOptionalProject(matches?: RouteMatch[]) {
return routeMatch?.project;
}
export function useProject(matches?: RouteMatch[]) {
export function useProject(matches?: UIMatch[]) {
const project = useOptionalProject(matches);
invariant(project, "Project must be defined");
return project;
@@ -0,0 +1,73 @@
import { useEffect } from "react";
import { useEventSource } from "remix-utils/sse/react";
import { projectPath, projectStreamingPath } from "~/utils/pathBuilder";
import { useProject } from "./useProject";
import { useOrganization } from "./useOrganizations";
import { useNavigate } from "@remix-run/react";
export function useProjectSetupComplete() {
const project = useProject();
const organization = useOrganization();
const navigate = useNavigate();
const events = useEventSource(projectStreamingPath(project.id), {
event: "message",
});
useEffect(() => {
if (events !== null) {
// This uses https://www.npmjs.com/package/canvas-confetti
if ("confetti" in window && typeof window.confetti !== "undefined") {
const duration = 3.5 * 1000;
const animationEnd = Date.now() + duration;
const defaults = {
startVelocity: 30,
spread: 360,
ticks: 60,
zIndex: 0,
colors: [
"#E7FF52",
"#41FF54",
"rgb(245 158 11)",
"rgb(22 163 74)",
"rgb(37 99 235)",
"rgb(67 56 202)",
"rgb(219 39 119)",
"rgb(225 29 72)",
"rgb(217 70 239)",
],
};
function randomInRange(min: number, max: number): number {
return Math.random() * (max - min) + min;
}
// @ts-ignore
const interval = setInterval(function () {
const timeLeft = animationEnd - Date.now();
if (timeLeft <= 0) {
return clearInterval(interval);
}
const particleCount = 60 * (timeLeft / duration);
// since particles fall down, start a bit higher than random
// @ts-ignore
window.confetti(
Object.assign({}, defaults, {
particleCount,
origin: { x: randomInRange(0.1, 0.4), y: Math.random() - 0.2 },
})
);
// @ts-ignore
window.confetti(
Object.assign({}, defaults, {
particleCount,
origin: { x: randomInRange(0.6, 0.9), y: Math.random() - 0.2 },
})
);
}, 250);
}
navigate(projectPath(organization, project));
}
// WARNING Don't put the revalidator in the useEffect deps array or bad things will happen
}, [events]); // eslint-disable-line react-hooks/exhaustive-deps
}
+3 -3
View File
@@ -1,4 +1,4 @@
import { RouteMatch } from "@remix-run/react";
import { UIMatch } from "@remix-run/react";
import { UseDataFunctionReturn } from "remix-typedjson";
import invariant from "tiny-invariant";
import type { loader as runLoader } from "~/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam/route";
@@ -7,7 +7,7 @@ import { useTypedMatchesData } from "./useTypedMatchData";
export type MatchedRun = UseDataFunctionReturn<typeof runLoader>["run"];
export function useOptionalRun(matches?: RouteMatch[]) {
export function useOptionalRun(matches?: UIMatch[]) {
const project = useOptionalProject(matches);
const routeMatch = useTypedMatchesData<typeof runLoader>({
id: "routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam",
@@ -21,7 +21,7 @@ export function useOptionalRun(matches?: RouteMatch[]) {
return routeMatch.run;
}
export function useRun(matches?: RouteMatch[]) {
export function useRun(matches?: UIMatch[]) {
const run = useOptionalRun(matches);
invariant(run, "Run must be present");
return run;
+23 -11
View File
@@ -1,12 +1,12 @@
import { useEffect, useState } from "react";
import { useHotkeys } from "react-hotkeys-hook";
import { useOperatingSystem } from "~/components/primitives/OperatingSystemProvider";
export type Modifier = "alt" | "ctrl" | "meta" | "shift";
export type Modifier = "alt" | "ctrl" | "meta" | "shift" | "mod";
export type Shortcut = {
key: string;
modifiers?: Modifier[];
enabledOnInputElements?: boolean;
};
export type ShortcutDefinition =
@@ -20,19 +20,31 @@ type useShortcutKeysProps = {
shortcut: ShortcutDefinition;
action: (event: KeyboardEvent) => void;
disabled?: boolean;
enabledOnInputElements?: boolean;
};
export function useShortcutKeys({ shortcut, action, disabled = false }: useShortcutKeysProps) {
const keys = createKeysFromShortcut(shortcut);
useHotkeys(keys, action, { enabled: !disabled });
}
function createKeysFromShortcut(shortcut: ShortcutDefinition) {
const { platform } = useOperatingSystem();
const isMac = platform === "mac";
let relevantShortcut = "mac" in shortcut ? (isMac ? shortcut.mac : shortcut.windows) : shortcut;
const modifiers = relevantShortcut.modifiers;
const character = relevantShortcut.key;
const relevantShortcut = "mac" in shortcut ? (isMac ? shortcut.mac : shortcut.windows) : shortcut;
return modifiers ? modifiers.map((k) => k).join("+") + "+" : "" + character;
const keys = createKeysFromShortcut(relevantShortcut);
useHotkeys(
keys,
(event, hotkeysEvent) => {
action(event);
},
{
enabled: !disabled,
enableOnFormTags: relevantShortcut.enabledOnInputElements,
enableOnContentEditable: relevantShortcut.enabledOnInputElements,
}
);
}
function createKeysFromShortcut(shortcut: Shortcut) {
const modifiers = shortcut.modifiers;
const character = shortcut.key;
return modifiers ? modifiers.map((k) => k).join("+") + "+" + character : character;
}
+21
View File
@@ -0,0 +1,21 @@
import { useMemo, useState } from "react";
type ToggleFilterProps<T> = {
items: T[];
filter: (item: T, isToggleActive: boolean) => boolean;
defaultValue?: boolean;
};
export function useToggleFilter<T>({ items, filter, defaultValue = false }: ToggleFilterProps<T>) {
const [isToggleActive, setToggleActive] = useState(defaultValue);
const filteredItems = useMemo<T[]>(() => {
return items.filter((item) => filter(item, isToggleActive));
}, [items, isToggleActive]);
return {
isToggleActive,
setToggleActive,
filteredItems,
};
}
+4 -4
View File
@@ -1,4 +1,4 @@
import { RouteMatch, useMatches } from "@remix-run/react";
import { UIMatch, useMatches } from "@remix-run/react";
import { RemixSerializedType, UseDataFunctionReturn, deserializeRemix } from "remix-typedjson";
type AppData = any;
@@ -8,7 +8,7 @@ function useTypedDataFromMatches<T = AppData>({
matches,
}: {
id: string;
matches: RouteMatch[];
matches: UIMatch[];
}): UseDataFunctionReturn<T> | undefined {
const match = matches.find((m) => m.id === id);
return useTypedMatchData<T>(match);
@@ -19,7 +19,7 @@ export function useTypedMatchesData<T = AppData>({
matches,
}: {
id: string;
matches?: RouteMatch[];
matches?: UIMatch[];
}): UseDataFunctionReturn<T> | undefined {
if (!matches) {
matches = useMatches();
@@ -29,7 +29,7 @@ export function useTypedMatchesData<T = AppData>({
}
export function useTypedMatchData<T = AppData>(
match: RouteMatch | undefined
match: UIMatch | undefined
): UseDataFunctionReturn<T> | undefined {
if (!match) {
return undefined;
+3 -3
View File
@@ -1,11 +1,11 @@
import type { User } from "~/models/user.server";
import { useMatchesData } from "~/utils";
import { useChanged } from "./useChanged";
import { RouteMatch } from "@remix-run/react";
import { UIMatch } from "@remix-run/react";
import { useTypedMatchesData } from "./useTypedMatchData";
import { loader } from "~/root";
export function useOptionalUser(matches?: RouteMatch[]): User | undefined {
export function useOptionalUser(matches?: UIMatch[]): User | undefined {
const routeMatch = useTypedMatchesData<typeof loader>({
id: "root",
matches,
@@ -14,7 +14,7 @@ export function useOptionalUser(matches?: RouteMatch[]): User | undefined {
return routeMatch?.user ?? undefined;
}
export function useUser(matches?: RouteMatch[]): User {
export function useUser(matches?: UIMatch[]): User {
const maybeUser = useOptionalUser(matches);
if (!maybeUser) {
throw new Error(
+101
View File
@@ -0,0 +1,101 @@
import { RuntimeEnvironmentType, type RuntimeEnvironment } from "@trigger.dev/database";
import { prisma } from "~/db.server";
import { customAlphabet } from "nanoid";
const apiKeyId = customAlphabet(
"1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
12
);
type RegenerateAPIKeyInput = {
userId: string;
environmentId: string;
};
export async function regenerateApiKey({ userId, environmentId }: RegenerateAPIKeyInput) {
const environment = await prisma.runtimeEnvironment.findUnique({
where: {
id: environmentId,
},
include: {
organization: true,
project: true,
},
});
if (!environment) {
throw new Error("Environment does not exist");
}
// check if the user is part of the org
const organization = await prisma.organization.findFirst({
where: {
id: environment.organization.id,
members: { some: { userId } },
},
});
if (!organization) {
throw new Error("User does not have permission to regenerate API key");
}
// check if it is the user's dev environment
if (environment.type === RuntimeEnvironmentType.DEVELOPMENT) {
if (!environment.orgMemberId) {
throw new Error("User does not have permission to regenerate API key");
}
const orgMember = await prisma.orgMember.findFirst({
where: {
organizationId: organization.id,
userId: userId,
id: environment.orgMemberId,
},
});
if (!orgMember) {
throw new Error("User does not have permission to regenerate API key");
}
}
// generate and store new keys
const newApiKey = createApiKeyForEnv(environment.type);
const newPkApiKey = createPkApiKeyForEnv(environment.type);
const updatedEnviroment = await prisma.runtimeEnvironment.update({
data: {
apiKey: newApiKey,
pkApiKey: newPkApiKey,
},
where: {
id: environmentId,
},
});
return updatedEnviroment;
}
export function createApiKeyForEnv(envType: RuntimeEnvironment["type"]) {
return `tr_${envSlug(envType)}_${apiKeyId(20)}`;
}
export function createPkApiKeyForEnv(envType: RuntimeEnvironment["type"]) {
return `pk_${envSlug(envType)}_${apiKeyId(20)}`;
}
export function envSlug(environmentType: RuntimeEnvironment["type"]) {
switch (environmentType) {
case "DEVELOPMENT": {
return "dev";
}
case "PRODUCTION": {
return "prod";
}
case "STAGING": {
return "stg";
}
case "PREVIEW": {
return "prev";
}
}
}
+12
View File
@@ -1,3 +1,4 @@
import { RESPONSE_TIMEOUT_STATUS_CODES } from "~/consts";
import { prisma } from "~/db.server";
import { Prettify } from "~/lib.es5";
@@ -18,3 +19,14 @@ export async function findEndpoint(id: string) {
},
});
}
export function detectResponseIsTimeout(response?: Response) {
if (!response) {
return false;
}
return (
RESPONSE_TIMEOUT_STATUS_CODES.includes(response.status) ||
response.headers.get("x-vercel-error") === "FUNCTION_INVOCATION_TIMEOUT"
);
}
@@ -1,14 +0,0 @@
import { z } from "zod";
const IndexEndpointStatsSchema = z.object({
jobs: z.number(),
sources: z.number(),
dynamicTriggers: z.number(),
dynamicSchedules: z.number(),
});
export type IndexEndpointStats = z.infer<typeof IndexEndpointStatsSchema>;
export function parseEndpointIndexStats(stats: unknown): IndexEndpointStats {
return IndexEndpointStatsSchema.parse(stats);
}
@@ -2,31 +2,12 @@ import { JobRun, JobRunExecution } from "@trigger.dev/database";
import { PrismaClientOrTransaction } from "~/db.server";
import { executionWorker } from "~/services/worker.server";
export async function enqueueRunExecutionV1(
execution: JobRunExecution,
queueId: string,
concurrency: number,
tx: PrismaClientOrTransaction,
runAt?: Date
) {
const job = await executionWorker.enqueue(
"performRunExecution",
{
id: execution.id,
},
{
queueName: `job:queue:${queueId}`,
tx,
runAt,
jobKey: `execution:${execution.runId}`,
}
);
}
export type EnqueueRunExecutionV2Options = {
runAt?: Date;
resumeTaskId?: string;
isRetry?: boolean;
skipRetrying?: boolean;
executionCount?: number;
};
export async function enqueueRunExecutionV2(
@@ -43,10 +24,12 @@ export async function enqueueRunExecutionV2(
isRetry: typeof options.isRetry === "boolean" ? options.isRetry : false,
},
{
queueName: `job:${run.jobId}:env:${run.environmentId}`,
tx,
runAt: options.runAt,
jobKey: `job_run:${run.id}`,
jobKey: `job_run:${run.id}:${options.executionCount ?? 0}${
options.resumeTaskId ? `:task:${options.resumeTaskId}` : ""
}`,
maxAttempts: options.skipRetrying ? 1 : undefined,
}
);
}

Some files were not shown because too many files have changed in this diff Show More