feat: add nuxt adapter (#460)

* feat: add nuxt adapter

* fix link

* Update FrameworkSelector.tsx

* Update FrameworkSelector.tsx

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
This commit is contained in:
neo773
2023-10-19 18:52:45 +05:30
committed by GitHub
parent 65fa8300ad
commit dfef239197
25 changed files with 15498 additions and 12471 deletions
@@ -63,7 +63,7 @@ export function FrameworkSelector() {
<FrameworkLink to={projectSetupAstroPath(organization, project)}>
<AstroLogo className="w-32" />
</FrameworkLink>
<FrameworkLink to={projectSetupNuxtPath(organization, project)}>
<FrameworkLink to={projectSetupNuxtPath(organization, project)} supported>
<NuxtLogo className="w-32" />
</FrameworkLink>
<FrameworkLink to={projectSetupSvelteKitPath(organization, project)}>
@@ -1,21 +1,213 @@
import { NuxtLogo } from "~/assets/logos/NuxtLogo";
import { FrameworkComingSoon } from "~/components/frameworks/FrameworkComingSoon";
import { ChatBubbleLeftRightIcon, Squares2X2Icon } from "@heroicons/react/20/solid";
import { useState } from "react";
import invariant from "tiny-invariant";
import { Feedback } from "~/components/Feedback";
import { PageGradient } from "~/components/PageGradient";
import { InitCommand, RunDevCommand, TriggerDevStep } from "~/components/SetupCommands";
import { StepContentContainer } from "~/components/StepContentContainer";
import { InlineCode } from "~/components/code/InlineCode";
import { BreadcrumbLink } from "~/components/navigation/NavBar";
import { Button, LinkButton } from "~/components/primitives/Buttons";
import {
ClientTabs,
ClientTabsContent,
ClientTabsList,
ClientTabsTrigger,
} from "~/components/primitives/ClientTabs";
import { ClipboardField } from "~/components/primitives/ClipboardField";
import { Header1 } from "~/components/primitives/Headers";
import { NamedIcon } from "~/components/primitives/NamedIcon";
import { Paragraph } from "~/components/primitives/Paragraph";
import { RadioGroup, RadioGroupItem } from "~/components/primitives/RadioButton";
import { StepNumber } from "~/components/primitives/StepNumber";
import { useAppOrigin } from "~/hooks/useAppOrigin";
import { useProjectSetupComplete } from "~/hooks/useProjectSetupComplete";
import { useDevEnvironment } from "~/hooks/useEnvironments";
import { useOrganization } from "~/hooks/useOrganizations";
import { useProject } from "~/hooks/useProject";
import { Handle } from "~/utils/handle";
import { trimTrailingSlash } from "~/utils/pathBuilder";
import { projectSetupPath, trimTrailingSlash } from "~/utils/pathBuilder";
import { Callout } from "~/components/primitives/Callout";
type SelectionChoices = "use-existing-project" | "create-new-nuxt-app";
export const handle: Handle = {
breadcrumb: (match) => <BreadcrumbLink to={trimTrailingSlash(match.pathname)} title="Nuxt" />,
};
export default function Page() {
export default function SetupNuxt3() {
const organization = useOrganization();
const project = useProject();
useProjectSetupComplete();
const devEnvironment = useDevEnvironment();
const appOrigin = useAppOrigin();
const [selectedValue, setSelectedValue] = useState<SelectionChoices | null>(null);
invariant(devEnvironment, "devEnvironment is required");
return (
<FrameworkComingSoon
frameworkName="Nuxt"
githubIssueUrl="https://github.com/triggerdotdev/trigger.dev/issues/447"
githubIssueNumber={447}
>
<NuxtLogo className="w-56" />
</FrameworkComingSoon>
<PageGradient>
<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-nuxt-app" ? "5" : "2"} minutes
</Header1>
<div className="flex items-center gap-2">
<LinkButton
to={projectSetupPath(organization, project)}
variant="tertiary/small"
LeadingIcon={Squares2X2Icon}
>
Choose a different framework
</LinkButton>
<Feedback
button={
<Button variant="tertiary/small" LeadingIcon={ChatBubbleLeftRightIcon}>
I'm stuck!
</Button>
}
defaultValue="help"
/>
</div>
</div>
<RadioGroup
className="mb-4 flex gap-x-2"
onValueChange={(value) => setSelectedValue(value as SelectionChoices)}
>
<RadioGroupItem
label="Use an existing Nuxt project"
description="Use Trigger.dev in an existing Nuxt 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 Nuxt project"
description="This is the quickest way to try out Trigger.dev in a new Nuxt project and takes 5 mins."
value="create-new-nuxt-app"
checked={selectedValue === "create-new-nuxt-app"}
variant="icon"
data-action="create-new-nuxt-app"
icon={<NamedIcon className="h-8 w-8 text-green-600" name={"sapling"} />}
/>
</RadioGroup>
{selectedValue && (
<>
<Callout
variant={"info"}
to="https://github.com/triggerdotdev/trigger.dev/discussions/430"
className="mb-8"
>
Trigger.dev has full support for serverless. We will be adding support for
long-running servers soon.
</Callout>
{selectedValue === "create-new-nuxt-app" ? (
<>
<StepNumber stepNumber="1" title="Create a new Nuxt 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 nuxi@latest init <project-name>`}
/>
</ClientTabsContent>
<ClientTabsContent value={"pnpm"}>
<ClipboardField
variant="primary/medium"
className="mb-4"
value={`pnpm dlx nuxi@latest init <project-name>`}
/>
</ClientTabsContent>
<ClientTabsContent value={"yarn"}>
<ClipboardField
variant="primary/medium"
className="mb-4"
value={`yarn create nuxt-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 Nuxt project" />
<StepContentContainer>
<Paragraph spacing>
You have now created a new Nuxt 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 Nuxt 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 Nuxt app" />
<StepContentContainer>
<RunDevCommand />
</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 Nuxt 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 Nuxt app" />
<StepContentContainer>
<RunDevCommand />
</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>
</PageGradient>
);
}
+219 -1
View File
@@ -1 +1,219 @@
We're in the process of building support for the Nuxt framework. You can follow along with progress or contribute via [this GitHub issue](https://github.com/triggerdotdev/trigger.dev/issues).
<Accordion defaultOpen title="Don't have a Nuxt project yet to add Trigger.dev to? No problem, you can complete the Manual Setup using a blank Nuxt project:">
Create a blank project by running the `nuxi@latest init <project-name>` command in your terminal:
<CodeGroup>
```bash npm
npx nuxi@latest init <project-name>
```
```bash pnpm
pnpm dlx nuxi@latest init <project-name>
```
```bash yarn
yarn nuxi@latest init <project-name>
```
</CodeGroup>
</Accordion>
## Installing Required Packages
To begin, install the necessary packages in your Nuxt project directory. You can choose one of the following package managers:
<CodeGroup>
```bash npm
npm i @trigger.dev/sdk @trigger-dev/nuxtjs
```
```bash pnpm
pnpm install @trigger.dev/sdk @trigger-dev/nuxtjs
```
```bash yarn
yarn add @trigger.dev/sdk @trigger-dev/nuxtjs
```
</CodeGroup>
<br />
<Note>Ensure that you execute this command within a Nuxt project.</Note>
## Obtaining the Development API Key
To locate your development API key, login to the [Trigger.dev
dashboard](https://cloud.trigger.dev) and select the Project you want to
connect to. Then click on the Environments & API Keys tab in the left menu.
You can copy your development API Key from the field at the top of this page.
(Your development key will start with `tr_dev_`).
## Adding Environment Variables
Create a `.env.local` file at the root of your project and include your Trigger API key and URL like this:
```bash
TRIGGER_API_KEY=ENTER_YOUR_DEVELOPMENT_API_KEY_HERE
TRIGGER_API_URL=https://cloud.trigger.dev
```
Replace `ENTER_YOUR_DEVELOPMENT_API_KEY_HERE` with the actual API key obtained from the previous step.
## Configuring the Trigger Client
To set up the Trigger Client for your project, follow these steps:
1. **Create Configuration File:**
In your project directory, create a configuration file named `trigger.ts`.
2. **Choose Directory:**
Depending on your project structure, choose the appropriate directory for the configuration file. If your project uses a `src` directory, create the file within it. Otherwise, create it directly in the project root.
3. **Add Configuration Code:**
Open the configuration file you created and add the following code:
```typescript
import { TriggerClient } from "@trigger.dev/sdk";
export const client = new TriggerClient({
id: "my-app",
apiKey: process.env.TRIGGER_API_KEY,
apiUrl: process.env.TRIGGER_API_URL,
});
```
Replace **"my-app"** with an appropriate identifier for your project. The **apiKey** and **apiUrl** are obtained from the environment variables you set earlier.
4. **File Location:**
Depending on your project structure, save the configuration file in the appropriate location:
- If your project uses a **src** directory, save the file within the **src** directory.
- If your project does not use a **src** directory, save the file in the project root.
**Example Directory Structure with src:**
```
project-root/
├── src/
├── trigger.ts
├── other files...
```
**Example Directory Structure without src:**
```
project-root/
├── trigger.ts
├── other files...
```
By following these steps, you'll configure the Trigger Client to work with your project, regardless of whether you have a separate **src** directory and whether you're using TypeScript or JavaScript files.
## Creating the API Route
To establish an API route for interacting with Trigger.dev, follow these steps.
1. Create a new file named `trigger.ts` within the `server/api/` directory.
2. Add the following code to `trigger.ts`:
```typescript
import { client } from "@/trigger";
import { createNuxtRoute } from "@trigger.dev/nuxtjs";
import { eventTrigger } from "@trigger.dev/sdk";
client.defineJob({
id: "hello-world",
name: "Hello World",
version: "0.0.1",
trigger: eventTrigger({
name: "starter.hello-world",
}),
run: async (_payload, io, _ctx) => {
await io.logger.info("Hello world!");
return {
message: "Hello world!",
};
},
});
// Add your jobs here
const nuxt = createNuxtRoute(client);
export default defineEventHandler(nuxt);
```
## Adding Configuration to `package.json`
Inside the `package.json` file, add the following configuration under the root object:
```json
"trigger.dev": {
"endpointId": "my-app"
}
```
Your `package.json` file might look something like this:
```json
{
"name": "my-app",
"version": "1.0.0",
"dependencies": {
// ... other dependencies
},
"trigger.dev": {
"endpointId": "my-app"
}
}
```
Replace **"my-app"** with the appropriate identifier you used during the step for creating the Trigger Client.
## Nuxt Steps
Start your Nuxt project locally, and then execute the `dev` CLI command to run Trigger.dev locally. You should run this command every time you want to use Trigger.dev locally.
![Your first Job](/images/cli-dev.gif)
<Warning>
Make sure your Nuxt site is running locally before continuing. You must also leave this `dev`
terminal command running while you develop.
</Warning>
In a **new terminal window or tab** run:
<CodeGroup>
```bash npm
npx @trigger.dev/cli@latest dev
```
```bash pnpm
pnpm dlx @trigger.dev/cli@latest dev
```
```bash yarn
yarn dlx @trigger.dev/cli@latest dev
```
</CodeGroup>
<br />
<Note>
You can optionally pass the port if you're not running on 3000 by adding
`--port 3001` to the end
</Note>
<Note>
You can optionally pass the hostname if you're not running on localhost by adding
`--hostname <host>`. Example, in case your Nuxt is running on 0.0.0.0: `--hostname 0.0.0.0`.
</Note>
@@ -28,4 +28,5 @@ Each platform has one or more adaptors, see the guides below:
| ------------------------------------------------- | -------------------- |
| [Next.js](/documentation/guides/platforms/nextjs) | `createPagesRoute()` |
| [Next.js](/documentation/guides/platforms/nextjs) | `createAppRoute()` |
| [Nuxt.js](/documentation/guides/platforms/nuxt) | `createNuxtRoute()` |
| Express | Coming soon |
+24
View File
@@ -0,0 +1,24 @@
# Nuxt dev/build outputs
.output
.data
.nuxt
.nitro
.cache
dist
# Node dependencies
node_modules
# Logs
logs
*.log
# Misc
.DS_Store
.fleet
.idea
# Local env files
.env
.env.*
!.env.example
+1
View File
@@ -0,0 +1 @@
shamefully-hoist=true
+63
View File
@@ -0,0 +1,63 @@
# Nuxt 3 Minimal Starter
Look at the [Nuxt 3 documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
## Setup
Make sure to install the dependencies:
```bash
# npm
npm install
# pnpm
pnpm install
# yarn
yarn install
```
## Development Server
Start the development server on `http://localhost:3000`:
```bash
# npm
npm run dev
# pnpm
pnpm run dev
# yarn
yarn dev
```
## Production
Build the application for production:
```bash
# npm
npm run build
# pnpm
pnpm run build
# yarn
yarn build
```
Locally preview production build:
```bash
# npm
npm run preview
# pnpm
pnpm run preview
# yarn
yarn preview
```
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
+5
View File
@@ -0,0 +1,5 @@
<template>
<div>
<NuxtWelcome />
</div>
</template>
+4
View File
@@ -0,0 +1,4 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
devtools: { enabled: true }
})
+24
View File
@@ -0,0 +1,24 @@
{
"name": "nuxt-app",
"private": true,
"scripts": {
"build": "nuxt build",
"dev": " nuxi dev --dotenv .env.local --host",
"preview": "nuxt preview",
"postinstall": "nuxt prepare"
},
"dependencies": {
"@trigger.dev/nextjs": "^2.1.0",
"@trigger.dev/nuxtjs": "workspace:*",
"@trigger.dev/sdk": "^2.1.0",
"zod": "3.21.4"
},
"devDependencies": {
"@nuxt/devtools": "latest",
"@trigger.dev/cli": "workspace:*",
"nuxt": "^3.7.1"
},
"trigger.dev": {
"endpointId": "nuxt-E9C7"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

+52
View File
@@ -0,0 +1,52 @@
import { client } from "@/trigger";
import { createNuxtRoute} from "@trigger.dev/nuxtjs"
import { eventTrigger } from "@trigger.dev/sdk";
const QUOTES = [
"Any fool can write code that a computer can understand. Good programmers write code that humans can understand. - Martin Fowler",
"First, solve the problem. Then, write the code. - John Johnson",
"Experience is the name everyone gives to their mistakes. - Oscar Wilde",
"In order to be irreplaceable, one must always be different - Coco Chanel",
"Knowledge is power. - Francis Bacon",
"Sometimes it pays to stay in bed on Monday, rather than spending the rest of the week debugging Monday's code. - Dan Salomon",
"Perfection is achieved not when there is nothing more to add, but rather when there is nothing more to take away. - Antoine de Saint-Exupery",
"Rust is the most loved programming language. - Stack Overflow",
"Code is like humor. When you have to explain it, its bad. - Cory House",
"Fix the cause, not the symptom. - Steve Maguire",
];
client.defineJob({
id: "hello-world",
name: "Hello World",
version: "0.0.1",
trigger: eventTrigger({
name: "starter.hello-world",
}),
run: async (_payload, io, _ctx) => {
await io.logger.info("Hello world!");
return {
message: "Hello world!",
};
},
});
client.defineJob({
id: "quote",
name: "Random Quote",
version: "0.0.1",
trigger: eventTrigger({
name: "starter.quote",
}),
run: async (_payload, _io, _ctx) => {
return {
quote: QUOTES[Math.floor(Math.random() * QUOTES.length)],
};
},
});
//this route is used to send and receive data with Trigger.dev
const nuxt = createNuxtRoute(client);
export default defineEventHandler(nuxt)
+9
View File
@@ -0,0 +1,9 @@
import { TriggerClient } from "@trigger.dev/sdk";
export const client = new TriggerClient({
id: "nuxt-E9C7",
apiKey: process.env.TRIGGER_API_KEY,
apiUrl: process.env.TRIGGER_API_URL,
});
+4
View File
@@ -0,0 +1,4 @@
{
// https://nuxt.com/docs/guide/concepts/typescript
"extends": "./.nuxt/tsconfig.json"
}
+144 -21
View File
@@ -12,6 +12,7 @@ import { CLOUD_API_URL, CLOUD_TRIGGER_URL, COMMAND_NAME } from "../consts";
import { TelemetryClient, telemetryClient } from "../telemetry/telemetry";
import { addDependencies } from "../utils/addDependencies";
import { detectNextJsProject } from "../utils/detectNextJsProject";
import { detectNuxtJsProject } from "../utils/detectNuxtJsProject";
import { pathExists, readJSONFile } from "../utils/fileSystem";
import { logger } from "../utils/logger";
import { resolvePath } from "../utils/parseNameAndPath";
@@ -46,17 +47,20 @@ export const initCommand = async (options: InitCommandOptions) => {
// Detect if are are in a Next.js project
const isNextJsProject = await detectNextJsProject(resolvedPath);
const isNuxtJsProject = await detectNuxtJsProject(resolvedPath);
// Add checks for other frameworks here
if (!isNextJsProject) {
if (!isNextJsProject && !isNuxtJsProject) {
logger.error(
"We currently only support automatic setup for Next.js projects (we didn't detect one). View our manual installation guides for all frameworks: https://trigger.dev/docs/documentation/quickstarts/introduction"
"We currently only support automatic setup for Next.js and Nuxt.js projects (we didn't detect one). View our manual installation guides for all frameworks: https://trigger.dev/docs/documentation/quickstarts/introduction"
);
telemetryClient.init.failed("not_nextjs_project", options);
telemetryClient.init.failed("not_supported_project", options);
return;
} else {
} else if (isNextJsProject) {
logger.success("✅ Detected Next.js project");
} else if (isNuxtJsProject) {
logger.success("✅ Detected Nuxt.js project");
}
const hasGitChanges = await detectGitChanges(resolvedPath);
if (hasGitChanges) {
@@ -123,18 +127,32 @@ export const initCommand = async (options: InitCommandOptions) => {
const routeDir = pathModule.join(resolvedPath, usesSrcDir ? "src" : "");
if (nextJsDir === "pages") {
telemetryClient.init.createFiles(resolvedOptions, "pages");
await createTriggerPageRoute(
resolvedPath,
routeDir,
resolvedOptions,
isTypescriptProject,
usesSrcDir
);
} else {
telemetryClient.init.createFiles(resolvedOptions, "app");
await createTriggerAppRoute(
let framework = "";
if (isNextJsProject) {
framework = "Next.js";
if (nextJsDir === "pages") {
telemetryClient.init.createFiles(resolvedOptions, "pages");
await createTriggerPageRoute(
resolvedPath,
routeDir,
resolvedOptions,
isTypescriptProject,
usesSrcDir
);
} else {
telemetryClient.init.createFiles(resolvedOptions, "app");
await createTriggerAppRoute(
resolvedPath,
routeDir,
resolvedOptions,
isTypescriptProject,
usesSrcDir
);
}
} else if (isNuxtJsProject) {
framework = "Nuxt.js";
await createTriggerNuxtRoute(
resolvedPath,
routeDir,
resolvedOptions,
@@ -144,20 +162,23 @@ export const initCommand = async (options: InitCommandOptions) => {
}
await detectMiddlewareUsage(resolvedPath, usesSrcDir);
await addConfigurationToPackageJson(resolvedPath, resolvedOptions);
await printNextSteps(resolvedOptions, authorizedKey);
await printNextSteps(resolvedOptions, authorizedKey, framework);
telemetryClient.init.completed(resolvedOptions);
};
async function printNextSteps(options: ResolvedOptions, authorizedKey: WhoamiResponse) {
async function printNextSteps(
options: ResolvedOptions,
authorizedKey: WhoamiResponse,
framework: string
) {
const projectUrl = `${options.triggerUrl}/orgs/${authorizedKey.organization.slug}/projects/${authorizedKey.project.slug}`;
logger.success(`✅ Successfully initialized Trigger.dev!`);
logger.info("Next steps:");
logger.info(` 1. Run your Next.js project locally with 'npm run dev'`);
logger.info(` 1. Run your ${framework} project locally with 'npm run dev'`);
logger.info(
` 2. In a separate terminal, run 'npx @trigger.dev/cli@latest dev' to watch for changes and automatically register Trigger.dev jobs`
);
@@ -444,6 +465,108 @@ function getPathAlias(tsconfig: any, usesSrcDir: boolean) {
return;
}
async function createTriggerNuxtRoute(
projectPath: string,
path: string,
options: ResolvedOptions,
isTypescriptProject: boolean,
usesSrcDir = false
) {
const extension = isTypescriptProject ? ".ts" : ".js";
const triggerFileName = `trigger${extension}`;
const routeFileName = `trigger${extension}`;
const routeContent = `
import { client } from "@/trigger";
import { createNuxtRoute} from "@trigger.dev/nuxtjs"
import { eventTrigger } from "@trigger.dev/sdk";
const QUOTES = [
"Any fool can write code that a computer can understand. Good programmers write code that humans can understand. - Martin Fowler",
"First, solve the problem. Then, write the code. - John Johnson",
"Experience is the name everyone gives to their mistakes. - Oscar Wilde",
"In order to be irreplaceable, one must always be different - Coco Chanel",
"Knowledge is power. - Francis Bacon",
"Sometimes it pays to stay in bed on Monday, rather than spending the rest of the week debugging Monday's code. - Dan Salomon",
"Perfection is achieved not when there is nothing more to add, but rather when there is nothing more to take away. - Antoine de Saint-Exupery",
"Rust is the most loved programming language. - Stack Overflow",
"Code is like humor. When you have to explain it, its bad. - Cory House",
"Fix the cause, not the symptom. - Steve Maguire",
];
client.defineJob({
id: "hello-world",
name: "Hello World",
version: "0.0.1",
trigger: eventTrigger({
name: "starter.hello-world",
}),
run: async (_payload, io, _ctx) => {
await io.logger.info("Hello world!");
return {
message: "Hello world!",
};
},
});
client.defineJob({
id: "quote",
name: "Random Quote",
version: "0.0.1",
trigger: eventTrigger({
name: "starter.quote",
}),
run: async (_payload, _io, _ctx) => {
return {
quote: QUOTES[Math.floor(Math.random() * QUOTES.length)],
};
},
});
//this route is used to send and receive data with Trigger.dev
const nuxt = createNuxtRoute(client);
export default defineEventHandler(nuxt)
`;
const triggerContent = `
import { TriggerClient } from "@trigger.dev/sdk";
export const client = new TriggerClient({
id: "${options.endpointSlug}",
apiKey: process.env.TRIGGER_API_KEY,
apiUrl: process.env.TRIGGER_API_URL,
});
`;
const directories = pathModule.join(path, "server", "api");
await fs.mkdir(directories, { recursive: true });
const fileExists = await pathExists(pathModule.join(directories, routeFileName));
if (fileExists) {
logger.info("Skipping creation of server route because it already exists");
return;
}
await fs.writeFile(pathModule.join(directories, routeFileName), routeContent);
logger.success(
`✅ Created app route at ${usesSrcDir ? "src/" : ""}server/api/${removeFileExtension(
triggerFileName
)}/${routeFileName}`
);
const triggerFileExists = await pathExists(pathModule.join(path, triggerFileName));
if (!triggerFileExists) {
await fs.writeFile(pathModule.join(path, triggerFileName), triggerContent);
logger.success(`✅ Created trigger client at ${usesSrcDir ? "src/" : ""}${triggerFileName}`);
}
}
async function createTriggerAppRoute(
projectPath: string,
path: string,
@@ -0,0 +1,30 @@
import fs from "fs/promises";
import pathModule from "path";
import { readPackageJson } from "./readPackageJson";
/** Detects if the project is a Nuxt.js project at path */
export async function detectNuxtJsProject(path: string): Promise<boolean> {
const hasNuxtConfigFile = await detectNuxtConfigFile(path);
if (hasNuxtConfigFile) {
return true;
}
return await detectNuxtDependency(path);
}
async function detectNuxtConfigFile(path: string): Promise<boolean> {
return fs
.access(pathModule.join(path, "nuxt.config.ts"))
.then(() => true)
.catch(() => false);
}
async function detectNuxtDependency(path: string): Promise<boolean> {
const packageJsonContent = await readPackageJson(path);
if (!packageJsonContent) {
return false;
}
return packageJsonContent.dependencies?.nuxt !== undefined;
}
+2 -1
View File
@@ -6,7 +6,8 @@
"emitDecoratorMetadata": true,
"declaration": false,
"declarationMap": false,
"types": ["jest"]
"types": ["jest", "node"],
"lib": ["DOM", "ES2016"]
},
"exclude": ["node_modules"]
}
+6
View File
@@ -0,0 +1,6 @@
# @trigger.dev/nuxtjs
## 0.0.1
### Major Changes
- Initial Release
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Trigger.dev
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+9
View File
@@ -0,0 +1,9 @@
# Nuxt.js and Trigger.dev
Trigger.dev has full support for the Nuxt.js framework.
For information about the using Trigger.dev in your Nuxt.js app, check out these useful docs links:
- [Quick start guide for getting setup with Trigger.dev in a Nuxt.js project](https://trigger.dev/docs/documentation/quickstarts/nuxt)
- [Manually setup Nuxt.js with Trigger.dev](https://trigger.dev/docs/documentation/guides/manual/nuxt)
- [Using Trigger.dev with Nuxt.js, handling middleware and more](https://trigger.dev/docs/documentation/guides/platforms/nuxt)
+49
View File
@@ -0,0 +1,49 @@
{
"name": "@trigger.dev/nuxtjs",
"version": "0.0.1",
"description": "Trigger.dev Nuxt.js integration",
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"publishConfig": {
"access": "public"
},
"files": [
"dist"
],
"exports": {
".": {
"import": "./dist/index.js",
"require": "./dist/index.js"
},
"./package.json": "./package.json"
},
"devDependencies": {
"@trigger.dev/tsconfig": "workspace:*",
"@types/debug": "^4.1.7",
"@types/ws": "^8.5.3",
"nuxt": "^3.7.1",
"rimraf": "^3.0.2",
"tsup": "^6.5.0",
"tsx": "^3.12.1",
"typescript": "^4.8.4"
},
"scripts": {
"clean": "rimraf dist",
"build": "npm run clean && npm run build:tsup",
"build:tsup": "tsup",
"dev": "tsup --watch"
},
"peerDependencies": {
"@trigger.dev/sdk": "workspace:^2.1.0"
},
"dependencies": {
"@remix-run/web-fetch": "^4.3.5",
"debug": "^4.3.4",
"h3": "^1.8.1",
"nuxt3": "3.7.2-28233838.48fb6e24"
},
"engines": {
"node": ">=16.8.0"
}
}
+67
View File
@@ -0,0 +1,67 @@
import { TriggerClient } from "@trigger.dev/sdk";
import { Request as StandardRequest, Headers as StandardHeaders } from "@remix-run/web-fetch";
import type { EventHandlerRequest, H3Event, NodeIncomingMessage } from "h3";
function getRequestBody(req: NodeIncomingMessage): Promise<string> {
return new Promise((resolve, reject) => {
let body = '';
req.on('data', chunk => {
body += chunk.toString();
});
req.on('end', () => {
resolve(body);
});
req.on('error', (err) => {
reject(err);
});
});
}
export const createNuxtRoute = (client: TriggerClient) => {
return async (event: H3Event<EventHandlerRequest>) => {
if (event.node.req.method === "HEAD") {
event.node.res.statusCode = 200;
return;
}
try {
const request = await convertToStandardRequest(event.node.req);
const response = await client.handleRequest(request);
if (!response) {
event.node.res.statusCode = 404;
event.node.res.setHeader("Content-Type", "application/json");
event.node.res.end(JSON.stringify({ error: "Not found" }));
return;
}
event.node.res.statusCode = response.status;
event.node.res.setHeader("Content-Type", "application/json");
event.node.res.end(JSON.stringify(response.body));
} catch (error) {
event.node.res.statusCode = 500;
event.node.res.setHeader("Content-Type", "application/json");
event.node.res.end(JSON.stringify({ error: (error as Error).message }));
}
};
async function convertToStandardRequest(req: NodeIncomingMessage): Promise<StandardRequest> {
const { headers: nuxtHeaders, method } = req;
const headers = new StandardHeaders();
Object.entries(nuxtHeaders).forEach(([key, value]) => {
headers.set(key, value as string);
});
const body = await getRequestBody(req)
// Create a new Request object (hardcode the url because it doesn't really matter what it is)
return new StandardRequest("https://nuxt.js/api/trigger", {
headers,
method,
body: body,
// @ts-ignore
duplex: "half",
});
}
};
+16
View File
@@ -0,0 +1,16 @@
{
"extends": "@trigger.dev/tsconfig/node18.json",
"include": ["./src/**/*.ts", "tsup.config.ts"],
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"declaration": false,
"declarationMap": false,
"lib": ["DOM", "DOM.Iterable"],
"paths": {
"@trigger.dev/sdk": ["../trigger-sdk/src/index"],
"@trigger.dev/sdk/*": ["../trigger-sdk/src/*"]
}
},
"exclude": ["node_modules"]
}
+19
View File
@@ -0,0 +1,19 @@
import { defineConfig } from "tsup";
export default defineConfig([
{
name: "main",
entry: ["./src/index.ts"],
outDir: "./dist",
platform: "node",
format: ["cjs"],
legacyOutput: true,
sourcemap: true,
clean: true,
bundle: true,
splitting: false,
dts: true,
external: ["http", "https", "util", "events", "tty", "os", "timers"],
esbuildPlugins: [],
},
]);
+14525 -12436
View File
File diff suppressed because it is too large Load Diff