diff --git a/packages/core/package.json b/packages/core/package.json
index e206763058..09c77045fa 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -13,7 +13,7 @@
],
"exports": {
".": {
- "import": "./dist/index.js",
+ "import": "./dist/esm/index.js",
"require": "./dist/index.js"
},
"./package.json": "./package.json"
@@ -35,6 +35,7 @@
"@trigger.dev/tsconfig": "workspace:*",
"@types/jest": "^29.5.3",
"@types/node": "16",
+ "esbuild-plugin-polyfill-node": "^0.3.0",
"jest": "^29.6.2",
"rimraf": "^3.0.2",
"ts-jest": "^29.1.1",
diff --git a/packages/core/tsup.config.ts b/packages/core/tsup.config.ts
index ec5c6d83df..a05936c773 100644
--- a/packages/core/tsup.config.ts
+++ b/packages/core/tsup.config.ts
@@ -1,4 +1,5 @@
import { defineConfig } from "tsup";
+import { polyfillNode } from "esbuild-plugin-polyfill-node";
export default defineConfig([
{
@@ -6,15 +7,25 @@ export default defineConfig([
config: "tsconfig.build.json",
entry: ["./src/index.ts"],
outDir: "./dist",
- platform: "neutral",
- format: ["cjs"],
+ platform: "node",
+ format: ["cjs", "esm"],
legacyOutput: true,
sourcemap: true,
clean: true,
bundle: true,
splitting: false,
dts: true,
- external: ["http", "https", "util", "events", "tty", "os", "timers"],
- esbuildPlugins: [],
+ external: ["http", "https", "util", "events", "tty", "os", "timers" ],
+ esbuildPlugins: [polyfillNode({
+ globals: {
+ global: false,
+ buffer: true,
+ process: false,
+ navigator: false
+ },
+ polyfills: {
+ buffer: true,
+ },
+ }) as any],
},
]);
diff --git a/packages/react/src/events.ts b/packages/react/src/events.ts
index c240515b2b..c15c75f36c 100644
--- a/packages/react/src/events.ts
+++ b/packages/react/src/events.ts
@@ -15,7 +15,7 @@ export function useEventDetails(eventId: string | undefined): UseEventDetailsRes
return useQuery(
{
- queryKey: [`triggerdotdev-event-${eventId}`],
+ queryKey: [`triggerdotdev-eventdetails-${eventId}`],
queryFn: async () => {
return await zodfetch(GetEventSchema, `${apiUrl}/api/v1/events/${eventId}`, {
method: "GET",
diff --git a/packages/react/src/runs.ts b/packages/react/src/runs.ts
index 1cd1bee130..676e90c4d0 100644
--- a/packages/react/src/runs.ts
+++ b/packages/react/src/runs.ts
@@ -28,7 +28,7 @@ export function useRunDetails(
return useQuery(
{
- queryKey: [`triggerdotdev-run-${runId}`],
+ queryKey: [`triggerdotdev-details-${runId}`],
queryFn: async () => {
return await zodfetch(GetRunSchema, url, {
method: "GET",
diff --git a/packages/react/src/statuses.ts b/packages/react/src/statuses.ts
index ec722d6640..5478a0f946 100644
--- a/packages/react/src/statuses.ts
+++ b/packages/react/src/statuses.ts
@@ -47,7 +47,7 @@ export function useRunStatuses(
const queryResult = useQuery(
{
- queryKey: [`triggerdotdev-run-${runId}`],
+ queryKey: [`triggerdotdev-runstatuses-${runId}`],
queryFn: async () => {
return await zodfetch(GetRunStatusesSchema, `${apiUrl}/api/v1/runs/${runId}/statuses`, {
method: "GET",
diff --git a/packages/svelte/.eslintignore b/packages/svelte/.eslintignore
new file mode 100644
index 0000000000..38972655fa
--- /dev/null
+++ b/packages/svelte/.eslintignore
@@ -0,0 +1,13 @@
+.DS_Store
+node_modules
+/build
+/.svelte-kit
+/package
+.env
+.env.*
+!.env.example
+
+# Ignore files for PNPM, NPM and YARN
+pnpm-lock.yaml
+package-lock.json
+yarn.lock
diff --git a/packages/svelte/.eslintrc.cjs b/packages/svelte/.eslintrc.cjs
new file mode 100644
index 0000000000..ebc19589fa
--- /dev/null
+++ b/packages/svelte/.eslintrc.cjs
@@ -0,0 +1,30 @@
+module.exports = {
+ root: true,
+ extends: [
+ 'eslint:recommended',
+ 'plugin:@typescript-eslint/recommended',
+ 'plugin:svelte/recommended',
+ 'prettier'
+ ],
+ parser: '@typescript-eslint/parser',
+ plugins: ['@typescript-eslint'],
+ parserOptions: {
+ sourceType: 'module',
+ ecmaVersion: 2020,
+ extraFileExtensions: ['.svelte']
+ },
+ env: {
+ browser: true,
+ es2017: true,
+ node: true
+ },
+ overrides: [
+ {
+ files: ['*.svelte'],
+ parser: 'svelte-eslint-parser',
+ parserOptions: {
+ parser: '@typescript-eslint/parser'
+ }
+ }
+ ]
+};
diff --git a/packages/svelte/.gitignore b/packages/svelte/.gitignore
new file mode 100644
index 0000000000..ac7211b403
--- /dev/null
+++ b/packages/svelte/.gitignore
@@ -0,0 +1,11 @@
+.DS_Store
+node_modules
+/build
+/dist
+/.svelte-kit
+/package
+.env
+.env.*
+!.env.example
+vite.config.js.timestamp-*
+vite.config.ts.timestamp-*
diff --git a/packages/svelte/.prettierignore b/packages/svelte/.prettierignore
new file mode 100644
index 0000000000..38972655fa
--- /dev/null
+++ b/packages/svelte/.prettierignore
@@ -0,0 +1,13 @@
+.DS_Store
+node_modules
+/build
+/.svelte-kit
+/package
+.env
+.env.*
+!.env.example
+
+# Ignore files for PNPM, NPM and YARN
+pnpm-lock.yaml
+package-lock.json
+yarn.lock
diff --git a/packages/svelte/.prettierrc b/packages/svelte/.prettierrc
new file mode 100644
index 0000000000..a77fddea90
--- /dev/null
+++ b/packages/svelte/.prettierrc
@@ -0,0 +1,9 @@
+{
+ "useTabs": true,
+ "singleQuote": true,
+ "trailingComma": "none",
+ "printWidth": 100,
+ "plugins": ["prettier-plugin-svelte"],
+ "pluginSearchDirs": ["."],
+ "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
+}
diff --git a/packages/svelte/README.md b/packages/svelte/README.md
new file mode 100644
index 0000000000..4fee31f6f8
--- /dev/null
+++ b/packages/svelte/README.md
@@ -0,0 +1,58 @@
+# create-svelte
+
+Everything you need to build a Svelte library, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).
+
+Read more about creating a library [in the docs](https://kit.svelte.dev/docs/packaging).
+
+## Creating a project
+
+If you're seeing this, you've probably already done this step. Congrats!
+
+```bash
+# create a new project in the current directory
+npm create svelte@latest
+
+# create a new project in my-app
+npm create svelte@latest my-app
+```
+
+## Developing
+
+Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
+
+```bash
+npm run dev
+
+# or start the server and open the app in a new browser tab
+npm run dev -- --open
+```
+
+Everything inside `src/lib` is part of your library, everything inside `src/routes` can be used as a showcase or preview app.
+
+## Building
+
+To build your library:
+
+```bash
+npm run package
+```
+
+To create a production version of your showcase app:
+
+```bash
+npm run build
+```
+
+You can preview the production build with `npm run preview`.
+
+> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
+
+## Publishing
+
+Go into the `package.json` and give your package the desired name through the `"name"` option. Also consider adding a `"license"` field and point it to a `LICENSE` file which you can create from a template (one popular option is the [MIT license](https://opensource.org/license/mit/)).
+
+To publish your library to [npm](https://www.npmjs.com):
+
+```bash
+npm publish
+```
diff --git a/packages/svelte/package.json b/packages/svelte/package.json
new file mode 100644
index 0000000000..bfa686e62f
--- /dev/null
+++ b/packages/svelte/package.json
@@ -0,0 +1,64 @@
+{
+ "name": "@trigger.dev/svelte",
+ "version": "2.1.9",
+ "description": "Trigger.dev Svelte SDK",
+ "license": "MIT",
+ "scripts": {
+ "dev": "vite dev",
+ "build": "svelte-package --input ./src --output ./build",
+ "preview": "vite preview",
+ "package": "svelte-kit sync && svelte-package && publint",
+ "prepublishOnly": "npm run package",
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
+ "test": "vitest",
+ "lint": "prettier --plugin-search-dir . --check . && eslint .",
+ "format": "prettier --plugin-search-dir . --write ."
+ },
+ "type": "module",
+ "types": "dist/trigger.d.ts",
+ "module": "dist/trigger.js",
+ "exports": {
+ ".": {
+ "types": "./dist/trigger.d.ts",
+ "import": "./dist/trigger.js",
+ "svelte": "./dist/trigger.js",
+ "default": "./dist/trigger.js"
+ },
+ "./package.json": "./package.json"
+ },
+ "files": [
+ "dist",
+ "!dist/**/*.test.*",
+ "!dist/**/*.spec.*"
+ ],
+ "peerDependencies": {
+ "svelte": "^4.0.0"
+ },
+ "devDependencies": {
+ "@sveltejs/adapter-auto": "^2.0.0",
+ "@sveltejs/kit": "^1.20.4",
+ "@sveltejs/package": "^2.0.0",
+ "@typescript-eslint/eslint-plugin": "^5.45.0",
+ "@typescript-eslint/parser": "^5.45.0",
+ "eslint": "^8.28.0",
+ "eslint-config-prettier": "^8.5.0",
+ "eslint-plugin-svelte": "^2.30.0",
+ "prettier": "^2.8.0",
+ "prettier-plugin-svelte": "^2.10.1",
+ "publint": "^0.1.9",
+ "svelte": "^4.2.1",
+ "svelte-check": "^3.4.3",
+ "tslib": "^2.4.1",
+ "typescript": "^5.0.0",
+ "vite": "^4.4.2",
+ "vitest": "^0.34.0"
+ },
+ "dependencies": {
+ "@tanstack/svelte-query": "^4.33.0",
+ "@trigger.dev/core": "workspace:*",
+ "@trigger.dev/sdk": "workspace:*",
+ "esm-env": "^1.0.0",
+ "zod": "3.22.3"
+ }
+}
diff --git a/packages/svelte/src/app.d.ts b/packages/svelte/src/app.d.ts
new file mode 100644
index 0000000000..6713760814
--- /dev/null
+++ b/packages/svelte/src/app.d.ts
@@ -0,0 +1,14 @@
+///
+
+// See https://kit.svelte.dev/docs/types#app
+// for information about these interfaces
+declare global {
+ namespace App {
+ // interface Error {}
+ // interface Locals {}
+ // interface PageData {}
+ // interface Platform {}
+ }
+}
+declare module '*.svelte'
+export {};
\ No newline at end of file
diff --git a/packages/svelte/src/app.html b/packages/svelte/src/app.html
new file mode 100644
index 0000000000..effe0d0d26
--- /dev/null
+++ b/packages/svelte/src/app.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ %sveltekit.head%
+
+
+ %sveltekit.body%
+
+
diff --git a/packages/svelte/src/lib/TriggerProvider.svelte b/packages/svelte/src/lib/TriggerProvider.svelte
new file mode 100644
index 0000000000..612bd18fa4
--- /dev/null
+++ b/packages/svelte/src/lib/TriggerProvider.svelte
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
diff --git a/packages/svelte/src/lib/events.ts b/packages/svelte/src/lib/events.ts
new file mode 100644
index 0000000000..0f5b7ee479
--- /dev/null
+++ b/packages/svelte/src/lib/events.ts
@@ -0,0 +1,86 @@
+import { createQuery, type CreateQueryResult } from '@tanstack/svelte-query';
+import { GetEventSchema, type GetEvent } from '@trigger.dev/core';
+import { getTriggerContext } from './providerContext.js';
+import { zodfetch } from './fetch.js';
+import { onDestroy } from 'svelte';
+import { writable } from 'svelte/store';
+import { runResolvedStatuses, type RunDetailOptions } from "./runs.js";
+import { urlWithSearchParams, GetRunSchema, type GetRun } from '@trigger.dev/core';
+const defaultRefreshInterval = 1000;
+
+export type UseEventDetailsResult = CreateQueryResult;
+export function useEventDetails(eventId: string | undefined ): UseEventDetailsResult {
+ const { apiUrl, publicApiKey } = getTriggerContext();
+
+ return createQuery({
+ queryKey: [`triggerdotdev-event-${eventId}`],
+ queryFn: async () => {
+ return await zodfetch(GetEventSchema, `${apiUrl}/api/v1/events/${eventId}`, {
+ method: 'GET',
+ headers: {
+ Authorization: `Bearer ${publicApiKey}`
+ }
+ });
+ },
+ refetchInterval: (data) => {
+ if (
+ data &&
+ data.runs.length > 0 &&
+ data.runs.every((r) => runResolvedStatuses.includes(r.status))
+ ) {
+ return false;
+ }
+
+ return defaultRefreshInterval;
+ },
+ enabled: !!eventId,
+ });
+}
+
+
+
+type Omit = Pick>
+type PartialBy = Omit & Partial>
+
+const resultStore = writable<{data: PartialBy | undefined, error: Error| undefined} >({data: undefined, error: undefined});
+
+export function useEventRunDetails(
+ eventId: string | undefined,
+ options?: RunDetailOptions
+): typeof resultStore{
+ const event = useEventDetails(eventId);
+ const { apiUrl, publicApiKey } = getTriggerContext();
+
+ const subscribedEvent = event.subscribe(async (event) => {
+ if (event.data) {
+ // console.log('event: ', event.data?.id);
+
+ const url = urlWithSearchParams(`${apiUrl}/api/v1/runs/${event.data?.runs[0].id}`, options);
+
+ //we cannot call useRunDetails inside the subscription, because it would be called outside component initialization, we will have to do it inside the svelte component itself
+
+ // Because of useRunDetails use Context in async function(subscribe) which is detached from the component tree it couses an error.
+ // So we use simple fetch.
+ try {
+ const req = await zodfetch(GetRunSchema, url, {
+ method: 'GET',
+ headers: {
+ Authorization: `Bearer ${publicApiKey}`
+ }
+ });
+ resultStore.set({data: req, error: undefined});
+ } catch (error) {
+ resultStore.set({data: undefined, error: error as Error});
+ }
+ }
+ if(event.error){
+ resultStore.set({data: undefined, error: event.error as Error});
+ }
+ });
+
+ onDestroy(() => {
+ subscribedEvent();
+ });
+
+ return resultStore;
+}
diff --git a/packages/svelte/src/lib/fetch.ts b/packages/svelte/src/lib/fetch.ts
new file mode 100644
index 0000000000..cf82ecc17a
--- /dev/null
+++ b/packages/svelte/src/lib/fetch.ts
@@ -0,0 +1,32 @@
+import type { z } from 'zod';
+
+// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint
+export async function zodfetch(
+ schema: z.Schema,
+ url: string,
+ requestInit?: RequestInit
+): Promise {
+ const response = await fetch(url, requestInit);
+
+ if ((!requestInit || requestInit.method === 'GET') && response.status === 404) {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ return;
+ }
+
+ //todo improve error handling
+
+ if (response.status >= 400 && response.status < 500) {
+ const body = await response.json();
+
+ throw new Error(body.error);
+ }
+
+ if (response.status !== 200) {
+ throw new Error(`Failed to fetch ${url}, got status code ${response.status}`);
+ }
+
+ const jsonBody = await response.json();
+
+ return schema.parse(jsonBody);
+}
diff --git a/packages/svelte/src/lib/providerContext.ts b/packages/svelte/src/lib/providerContext.ts
new file mode 100644
index 0000000000..27d6576603
--- /dev/null
+++ b/packages/svelte/src/lib/providerContext.ts
@@ -0,0 +1,19 @@
+import { getContext, setContext } from 'svelte';
+
+
+export type TriggerContext = {
+ publicApiKey: string;
+ apiUrl?: string;
+};
+const triggerContextKey = "$$_TriggerContext"
+
+
+export function setTriggerContext(context: TriggerContext) {
+ setContext(triggerContextKey, context);
+}
+
+export function getTriggerContext(): TriggerContext {
+ return getContext(triggerContextKey);
+}
+
+
diff --git a/packages/svelte/src/lib/runs.ts b/packages/svelte/src/lib/runs.ts
new file mode 100644
index 0000000000..869590c8a0
--- /dev/null
+++ b/packages/svelte/src/lib/runs.ts
@@ -0,0 +1,54 @@
+import { createQuery, type CreateQueryResult } from '@tanstack/svelte-query';
+import {
+ GetRunSchema,
+ urlWithSearchParams,
+ type GetRun,
+ type GetRunOptions
+} from '@trigger.dev/core';
+import { getTriggerContext } from './providerContext.js';
+import { zodfetch } from './fetch.js';
+
+export const runResolvedStatuses = ['SUCCESS', 'FAILURE', 'CANCELED', 'TIMED_OUT', 'ABORTED'];
+
+const defaultRefreshInterval = 1000;
+
+export type RunDetailOptions = GetRunOptions & {
+ /** How often you want to refresh, the default is 1000. Min is 500 */
+ refreshIntervalMs?: number;
+};
+
+export type UseRunDetailsResult = CreateQueryResult;
+
+export function useRunDetails(
+ runId: string | undefined,
+ options?: RunDetailOptions,
+): UseRunDetailsResult {
+ const { apiUrl, publicApiKey } = getTriggerContext();
+
+ const { refreshIntervalMs: refreshInterval, ...otherOptions } = options || {};
+
+ const url = urlWithSearchParams(`${apiUrl}/api/v1/runs/${runId}`, otherOptions);
+
+ return createQuery({
+ queryKey: [`triggerdotdev-rundetails-${runId}`],
+ queryFn: async () => {
+ return await zodfetch(GetRunSchema, url, {
+ method: 'GET',
+ headers: {
+ Authorization: `Bearer ${publicApiKey}`
+ }
+ });
+ },
+ enabled: !!runId,
+ refetchInterval: (data) => {
+ if (data?.status && runResolvedStatuses.includes(data.status)) {
+ return false;
+ }
+ if (refreshInterval !== undefined) {
+ return Math.max(refreshInterval, 500);
+ }
+
+ return defaultRefreshInterval;
+ }
+ });
+}
diff --git a/packages/svelte/src/lib/statuses.ts b/packages/svelte/src/lib/statuses.ts
new file mode 100644
index 0000000000..641b26872d
--- /dev/null
+++ b/packages/svelte/src/lib/statuses.ts
@@ -0,0 +1,170 @@
+import { createQuery } from '@tanstack/svelte-query';
+import {
+ GetRunStatuses,
+ GetRunStatusesSchema
+} from "@trigger.dev/core";
+import { useEventDetails } from "./events";
+import { getTriggerContext } from './providerContext.js';
+import { zodfetch } from './fetch.js';
+import { onDestroy } from 'svelte';
+import { writable } from 'svelte/store';
+import { runResolvedStatuses } from "./runs.js";
+
+
+
+const defaultRefreshInterval = 1000;
+
+export type RunStatusesOptions = {
+ /** How often you want to refresh, the default is 1000. Min is 500 */
+ refreshIntervalMs?: number;
+};
+
+export type UseRunStatusesResult =
+ | {
+ fetchStatus: "loading";
+ error: undefined;
+ statuses: undefined;
+ run: undefined;
+ }
+ | {
+ fetchStatus: "error";
+ error: Error;
+ statuses: undefined;
+ run: undefined;
+ }
+ | ({
+ fetchStatus: "success";
+ error: undefined;
+ } & GetRunStatuses);
+
+
+const resultStatusesStore = writable();
+
+export function useRunStatuses(
+ runId: string | undefined,
+ options?: RunStatusesOptions
+): typeof resultStatusesStore {
+ const { apiUrl, publicApiKey } = getTriggerContext();
+
+ const queryResult = createQuery({
+ queryKey: [`triggerdotdev-runstatuses-${runId}`],
+ queryFn: async () => {
+ return await zodfetch(GetRunStatusesSchema, `${apiUrl}/api/v1/runs/${runId}/statuses`, {
+ method: "GET",
+ headers: {
+ Authorization: `Bearer ${publicApiKey}`,
+ },
+ });
+ },
+ enabled: !!runId,
+ refetchInterval: (data) => {
+ if (data?.run.status && runResolvedStatuses.includes(data.run.status)) {
+ return false;
+ }
+ if (options?.refreshIntervalMs !== undefined) {
+ return Math.max(options.refreshIntervalMs, 500);
+ }
+
+ return defaultRefreshInterval;
+ },
+ },
+ );
+ queryResult.subscribe(queryResult => {
+ switch (queryResult.status) {
+ case "loading": {
+ resultStatusesStore.set( {
+ fetchStatus: "loading",
+ error: undefined,
+ statuses: undefined,
+ run: undefined,
+ });
+ break;
+ }
+ case "error": {
+ resultStatusesStore.set({
+ fetchStatus: "error",
+ error: queryResult.error as Error,
+ statuses: undefined,
+ run: undefined,
+ });
+ break;
+ }
+ case "success": {
+ resultStatusesStore.set( {
+ fetchStatus: "success",
+ error: undefined,
+ run: queryResult.data.run,
+ statuses: queryResult.data.statuses,
+ });
+ break;
+ }
+ }
+ })
+
+ return resultStatusesStore;
+}
+
+// const resultStore = writable<{data: GetRunStatuses | undefined, error: Error | null}>({data: undefined, error: null});
+const resultStore = writable({
+ fetchStatus: "loading",
+ error: undefined,
+ statuses: undefined,
+ run: undefined,
+});
+
+export function useEventRunStatuses(
+ eventId: string | undefined,
+): typeof resultStore{
+ const event = useEventDetails(eventId);
+ const { apiUrl, publicApiKey } = getTriggerContext();
+
+ const subscribedEvent = event.subscribe(async (event) => {
+ if (event.data) {
+ // console.log('event: ', event.data?.id);
+
+ //we cannot call useRunStatuses inside the subscription, because it would be called outside component initialization, we will have to do it inside the svelte component itself
+
+ // Because of useRunStatuses use Context in async function(subscribe) which is detached from the component tree it couses an error.
+ // So we use simple fetch.
+ try{
+ const req = await zodfetch(GetRunStatusesSchema, `${apiUrl}/api/v1/runs/${event.data?.runs[0].id}/statuses`, {
+ method: 'GET',
+ headers: {
+ Authorization: `Bearer ${publicApiKey}`
+ }
+ });
+
+
+ resultStore.set( {
+ fetchStatus: "success",
+ error: undefined,
+ run: req.run,
+ statuses: req.statuses,
+ });
+
+
+ } catch (error) {
+ resultStore.set({
+ fetchStatus: "error",
+ error: error as Error,
+ statuses: undefined,
+ run: undefined,
+ });
+ }
+ }
+ if(event.error){
+ resultStore.set({
+ fetchStatus: "error",
+ error: event.error as Error,
+ statuses: undefined,
+ run: undefined,
+ });
+ }
+ });
+
+ onDestroy(() => {
+ subscribedEvent();
+ });
+
+ return resultStore;
+}
diff --git a/packages/svelte/src/lib/trigger.ts b/packages/svelte/src/lib/trigger.ts
new file mode 100644
index 0000000000..382dee463b
--- /dev/null
+++ b/packages/svelte/src/lib/trigger.ts
@@ -0,0 +1,5 @@
+export * from './events.js'
+export * from './runs.js'
+export * from './statuses.js'
+
+export { default as TriggerProvider } from './TriggerProvider.svelte';
diff --git a/packages/svelte/src/routes/+layout.js b/packages/svelte/src/routes/+layout.js
new file mode 100644
index 0000000000..5829b7eebf
--- /dev/null
+++ b/packages/svelte/src/routes/+layout.js
@@ -0,0 +1 @@
+export const ssr = false;
\ No newline at end of file
diff --git a/packages/svelte/src/routes/+layout.svelte b/packages/svelte/src/routes/+layout.svelte
new file mode 100644
index 0000000000..b60bbb66ec
--- /dev/null
+++ b/packages/svelte/src/routes/+layout.svelte
@@ -0,0 +1,13 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/svelte/src/routes/+page.js b/packages/svelte/src/routes/+page.js
new file mode 100644
index 0000000000..5829b7eebf
--- /dev/null
+++ b/packages/svelte/src/routes/+page.js
@@ -0,0 +1 @@
+export const ssr = false;
\ No newline at end of file
diff --git a/packages/svelte/src/routes/+page.svelte b/packages/svelte/src/routes/+page.svelte
new file mode 100644
index 0000000000..870a641a52
--- /dev/null
+++ b/packages/svelte/src/routes/+page.svelte
@@ -0,0 +1,108 @@
+
+
+eventId - {runId}
+status1 - {status1}
+status2 - {status2}
+
+{status3}
+
+
+{#if !useEventDetailsData}
+ Loading...
+{/if}
+{#if useEventDetailsError}
+ {useEventDetailsError.message}
+{/if}
+{#if useEventDetailsData}
+
+
{useEventDetailsData.name}
+
Runs: {useEventDetailsData.runs?.length}
+
+ {#each useEventDetailsData.runs as run}
+
+
+ Run {run.id}: {run.status}
+
+
+ {/each}
+
+
+{/if}
\ No newline at end of file
diff --git a/packages/svelte/svelte.config.js b/packages/svelte/svelte.config.js
new file mode 100644
index 0000000000..9002d78ab4
--- /dev/null
+++ b/packages/svelte/svelte.config.js
@@ -0,0 +1,18 @@
+import adapter from '@sveltejs/adapter-auto';
+import { vitePreprocess } from '@sveltejs/kit/vite';
+
+/** @type {import('@sveltejs/kit').Config} */
+const config = {
+ // Consult https://kit.svelte.dev/docs/integrations#preprocessors
+ // for more information about preprocessors
+ preprocess: vitePreprocess(),
+
+ kit: {
+ // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
+ // If your environment is not supported or you settled on a specific environment, switch out the adapter.
+ // See https://kit.svelte.dev/docs/adapters for more information about adapters.
+ adapter: adapter(),
+ }
+};
+
+export default config;
diff --git a/packages/svelte/tsconfig.json b/packages/svelte/tsconfig.json
new file mode 100644
index 0000000000..2a2938f468
--- /dev/null
+++ b/packages/svelte/tsconfig.json
@@ -0,0 +1,26 @@
+{
+ "extends": "./.svelte-kit/tsconfig.json",
+ "compilerOptions": {
+ "allowJs": true,
+ "checkJs": true,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "resolveJsonModule": true,
+ "skipLibCheck": true,
+ "sourceMap": true,
+ "strict": true,
+ "moduleResolution": "Node",
+ "ignoreDeprecations": "5.0",
+ "preserveValueImports": false, // in compliance with "@trigger.dev/core"
+ "importsNotUsedAsValues": "remove", // in compliance with "@trigger.dev/core"
+ "paths": {
+ "@trigger.dev/core": ["./../core/src/index"],
+ "@trigger.dev/core/*": ["./../core/src/*"],
+ "@trigger.dev/sdk": ["./../trigger-sdk/src/index"],
+ "@trigger.dev/sdk/*": ["./../trigger-sdk/src/*"],
+ "$lib": ["./src/lib"],
+ "$lib/*": ["./src/lib/*"]
+ }
+ },
+ "exclude": ["node_modules"]
+}
diff --git a/packages/svelte/vite.config.ts b/packages/svelte/vite.config.ts
new file mode 100644
index 0000000000..37b6a84bc3
--- /dev/null
+++ b/packages/svelte/vite.config.ts
@@ -0,0 +1,9 @@
+import { sveltekit } from '@sveltejs/kit/vite';
+import { defineConfig } from 'vitest/config';
+
+export default defineConfig({
+ plugins: [sveltekit()],
+ test: {
+ include: ['src/**/*.{test,spec}.{js,ts}']
+ }
+});