@farm.js/cli 0.1.0-beta.23 → 0.1.0-beta.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{add-integration-CdVfiPjG.mjs → add-integration-7hf9WI7e.mjs} +147 -140
- package/dist/add-integration-7hf9WI7e.mjs.map +1 -0
- package/dist/{add-integration-Xc0p-k-m.js → add-integration-D5mff3xX.js} +147 -140
- package/dist/add-integration-D5mff3xX.js.map +1 -0
- package/dist/add-integration.js +1 -1
- package/dist/add-integration.mjs +1 -1
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +2 -2
- package/dist/add-integration-CdVfiPjG.mjs.map +0 -1
- package/dist/add-integration-Xc0p-k-m.js.map +0 -1
|
@@ -123,7 +123,7 @@ function aiChatUIFeature() {
|
|
|
123
123
|
],
|
|
124
124
|
needsApiClient: false,
|
|
125
125
|
notes: ["Open \"/integrations/ai\" to try the generated chat UI."],
|
|
126
|
-
files: () => [componentFile("ai-chat.tsx", aiChatTemplate()), integrationPageFile("ai", "AIChat")]
|
|
126
|
+
files: () => [componentFile("ai-chat.tsx", aiChatTemplate()), integrationPageFile("ai", "AIChat", "ai-chat")]
|
|
127
127
|
};
|
|
128
128
|
}
|
|
129
129
|
function supabaseAuthUIFeature() {
|
|
@@ -155,35 +155,25 @@ function workosAuthUIFeature() {
|
|
|
155
155
|
key: input.key,
|
|
156
156
|
provider: "WorkOS",
|
|
157
157
|
componentName: "WorkOSAuthPanel",
|
|
158
|
-
statusCall: "session
|
|
159
|
-
|
|
158
|
+
statusCall: "session",
|
|
159
|
+
statusMethod: "get",
|
|
160
|
+
logoutCall: "logout",
|
|
161
|
+
logoutMethod: "post",
|
|
160
162
|
loginHref: "/login?returnTo=/dashboard",
|
|
161
163
|
signupHref: "/signup?returnTo=/dashboard",
|
|
162
164
|
statusLabel: "Session"
|
|
163
|
-
})), integrationPageFile("workos", "WorkOSAuthPanel")]
|
|
165
|
+
})), integrationPageFile("workos", "WorkOSAuthPanel", "workos-auth-panel")]
|
|
164
166
|
};
|
|
165
167
|
}
|
|
166
168
|
function auth0AuthUIFeature() {
|
|
167
|
-
return {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
notes: ["Open \"/integrations/auth0\" to try the generated auth UI."],
|
|
176
|
-
files: (input) => [componentFile("auth0-auth-panel.tsx", hostedAuthTemplate({
|
|
177
|
-
key: input.key,
|
|
178
|
-
provider: "Auth0",
|
|
179
|
-
componentName: "Auth0AuthPanel",
|
|
180
|
-
statusCall: "profile.get",
|
|
181
|
-
logoutCall: "logout.get",
|
|
182
|
-
loginHref: "/auth/login?returnTo=/dashboard",
|
|
183
|
-
signupHref: "/auth/signup?returnTo=/dashboard",
|
|
184
|
-
statusLabel: "Profile"
|
|
185
|
-
})), integrationPageFile("auth0", "Auth0AuthPanel")]
|
|
186
|
-
};
|
|
169
|
+
return authRouteShellUIFeature({
|
|
170
|
+
provider: "auth0",
|
|
171
|
+
label: "Auth0",
|
|
172
|
+
componentName: "Auth0AuthPanel",
|
|
173
|
+
signInHref: "/auth/login?returnTo=/dashboard",
|
|
174
|
+
signUpHref: "/auth/signup?returnTo=/dashboard",
|
|
175
|
+
sessionHref: "/auth/profile"
|
|
176
|
+
});
|
|
187
177
|
}
|
|
188
178
|
function clerkAuthUIFeature() {
|
|
189
179
|
return authRouteShellUIFeature({
|
|
@@ -262,16 +252,18 @@ function jobsUIFeature(provider) {
|
|
|
262
252
|
function unkeyApiKeysUIFeature() {
|
|
263
253
|
return {
|
|
264
254
|
name: "unkey-api-keys",
|
|
265
|
-
description: "Unkey
|
|
266
|
-
components: [
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
"
|
|
271
|
-
"
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
255
|
+
description: "Unkey protected route UI",
|
|
256
|
+
components: ["badge", "card"],
|
|
257
|
+
needsApiClient: false,
|
|
258
|
+
notes: ["Open \"/integrations/unkey\" to test the generated protected API route."],
|
|
259
|
+
files: () => [
|
|
260
|
+
componentFile("unkey-api-keys-console.tsx", unkeyApiKeysTemplate()),
|
|
261
|
+
integrationPageFile("unkey", "UnkeyApiKeysConsole"),
|
|
262
|
+
{
|
|
263
|
+
path: node_path.default.join("src", "app", "api", "protected", "route.ts"),
|
|
264
|
+
source: unkeyProtectedRouteTemplate()
|
|
265
|
+
}
|
|
266
|
+
]
|
|
275
267
|
};
|
|
276
268
|
}
|
|
277
269
|
function billingUIFeature(input) {
|
|
@@ -301,6 +293,7 @@ function authRouteShellUIFeature(input) {
|
|
|
301
293
|
"button",
|
|
302
294
|
"card"
|
|
303
295
|
],
|
|
296
|
+
needsApiClient: false,
|
|
304
297
|
notes: [`Open "/integrations/${input.provider}" to try the generated auth UI.`],
|
|
305
298
|
files: () => [componentFile(`${input.provider}-auth-panel.tsx`, authRouteShellTemplate({
|
|
306
299
|
provider: input.label,
|
|
@@ -308,7 +301,7 @@ function authRouteShellUIFeature(input) {
|
|
|
308
301
|
signInHref: input.signInHref,
|
|
309
302
|
signUpHref: input.signUpHref,
|
|
310
303
|
sessionHref: input.sessionHref
|
|
311
|
-
})), integrationPageFile(input.provider, input.componentName)]
|
|
304
|
+
})), integrationPageFile(input.provider, input.componentName, input.provider === "authjs" ? "authjs-auth-panel" : void 0)]
|
|
312
305
|
};
|
|
313
306
|
}
|
|
314
307
|
function componentFile(fileName, source) {
|
|
@@ -317,11 +310,10 @@ function componentFile(fileName, source) {
|
|
|
317
310
|
source
|
|
318
311
|
};
|
|
319
312
|
}
|
|
320
|
-
function integrationPageFile(provider, componentName) {
|
|
321
|
-
const fileName = kebabCase(componentName);
|
|
313
|
+
function integrationPageFile(provider, componentName, sourceFileName = kebabCase(componentName)) {
|
|
322
314
|
return {
|
|
323
315
|
path: node_path.default.join("src", "app", "integrations", provider, "page.tsx"),
|
|
324
|
-
source: `import { ${componentName} } from "@/components/farm/${
|
|
316
|
+
source: `import { ${componentName} } from "@/components/farm/${sourceFileName}";
|
|
325
317
|
|
|
326
318
|
export default function ${componentName}Page() {
|
|
327
319
|
return <${componentName} />;
|
|
@@ -478,7 +470,7 @@ const UI_DEPENDENCIES = {
|
|
|
478
470
|
"tailwind-merge": "^3.3.1",
|
|
479
471
|
tailwindcss: "^4.1.18"
|
|
480
472
|
};
|
|
481
|
-
const SHADCN_THEME_CSS = `@custom-variant dark (&:
|
|
473
|
+
const SHADCN_THEME_CSS = `@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));
|
|
482
474
|
|
|
483
475
|
@theme inline {
|
|
484
476
|
--color-background: var(--background);
|
|
@@ -504,7 +496,8 @@ const SHADCN_THEME_CSS = `@custom-variant dark (&:is(.dark *));
|
|
|
504
496
|
--radius-lg: var(--radius);
|
|
505
497
|
}
|
|
506
498
|
|
|
507
|
-
:root
|
|
499
|
+
:root,
|
|
500
|
+
[data-theme="light"] {
|
|
508
501
|
--radius: 0.5rem;
|
|
509
502
|
--background: oklch(1 0 0);
|
|
510
503
|
--foreground: oklch(0.145 0 0);
|
|
@@ -526,7 +519,7 @@ const SHADCN_THEME_CSS = `@custom-variant dark (&:is(.dark *));
|
|
|
526
519
|
--ring: oklch(0.708 0 0);
|
|
527
520
|
}
|
|
528
521
|
|
|
529
|
-
|
|
522
|
+
[data-theme="dark"] {
|
|
530
523
|
--background: oklch(0.145 0 0);
|
|
531
524
|
--foreground: oklch(0.985 0 0);
|
|
532
525
|
--card: oklch(0.205 0 0);
|
|
@@ -1129,12 +1122,17 @@ export function SupabaseAuthPanel() {
|
|
|
1129
1122
|
}
|
|
1130
1123
|
|
|
1131
1124
|
async function logout() {
|
|
1132
|
-
const response = await
|
|
1133
|
-
|
|
1134
|
-
|
|
1125
|
+
const response = await fetch("/auth/logout", {
|
|
1126
|
+
method: "POST",
|
|
1127
|
+
headers: { "content-type": "application/json" },
|
|
1128
|
+
body: JSON.stringify({ returnTo: "/" }),
|
|
1129
|
+
});
|
|
1130
|
+
const data = (await response.json()) as { redirectTo?: string; error?: string };
|
|
1131
|
+
if (data.redirectTo) {
|
|
1132
|
+
window.location.assign(data.redirectTo);
|
|
1135
1133
|
return;
|
|
1136
1134
|
}
|
|
1137
|
-
setStatus(
|
|
1135
|
+
setStatus(data.error ?? "Signed out");
|
|
1138
1136
|
}
|
|
1139
1137
|
|
|
1140
1138
|
return (
|
|
@@ -1193,7 +1191,7 @@ export function ${input.componentName}() {
|
|
|
1193
1191
|
|
|
1194
1192
|
async function refreshStatus() {
|
|
1195
1193
|
setPending(true);
|
|
1196
|
-
const response = await apiClient.${input.key}.${input.statusCall}();
|
|
1194
|
+
const response = await apiClient.${input.key}.${input.statusCall}.${input.statusMethod}();
|
|
1197
1195
|
if (response.error) {
|
|
1198
1196
|
setStatus(response.error.message);
|
|
1199
1197
|
} else {
|
|
@@ -1204,7 +1202,7 @@ export function ${input.componentName}() {
|
|
|
1204
1202
|
|
|
1205
1203
|
async function logout() {
|
|
1206
1204
|
setPending(true);
|
|
1207
|
-
const response = await apiClient.${input.key}.${input.logoutCall}();
|
|
1205
|
+
const response = await apiClient.${input.key}.${input.logoutCall}.${input.logoutMethod}();
|
|
1208
1206
|
if (response.data?.redirectTo) {
|
|
1209
1207
|
window.location.assign(response.data.redirectTo);
|
|
1210
1208
|
return;
|
|
@@ -1467,17 +1465,20 @@ import { apiClient } from "@/lib/api";
|
|
|
1467
1465
|
export function ResendEmailConsole() {
|
|
1468
1466
|
const [to, setTo] = React.useState("");
|
|
1469
1467
|
const [name, setName] = React.useState("Ada");
|
|
1470
|
-
const
|
|
1468
|
+
const templateId = "welcome" as const;
|
|
1471
1469
|
const [status, setStatus] = React.useState("Idle");
|
|
1472
1470
|
const [previewHtml, setPreviewHtml] = React.useState("");
|
|
1473
1471
|
|
|
1474
1472
|
async function loadTemplates() {
|
|
1475
|
-
const response = await apiClient.${key}.templates
|
|
1476
|
-
|
|
1473
|
+
const response = await apiClient.${key}.templates();
|
|
1474
|
+
const templates = Array.isArray(response.data)
|
|
1475
|
+
? (response.data as Array<{ id: string }>)
|
|
1476
|
+
: [];
|
|
1477
|
+
setStatus(response.error ? response.error.message : "Templates: " + templates.map((item) => item.id).join(", "));
|
|
1477
1478
|
}
|
|
1478
1479
|
|
|
1479
1480
|
async function preview() {
|
|
1480
|
-
const response = await apiClient.${key}.preview
|
|
1481
|
+
const response = await apiClient.${key}.preview({
|
|
1481
1482
|
body: {
|
|
1482
1483
|
templateId,
|
|
1483
1484
|
data: { name },
|
|
@@ -1492,7 +1493,7 @@ export function ResendEmailConsole() {
|
|
|
1492
1493
|
}
|
|
1493
1494
|
|
|
1494
1495
|
async function send() {
|
|
1495
|
-
const response = await apiClient.${key}.send
|
|
1496
|
+
const response = await apiClient.${key}.send({
|
|
1496
1497
|
body: {
|
|
1497
1498
|
templateId,
|
|
1498
1499
|
to,
|
|
@@ -1515,11 +1516,7 @@ export function ResendEmailConsole() {
|
|
|
1515
1516
|
<CardDescription>Template previews and delivery controls.</CardDescription>
|
|
1516
1517
|
</CardHeader>
|
|
1517
1518
|
<CardContent className="space-y-4">
|
|
1518
|
-
<div className="grid gap-4 sm:grid-cols-
|
|
1519
|
-
<div className="space-y-2">
|
|
1520
|
-
<Label htmlFor="templateId">Template</Label>
|
|
1521
|
-
<Input id="templateId" value={templateId} onChange={(event) => setTemplateId(event.target.value)} />
|
|
1522
|
-
</div>
|
|
1519
|
+
<div className="grid gap-4 sm:grid-cols-2">
|
|
1523
1520
|
<div className="space-y-2">
|
|
1524
1521
|
<Label htmlFor="to">To</Label>
|
|
1525
1522
|
<Input id="to" value={to} onChange={(event) => setTo(event.target.value)} />
|
|
@@ -1644,47 +1641,11 @@ export function ${`${pascalCase(provider)}JobsConsole`}() {
|
|
|
1644
1641
|
}
|
|
1645
1642
|
`;
|
|
1646
1643
|
}
|
|
1647
|
-
function unkeyApiKeysTemplate(
|
|
1648
|
-
return `
|
|
1649
|
-
|
|
1650
|
-
import * as React from "react";
|
|
1651
|
-
import { Badge } from "@/components/ui/badge";
|
|
1652
|
-
import { Button } from "@/components/ui/button";
|
|
1644
|
+
function unkeyApiKeysTemplate() {
|
|
1645
|
+
return `import { Badge } from "@/components/ui/badge";
|
|
1653
1646
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
|
1654
|
-
import { Input } from "@/components/ui/input";
|
|
1655
|
-
import { Label } from "@/components/ui/label";
|
|
1656
|
-
import { apiClient } from "@/lib/api";
|
|
1657
1647
|
|
|
1658
1648
|
export function UnkeyApiKeysConsole() {
|
|
1659
|
-
const [name, setName] = React.useState("Development key");
|
|
1660
|
-
const [prefix, setPrefix] = React.useState("farm");
|
|
1661
|
-
const [apiKey, setApiKey] = React.useState("");
|
|
1662
|
-
const [status, setStatus] = React.useState("Idle");
|
|
1663
|
-
|
|
1664
|
-
async function createKey() {
|
|
1665
|
-
const response = await apiClient.${key}.createKey.post({
|
|
1666
|
-
body: {
|
|
1667
|
-
name,
|
|
1668
|
-
prefix,
|
|
1669
|
-
},
|
|
1670
|
-
});
|
|
1671
|
-
if (response.error) {
|
|
1672
|
-
setStatus(response.error.message);
|
|
1673
|
-
return;
|
|
1674
|
-
}
|
|
1675
|
-
setApiKey(response.data?.key ?? "");
|
|
1676
|
-
setStatus("Created " + (response.data?.keyId ?? "key"));
|
|
1677
|
-
}
|
|
1678
|
-
|
|
1679
|
-
async function verifyKey() {
|
|
1680
|
-
const response = await apiClient.${key}.verifyKey.post({
|
|
1681
|
-
body: {
|
|
1682
|
-
key: apiKey,
|
|
1683
|
-
},
|
|
1684
|
-
});
|
|
1685
|
-
setStatus(response.error ? response.error.message : response.data?.valid ? "Valid key" : "Invalid key");
|
|
1686
|
-
}
|
|
1687
|
-
|
|
1688
1649
|
return (
|
|
1689
1650
|
<main className="min-h-screen bg-background px-6 py-12 text-foreground">
|
|
1690
1651
|
<section className="mx-auto flex w-full max-w-3xl flex-col gap-6">
|
|
@@ -1694,29 +1655,16 @@ export function UnkeyApiKeysConsole() {
|
|
|
1694
1655
|
</div>
|
|
1695
1656
|
<Card>
|
|
1696
1657
|
<CardHeader>
|
|
1697
|
-
<CardTitle className="text-xl">
|
|
1698
|
-
<CardDescription>
|
|
1658
|
+
<CardTitle className="text-xl">Protected API</CardTitle>
|
|
1659
|
+
<CardDescription>Requests are verified by Unkey before the route runs.</CardDescription>
|
|
1699
1660
|
</CardHeader>
|
|
1700
|
-
<CardContent className="space-y-
|
|
1701
|
-
<
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
<Label htmlFor="prefix">Prefix</Label>
|
|
1708
|
-
<Input id="prefix" value={prefix} onChange={(event) => setPrefix(event.target.value)} />
|
|
1709
|
-
</div>
|
|
1710
|
-
</div>
|
|
1711
|
-
<div className="space-y-2">
|
|
1712
|
-
<Label htmlFor="apiKey">API key</Label>
|
|
1713
|
-
<Input id="apiKey" value={apiKey} onChange={(event) => setApiKey(event.target.value)} />
|
|
1714
|
-
</div>
|
|
1715
|
-
<p className="rounded-md border bg-muted/30 px-3 py-2 text-sm">{status}</p>
|
|
1716
|
-
<div className="flex flex-wrap gap-2">
|
|
1717
|
-
<Button type="button" onClick={() => void createKey()}>Create key</Button>
|
|
1718
|
-
<Button type="button" variant="outline" onClick={() => void verifyKey()}>Verify</Button>
|
|
1719
|
-
</div>
|
|
1661
|
+
<CardContent className="space-y-3">
|
|
1662
|
+
<code className="block overflow-x-auto rounded-md border bg-muted/30 p-3 text-xs">
|
|
1663
|
+
curl http://localhost:3000/api/protected -H "Authorization: Bearer YOUR_KEY"
|
|
1664
|
+
</code>
|
|
1665
|
+
<p className="text-sm text-muted-foreground">
|
|
1666
|
+
Create and rotate keys from trusted server code or the Unkey dashboard.
|
|
1667
|
+
</p>
|
|
1720
1668
|
</CardContent>
|
|
1721
1669
|
</Card>
|
|
1722
1670
|
</section>
|
|
@@ -1725,6 +1673,15 @@ export function UnkeyApiKeysConsole() {
|
|
|
1725
1673
|
}
|
|
1726
1674
|
`;
|
|
1727
1675
|
}
|
|
1676
|
+
function unkeyProtectedRouteTemplate() {
|
|
1677
|
+
return `export function GET() {
|
|
1678
|
+
return Response.json({
|
|
1679
|
+
ok: true,
|
|
1680
|
+
message: "Valid Unkey API key.",
|
|
1681
|
+
});
|
|
1682
|
+
}
|
|
1683
|
+
`;
|
|
1684
|
+
}
|
|
1728
1685
|
function pascalCase(input) {
|
|
1729
1686
|
return input.split(/[^A-Za-z0-9]+/g).filter(Boolean).map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`).join("");
|
|
1730
1687
|
}
|
|
@@ -1752,6 +1709,7 @@ const PROVIDERS = [
|
|
|
1752
1709
|
"chat"
|
|
1753
1710
|
],
|
|
1754
1711
|
defaultKey: "chat",
|
|
1712
|
+
packageName: "@farm.js/ai",
|
|
1755
1713
|
fileName: "chat",
|
|
1756
1714
|
exportName: "POST",
|
|
1757
1715
|
description: "Vercel AI SDK chat route",
|
|
@@ -1762,7 +1720,7 @@ const PROVIDERS = [
|
|
|
1762
1720
|
"No farm.config integration wiring is required for this route."
|
|
1763
1721
|
],
|
|
1764
1722
|
ui: aiChatUIFeature(),
|
|
1765
|
-
template: () => `import { aiChatRoute } from "@farm.js/
|
|
1723
|
+
template: () => `import { aiChatRoute } from "@farm.js/ai";
|
|
1766
1724
|
|
|
1767
1725
|
export const POST = aiChatRoute({
|
|
1768
1726
|
model: "openai/gpt-4o-mini",
|
|
@@ -1778,17 +1736,19 @@ export const POST = aiChatRoute({
|
|
|
1778
1736
|
"stripe-billing"
|
|
1779
1737
|
],
|
|
1780
1738
|
defaultKey: "billing",
|
|
1739
|
+
packageName: "@farm.js/stripe",
|
|
1781
1740
|
fileName: "stripe",
|
|
1782
1741
|
exportName: "stripeIntegration",
|
|
1783
1742
|
description: "Stripe billing and checkout routes",
|
|
1784
1743
|
env: ["STRIPE_SECRET_KEY", "STRIPE_WEBHOOK_SECRET"],
|
|
1785
|
-
template: () => `import {
|
|
1744
|
+
template: () => `import type { FarmIntegrationLogEvent } from "@farm.js/core";
|
|
1745
|
+
import { stripe } from "@farm.js/stripe";
|
|
1786
1746
|
|
|
1787
1747
|
export const stripeIntegration = stripe({
|
|
1788
1748
|
secretKey: process.env.STRIPE_SECRET_KEY,
|
|
1789
1749
|
webhookSecret: process.env.STRIPE_WEBHOOK_SECRET,
|
|
1790
1750
|
products: [],
|
|
1791
|
-
log(event) {
|
|
1751
|
+
log(event: FarmIntegrationLogEvent) {
|
|
1792
1752
|
console.log("[stripe]", event.phase, event.route?.path || "none");
|
|
1793
1753
|
},
|
|
1794
1754
|
});
|
|
@@ -1799,6 +1759,7 @@ export const stripeIntegration = stripe({
|
|
|
1799
1759
|
provider: "supabase",
|
|
1800
1760
|
aliases: ["auth-supabase", "supabase-auth"],
|
|
1801
1761
|
defaultKey: "auth",
|
|
1762
|
+
packageName: "@farm.js/supabase",
|
|
1802
1763
|
fileName: "supabase",
|
|
1803
1764
|
exportName: "supabaseIntegration",
|
|
1804
1765
|
description: "Supabase auth routes and middleware",
|
|
@@ -1808,7 +1769,7 @@ export const stripeIntegration = stripe({
|
|
|
1808
1769
|
"APP_BASE_URL"
|
|
1809
1770
|
],
|
|
1810
1771
|
ui: supabaseAuthUIFeature(),
|
|
1811
|
-
template: () => `import { supabase } from "@farm.js/
|
|
1772
|
+
template: () => `import { supabase } from "@farm.js/supabase";
|
|
1812
1773
|
|
|
1813
1774
|
export const supabaseIntegration = supabase({
|
|
1814
1775
|
callbackUrl: \`\${process.env.APP_BASE_URL || "http://localhost:3000"}/auth/callback\`,
|
|
@@ -1827,6 +1788,7 @@ export const supabaseIntegration = supabase({
|
|
|
1827
1788
|
provider: "workos",
|
|
1828
1789
|
aliases: ["auth-workos", "workos-auth"],
|
|
1829
1790
|
defaultKey: "auth",
|
|
1791
|
+
packageName: "@farm.js/workos",
|
|
1830
1792
|
fileName: "workos",
|
|
1831
1793
|
exportName: "workosIntegration",
|
|
1832
1794
|
description: "WorkOS auth routes and protected route middleware",
|
|
@@ -1836,7 +1798,7 @@ export const supabaseIntegration = supabase({
|
|
|
1836
1798
|
"WORKOS_COOKIE_PASSWORD"
|
|
1837
1799
|
],
|
|
1838
1800
|
ui: workosAuthUIFeature(),
|
|
1839
|
-
template: () => `import { workos } from "@farm.js/
|
|
1801
|
+
template: () => `import { workos } from "@farm.js/workos";
|
|
1840
1802
|
|
|
1841
1803
|
export const workosIntegration = workos({
|
|
1842
1804
|
protectedRoutes: ["/dashboard(.*)"],
|
|
@@ -1850,6 +1812,7 @@ export const workosIntegration = workos({
|
|
|
1850
1812
|
provider: "auth0",
|
|
1851
1813
|
aliases: ["auth-auth0", "auth0-auth"],
|
|
1852
1814
|
defaultKey: "auth",
|
|
1815
|
+
packageName: "@farm.js/auth0",
|
|
1853
1816
|
fileName: "auth0",
|
|
1854
1817
|
exportName: "auth0Integration",
|
|
1855
1818
|
description: "Auth0 login, callback, logout, and profile routes",
|
|
@@ -1860,7 +1823,7 @@ export const workosIntegration = workos({
|
|
|
1860
1823
|
"AUTH0_SECRET"
|
|
1861
1824
|
],
|
|
1862
1825
|
ui: auth0AuthUIFeature(),
|
|
1863
|
-
template: () => `import { auth0 } from "@farm.js/
|
|
1826
|
+
template: () => `import { auth0 } from "@farm.js/auth0";
|
|
1864
1827
|
|
|
1865
1828
|
export const auth0Integration = auth0({
|
|
1866
1829
|
callbackUrl: \`\${process.env.APP_BASE_URL || "http://localhost:3000"}/auth/callback\`,
|
|
@@ -1875,12 +1838,14 @@ export const auth0Integration = auth0({
|
|
|
1875
1838
|
provider: "clerk",
|
|
1876
1839
|
aliases: ["auth-clerk", "clerk-auth"],
|
|
1877
1840
|
defaultKey: "auth",
|
|
1841
|
+
packageName: "@farm.js/clerk",
|
|
1878
1842
|
fileName: "clerk",
|
|
1879
1843
|
exportName: "clerkIntegration",
|
|
1880
1844
|
description: "Clerk auth provider and protected route middleware",
|
|
1881
1845
|
env: ["NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY", "CLERK_SECRET_KEY"],
|
|
1846
|
+
dependencies: { "@clerk/react": "^6.1.0" },
|
|
1882
1847
|
ui: clerkAuthUIFeature(),
|
|
1883
|
-
template: () => `import { clerk } from "@farm.js/
|
|
1848
|
+
template: () => `import { clerk } from "@farm.js/clerk";
|
|
1884
1849
|
|
|
1885
1850
|
export const clerkIntegration = clerk({
|
|
1886
1851
|
signInUrl: "/sign-in",
|
|
@@ -1896,6 +1861,7 @@ export const clerkIntegration = clerk({
|
|
|
1896
1861
|
provider: "resend",
|
|
1897
1862
|
aliases: ["email", "resend-email"],
|
|
1898
1863
|
defaultKey: "email",
|
|
1864
|
+
packageName: "@farm.js/email",
|
|
1899
1865
|
fileName: "resend",
|
|
1900
1866
|
exportName: "resendIntegration",
|
|
1901
1867
|
description: "Resend email send, preview, schedule, and webhook routes",
|
|
@@ -1906,7 +1872,7 @@ export const clerkIntegration = clerk({
|
|
|
1906
1872
|
],
|
|
1907
1873
|
ui: resendEmailUIFeature(),
|
|
1908
1874
|
template: () => `import { createElement } from "react";
|
|
1909
|
-
import { resend, template } from "@farm.js/
|
|
1875
|
+
import { resend, template } from "@farm.js/email";
|
|
1910
1876
|
|
|
1911
1877
|
function WelcomeEmail(props: { name: string }) {
|
|
1912
1878
|
return createElement("div", null, \`Welcome \${props.name}\`);
|
|
@@ -1945,6 +1911,7 @@ export const resendIntegration = resend({
|
|
|
1945
1911
|
provider: "jobs-inngest",
|
|
1946
1912
|
aliases: ["inngest", "jobs"],
|
|
1947
1913
|
defaultKey: "jobs",
|
|
1914
|
+
packageName: "@farm.js/jobs",
|
|
1948
1915
|
fileName: "jobs-inngest",
|
|
1949
1916
|
exportName: "jobsIntegration",
|
|
1950
1917
|
description: "Jobs integration backed by Inngest",
|
|
@@ -1955,7 +1922,7 @@ export const resendIntegration = resend({
|
|
|
1955
1922
|
],
|
|
1956
1923
|
notes: ["Add tasks to jobTasks before using the generated jobs API."],
|
|
1957
1924
|
ui: jobsUIFeature("inngest"),
|
|
1958
|
-
template: () => `import { defineTasks, inngest, jobs } from "@farm.js/
|
|
1925
|
+
template: () => `import { defineTasks, inngest, jobs } from "@farm.js/jobs";
|
|
1959
1926
|
|
|
1960
1927
|
export const jobTasks = defineTasks({});
|
|
1961
1928
|
|
|
@@ -1980,6 +1947,7 @@ export const jobsIntegration = jobs({
|
|
|
1980
1947
|
"jobs-triggerdev"
|
|
1981
1948
|
],
|
|
1982
1949
|
defaultKey: "jobs",
|
|
1950
|
+
packageName: "@farm.js/jobs",
|
|
1983
1951
|
fileName: "jobs-trigger",
|
|
1984
1952
|
exportName: "jobsIntegration",
|
|
1985
1953
|
description: "Jobs integration backed by Trigger.dev",
|
|
@@ -1990,7 +1958,7 @@ export const jobsIntegration = jobs({
|
|
|
1990
1958
|
],
|
|
1991
1959
|
notes: ["Add tasks to jobTasks before using the generated jobs API."],
|
|
1992
1960
|
ui: jobsUIFeature("trigger"),
|
|
1993
|
-
template: () => `import { defineTasks, jobs, trigger } from "@farm.js/
|
|
1961
|
+
template: () => `import { defineTasks, jobs, trigger } from "@farm.js/jobs";
|
|
1994
1962
|
|
|
1995
1963
|
export const jobTasks = defineTasks({});
|
|
1996
1964
|
|
|
@@ -2011,6 +1979,7 @@ export const jobsIntegration = jobs({
|
|
|
2011
1979
|
provider: "polar",
|
|
2012
1980
|
aliases: ["polar-billing", "billing-polar"],
|
|
2013
1981
|
defaultKey: "billing",
|
|
1982
|
+
packageName: "@farm.js/polar",
|
|
2014
1983
|
fileName: "polar",
|
|
2015
1984
|
exportName: "polarIntegration",
|
|
2016
1985
|
description: "Polar billing and checkout routes",
|
|
@@ -2022,9 +1991,9 @@ export const jobsIntegration = jobs({
|
|
|
2022
1991
|
notes: ["Replace resolveBillingOwner with your app user or organization lookup."],
|
|
2023
1992
|
ui: polarBillingUIFeature(),
|
|
2024
1993
|
template: () => `import type { FarmIntegrationHandlerContext } from "@farm.js/core";
|
|
2025
|
-
import { polar } from "@farm.js/
|
|
1994
|
+
import { polar } from "@farm.js/polar";
|
|
2026
1995
|
|
|
2027
|
-
|
|
1996
|
+
function resolveBillingOwner(_context: FarmIntegrationHandlerContext): never {
|
|
2028
1997
|
throw new Error("Configure Polar billing owner resolution for your app.");
|
|
2029
1998
|
}
|
|
2030
1999
|
|
|
@@ -2052,6 +2021,7 @@ export const polarIntegration = polar({
|
|
|
2052
2021
|
provider: "autumn",
|
|
2053
2022
|
aliases: ["autumn-billing", "billing-autumn"],
|
|
2054
2023
|
defaultKey: "billing",
|
|
2024
|
+
packageName: "@farm.js/autumn",
|
|
2055
2025
|
fileName: "autumn",
|
|
2056
2026
|
exportName: "autumnIntegration",
|
|
2057
2027
|
description: "Autumn billing and checkout routes",
|
|
@@ -2063,9 +2033,9 @@ export const polarIntegration = polar({
|
|
|
2063
2033
|
notes: ["Replace resolveBillingOwner with your app user or organization lookup."],
|
|
2064
2034
|
ui: autumnBillingUIFeature(),
|
|
2065
2035
|
template: () => `import type { FarmIntegrationHandlerContext } from "@farm.js/core";
|
|
2066
|
-
import { autumn } from "@farm.js/
|
|
2036
|
+
import { autumn } from "@farm.js/autumn";
|
|
2067
2037
|
|
|
2068
|
-
|
|
2038
|
+
function resolveBillingOwner(_context: FarmIntegrationHandlerContext): never {
|
|
2069
2039
|
throw new Error("Configure Autumn billing owner resolution for your app.");
|
|
2070
2040
|
}
|
|
2071
2041
|
|
|
@@ -2092,6 +2062,7 @@ export const autumnIntegration = autumn({
|
|
|
2092
2062
|
provider: "better-auth",
|
|
2093
2063
|
aliases: ["betterauth", "auth-better-auth"],
|
|
2094
2064
|
defaultKey: "auth",
|
|
2065
|
+
packageName: "@farm.js/better-auth",
|
|
2095
2066
|
fileName: "better-auth",
|
|
2096
2067
|
exportName: "betterAuthIntegration",
|
|
2097
2068
|
description: "Better Auth route adapter",
|
|
@@ -2146,7 +2117,7 @@ better-auth.sqlite-wal
|
|
|
2146
2117
|
}
|
|
2147
2118
|
],
|
|
2148
2119
|
ui: betterAuthUIFeature(),
|
|
2149
|
-
template: () => `import { betterAuth } from "@farm.js/
|
|
2120
|
+
template: () => `import { betterAuth } from "@farm.js/better-auth";
|
|
2150
2121
|
import { auth } from "../auth.ts";
|
|
2151
2122
|
|
|
2152
2123
|
export const betterAuthIntegration = betterAuth({
|
|
@@ -2165,13 +2136,45 @@ export const betterAuthIntegration = betterAuth({
|
|
|
2165
2136
|
"next-auth"
|
|
2166
2137
|
],
|
|
2167
2138
|
defaultKey: "auth",
|
|
2139
|
+
packageName: "@farm.js/authjs",
|
|
2168
2140
|
fileName: "authjs",
|
|
2169
2141
|
exportName: "authjsIntegration",
|
|
2170
2142
|
description: "Auth.js route adapter",
|
|
2171
|
-
env: [
|
|
2172
|
-
|
|
2143
|
+
env: [
|
|
2144
|
+
"AUTH_SECRET",
|
|
2145
|
+
"AUTH_GITHUB_ID",
|
|
2146
|
+
"AUTH_GITHUB_SECRET"
|
|
2147
|
+
],
|
|
2148
|
+
dependencies: { "@auth/core": "0.34.3" },
|
|
2149
|
+
setupFiles: [{
|
|
2150
|
+
path: "src/lib/auth.ts",
|
|
2151
|
+
source: () => `import { Auth } from "@auth/core";
|
|
2152
|
+
import GitHub from "@auth/core/providers/github";
|
|
2153
|
+
|
|
2154
|
+
const config = {
|
|
2155
|
+
providers: [
|
|
2156
|
+
GitHub({
|
|
2157
|
+
clientId: process.env.AUTH_GITHUB_ID!,
|
|
2158
|
+
clientSecret: process.env.AUTH_GITHUB_SECRET!,
|
|
2159
|
+
}),
|
|
2160
|
+
],
|
|
2161
|
+
secret: process.env.AUTH_SECRET,
|
|
2162
|
+
trustHost: true,
|
|
2163
|
+
};
|
|
2164
|
+
|
|
2165
|
+
const handler = (request: Request) => Auth(request, config);
|
|
2166
|
+
|
|
2167
|
+
export const auth = {
|
|
2168
|
+
handlers: {
|
|
2169
|
+
GET: handler,
|
|
2170
|
+
POST: handler,
|
|
2171
|
+
},
|
|
2172
|
+
};
|
|
2173
|
+
`
|
|
2174
|
+
}],
|
|
2175
|
+
notes: ["The generated Auth.js instance uses GitHub OAuth through @auth/core; add or replace providers in src/lib/auth.ts."],
|
|
2173
2176
|
ui: authjsUIFeature(),
|
|
2174
|
-
template: () => `import { authjs } from "@farm.js/
|
|
2177
|
+
template: () => `import { authjs } from "@farm.js/authjs";
|
|
2175
2178
|
import { auth } from "../auth.ts";
|
|
2176
2179
|
|
|
2177
2180
|
export const authjsIntegration = authjs({
|
|
@@ -2191,6 +2194,7 @@ export const authjsIntegration = authjs({
|
|
|
2191
2194
|
"unkey-api-keys"
|
|
2192
2195
|
],
|
|
2193
2196
|
defaultKey: "apiKeys",
|
|
2197
|
+
packageName: "@farm.js/unkey",
|
|
2194
2198
|
fileName: "unkey",
|
|
2195
2199
|
exportName: "unkeyIntegration",
|
|
2196
2200
|
description: "Unkey API key creation, verification, and route protection",
|
|
@@ -2200,7 +2204,7 @@ export const authjsIntegration = authjs({
|
|
|
2200
2204
|
"UNKEY_BASE_URL"
|
|
2201
2205
|
],
|
|
2202
2206
|
ui: unkeyApiKeysUIFeature(),
|
|
2203
|
-
template: () => `import { unkey } from "@farm.js/
|
|
2207
|
+
template: () => `import { unkey } from "@farm.js/unkey";
|
|
2204
2208
|
|
|
2205
2209
|
export const unkeyIntegration = unkey({
|
|
2206
2210
|
rootKey: process.env.UNKEY_ROOT_KEY,
|
|
@@ -2217,6 +2221,7 @@ export const unkeyIntegration = unkey({
|
|
|
2217
2221
|
function listFarmIntegrationProviders() {
|
|
2218
2222
|
return PROVIDERS.map((provider) => ({
|
|
2219
2223
|
name: provider.provider,
|
|
2224
|
+
packageName: provider.packageName,
|
|
2220
2225
|
aliases: [...provider.aliases],
|
|
2221
2226
|
defaultKey: provider.defaultKey,
|
|
2222
2227
|
description: provider.description,
|
|
@@ -2452,7 +2457,7 @@ async function updatePackageJson(input) {
|
|
|
2452
2457
|
const devDependencies = missingDependencies(manifest, input.definition.devDependencies);
|
|
2453
2458
|
manifest.dependencies = {
|
|
2454
2459
|
...manifest.dependencies,
|
|
2455
|
-
...hasPackageDependency(manifest,
|
|
2460
|
+
...hasPackageDependency(manifest, input.definition.packageName) ? {} : { [input.definition.packageName]: getFarmIntegrationVersion(manifest) },
|
|
2456
2461
|
...dependencies
|
|
2457
2462
|
};
|
|
2458
2463
|
if (Object.keys(devDependencies).length) manifest.devDependencies = {
|
|
@@ -2535,8 +2540,10 @@ function findFarmConfig(root) {
|
|
|
2535
2540
|
function hasPackageDependency(manifest, dependency) {
|
|
2536
2541
|
return dependency in (manifest.dependencies || {}) || dependency in (manifest.devDependencies || {}) || dependency in (manifest.peerDependencies || {}) || dependency in (manifest.optionalDependencies || {});
|
|
2537
2542
|
}
|
|
2538
|
-
function
|
|
2539
|
-
|
|
2543
|
+
function getFarmIntegrationVersion(manifest) {
|
|
2544
|
+
const farmCoreVersion = manifest.dependencies?.["@farm.js/core"] ?? manifest.devDependencies?.["@farm.js/core"] ?? manifest.peerDependencies?.["@farm.js/core"] ?? manifest.optionalDependencies?.["@farm.js/core"];
|
|
2545
|
+
if (!farmCoreVersion) return "latest";
|
|
2546
|
+
return farmCoreVersion.startsWith("workspace:") ? "workspace:*" : farmCoreVersion;
|
|
2540
2547
|
}
|
|
2541
2548
|
function toImportPath(relativePath) {
|
|
2542
2549
|
const normalized = relativePath.split(node_path.default.sep).join("/");
|
|
@@ -2565,4 +2572,4 @@ Object.defineProperty(exports, "listFarmIntegrationProviders", {
|
|
|
2565
2572
|
}
|
|
2566
2573
|
});
|
|
2567
2574
|
|
|
2568
|
-
//# sourceMappingURL=add-integration-
|
|
2575
|
+
//# sourceMappingURL=add-integration-D5mff3xX.js.map
|