@farm.js/cli 0.1.0-beta.4 → 0.1.0-beta.40

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.
@@ -1,29 +1,8 @@
1
- //#region \0rolldown/runtime.js
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __copyProps = (to, from, except, desc) => {
9
- if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
- key = keys[i];
11
- if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
- get: ((k) => from[k]).bind(null, key),
13
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
- });
15
- }
16
- return to;
17
- };
18
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
19
- value: mod,
20
- enumerable: true
21
- }) : target, mod));
22
- //#endregion
1
+ const require_rolldown_runtime = require("./rolldown-runtime-VH7oDXx4.js");
23
2
  let node_fs = require("node:fs");
24
3
  let node_fs_promises = require("node:fs/promises");
25
4
  let node_path = require("node:path");
26
- node_path = __toESM(node_path);
5
+ node_path = require_rolldown_runtime.__toESM(node_path);
27
6
  //#region src/ui-feature-registry.ts
28
7
  async function installUIFeature(input) {
29
8
  const feature = input.definition.ui;
@@ -123,7 +102,7 @@ function aiChatUIFeature() {
123
102
  ],
124
103
  needsApiClient: false,
125
104
  notes: ["Open \"/integrations/ai\" to try the generated chat UI."],
126
- files: () => [componentFile("ai-chat.tsx", aiChatTemplate()), integrationPageFile("ai", "AIChat")]
105
+ files: () => [componentFile("ai-chat.tsx", aiChatTemplate()), integrationPageFile("ai", "AIChat", "ai-chat")]
127
106
  };
128
107
  }
129
108
  function supabaseAuthUIFeature() {
@@ -155,35 +134,25 @@ function workosAuthUIFeature() {
155
134
  key: input.key,
156
135
  provider: "WorkOS",
157
136
  componentName: "WorkOSAuthPanel",
158
- statusCall: "session.get",
159
- logoutCall: "logout.post",
137
+ statusCall: "session",
138
+ statusMethod: "get",
139
+ logoutCall: "logout",
140
+ logoutMethod: "post",
160
141
  loginHref: "/login?returnTo=/dashboard",
161
142
  signupHref: "/signup?returnTo=/dashboard",
162
143
  statusLabel: "Session"
163
- })), integrationPageFile("workos", "WorkOSAuthPanel")]
144
+ })), integrationPageFile("workos", "WorkOSAuthPanel", "workos-auth-panel")]
164
145
  };
165
146
  }
166
147
  function auth0AuthUIFeature() {
167
- return {
168
- name: "auth0-auth",
169
- description: "Auth0 auth UI",
170
- components: [
171
- "badge",
172
- "button",
173
- "card"
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
- };
148
+ return authRouteShellUIFeature({
149
+ provider: "auth0",
150
+ label: "Auth0",
151
+ componentName: "Auth0AuthPanel",
152
+ signInHref: "/auth/login?returnTo=/dashboard",
153
+ signUpHref: "/auth/signup?returnTo=/dashboard",
154
+ sessionHref: "/auth/profile"
155
+ });
187
156
  }
188
157
  function clerkAuthUIFeature() {
189
158
  return authRouteShellUIFeature({
@@ -262,16 +231,18 @@ function jobsUIFeature(provider) {
262
231
  function unkeyApiKeysUIFeature() {
263
232
  return {
264
233
  name: "unkey-api-keys",
265
- description: "Unkey API key console UI",
266
- components: [
267
- "badge",
268
- "button",
269
- "card",
270
- "input",
271
- "label"
272
- ],
273
- notes: ["Open \"/integrations/unkey\" to try the generated API key UI."],
274
- files: (input) => [componentFile("unkey-api-keys-console.tsx", unkeyApiKeysTemplate(input.key)), integrationPageFile("unkey", "UnkeyApiKeysConsole")]
234
+ description: "Unkey protected route UI",
235
+ components: ["badge", "card"],
236
+ needsApiClient: false,
237
+ notes: ["Open \"/integrations/unkey\" to test the generated protected API route."],
238
+ files: () => [
239
+ componentFile("unkey-api-keys-console.tsx", unkeyApiKeysTemplate()),
240
+ integrationPageFile("unkey", "UnkeyApiKeysConsole"),
241
+ {
242
+ path: node_path.default.join("src", "app", "api", "protected", "route.ts"),
243
+ source: unkeyProtectedRouteTemplate()
244
+ }
245
+ ]
275
246
  };
276
247
  }
277
248
  function billingUIFeature(input) {
@@ -301,6 +272,7 @@ function authRouteShellUIFeature(input) {
301
272
  "button",
302
273
  "card"
303
274
  ],
275
+ needsApiClient: false,
304
276
  notes: [`Open "/integrations/${input.provider}" to try the generated auth UI.`],
305
277
  files: () => [componentFile(`${input.provider}-auth-panel.tsx`, authRouteShellTemplate({
306
278
  provider: input.label,
@@ -308,7 +280,7 @@ function authRouteShellUIFeature(input) {
308
280
  signInHref: input.signInHref,
309
281
  signUpHref: input.signUpHref,
310
282
  sessionHref: input.sessionHref
311
- })), integrationPageFile(input.provider, input.componentName)]
283
+ })), integrationPageFile(input.provider, input.componentName, input.provider === "authjs" ? "authjs-auth-panel" : void 0)]
312
284
  };
313
285
  }
314
286
  function componentFile(fileName, source) {
@@ -317,11 +289,10 @@ function componentFile(fileName, source) {
317
289
  source
318
290
  };
319
291
  }
320
- function integrationPageFile(provider, componentName) {
321
- const fileName = kebabCase(componentName);
292
+ function integrationPageFile(provider, componentName, sourceFileName = kebabCase(componentName)) {
322
293
  return {
323
294
  path: node_path.default.join("src", "app", "integrations", provider, "page.tsx"),
324
- source: `import { ${componentName} } from "@/components/farm/${fileName}";
295
+ source: `import { ${componentName} } from "@/components/farm/${sourceFileName}";
325
296
 
326
297
  export default function ${componentName}Page() {
327
298
  return <${componentName} />;
@@ -478,7 +449,7 @@ const UI_DEPENDENCIES = {
478
449
  "tailwind-merge": "^3.3.1",
479
450
  tailwindcss: "^4.1.18"
480
451
  };
481
- const SHADCN_THEME_CSS = `@custom-variant dark (&:is(.dark *));
452
+ const SHADCN_THEME_CSS = `@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));
482
453
 
483
454
  @theme inline {
484
455
  --color-background: var(--background);
@@ -504,7 +475,8 @@ const SHADCN_THEME_CSS = `@custom-variant dark (&:is(.dark *));
504
475
  --radius-lg: var(--radius);
505
476
  }
506
477
 
507
- :root {
478
+ :root,
479
+ [data-theme="light"] {
508
480
  --radius: 0.5rem;
509
481
  --background: oklch(1 0 0);
510
482
  --foreground: oklch(0.145 0 0);
@@ -526,7 +498,7 @@ const SHADCN_THEME_CSS = `@custom-variant dark (&:is(.dark *));
526
498
  --ring: oklch(0.708 0 0);
527
499
  }
528
500
 
529
- .dark {
501
+ [data-theme="dark"] {
530
502
  --background: oklch(0.145 0 0);
531
503
  --foreground: oklch(0.985 0 0);
532
504
  --card: oklch(0.205 0 0);
@@ -1129,12 +1101,17 @@ export function SupabaseAuthPanel() {
1129
1101
  }
1130
1102
 
1131
1103
  async function logout() {
1132
- const response = await apiClient.${key}.logout.post({ body: { returnTo: "/" } });
1133
- if (response.data?.redirectTo) {
1134
- window.location.assign(response.data.redirectTo);
1104
+ const response = await fetch("/auth/logout", {
1105
+ method: "POST",
1106
+ headers: { "content-type": "application/json" },
1107
+ body: JSON.stringify({ returnTo: "/" }),
1108
+ });
1109
+ const data = (await response.json()) as { redirectTo?: string; error?: string };
1110
+ if (data.redirectTo) {
1111
+ window.location.assign(data.redirectTo);
1135
1112
  return;
1136
1113
  }
1137
- setStatus(response.error?.message ?? "Signed out");
1114
+ setStatus(data.error ?? "Signed out");
1138
1115
  }
1139
1116
 
1140
1117
  return (
@@ -1193,7 +1170,7 @@ export function ${input.componentName}() {
1193
1170
 
1194
1171
  async function refreshStatus() {
1195
1172
  setPending(true);
1196
- const response = await apiClient.${input.key}.${input.statusCall}();
1173
+ const response = await apiClient.${input.key}.${input.statusCall}.${input.statusMethod}();
1197
1174
  if (response.error) {
1198
1175
  setStatus(response.error.message);
1199
1176
  } else {
@@ -1204,7 +1181,7 @@ export function ${input.componentName}() {
1204
1181
 
1205
1182
  async function logout() {
1206
1183
  setPending(true);
1207
- const response = await apiClient.${input.key}.${input.logoutCall}();
1184
+ const response = await apiClient.${input.key}.${input.logoutCall}.${input.logoutMethod}();
1208
1185
  if (response.data?.redirectTo) {
1209
1186
  window.location.assign(response.data.redirectTo);
1210
1187
  return;
@@ -1467,17 +1444,20 @@ import { apiClient } from "@/lib/api";
1467
1444
  export function ResendEmailConsole() {
1468
1445
  const [to, setTo] = React.useState("");
1469
1446
  const [name, setName] = React.useState("Ada");
1470
- const [templateId, setTemplateId] = React.useState("welcome");
1447
+ const templateId = "welcome" as const;
1471
1448
  const [status, setStatus] = React.useState("Idle");
1472
1449
  const [previewHtml, setPreviewHtml] = React.useState("");
1473
1450
 
1474
1451
  async function loadTemplates() {
1475
- const response = await apiClient.${key}.templates.get();
1476
- setStatus(response.error ? response.error.message : "Templates: " + (response.data ?? []).map((item) => item.id).join(", "));
1452
+ const response = await apiClient.${key}.templates();
1453
+ const templates = Array.isArray(response.data)
1454
+ ? (response.data as Array<{ id: string }>)
1455
+ : [];
1456
+ setStatus(response.error ? response.error.message : "Templates: " + templates.map((item) => item.id).join(", "));
1477
1457
  }
1478
1458
 
1479
1459
  async function preview() {
1480
- const response = await apiClient.${key}.preview.post({
1460
+ const response = await apiClient.${key}.preview({
1481
1461
  body: {
1482
1462
  templateId,
1483
1463
  data: { name },
@@ -1492,7 +1472,7 @@ export function ResendEmailConsole() {
1492
1472
  }
1493
1473
 
1494
1474
  async function send() {
1495
- const response = await apiClient.${key}.send.post({
1475
+ const response = await apiClient.${key}.send({
1496
1476
  body: {
1497
1477
  templateId,
1498
1478
  to,
@@ -1515,11 +1495,7 @@ export function ResendEmailConsole() {
1515
1495
  <CardDescription>Template previews and delivery controls.</CardDescription>
1516
1496
  </CardHeader>
1517
1497
  <CardContent className="space-y-4">
1518
- <div className="grid gap-4 sm:grid-cols-3">
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>
1498
+ <div className="grid gap-4 sm:grid-cols-2">
1523
1499
  <div className="space-y-2">
1524
1500
  <Label htmlFor="to">To</Label>
1525
1501
  <Input id="to" value={to} onChange={(event) => setTo(event.target.value)} />
@@ -1644,47 +1620,11 @@ export function ${`${pascalCase(provider)}JobsConsole`}() {
1644
1620
  }
1645
1621
  `;
1646
1622
  }
1647
- function unkeyApiKeysTemplate(key) {
1648
- return `"use client";
1649
-
1650
- import * as React from "react";
1651
- import { Badge } from "@/components/ui/badge";
1652
- import { Button } from "@/components/ui/button";
1623
+ function unkeyApiKeysTemplate() {
1624
+ return `import { Badge } from "@/components/ui/badge";
1653
1625
  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
1626
 
1658
1627
  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
1628
  return (
1689
1629
  <main className="min-h-screen bg-background px-6 py-12 text-foreground">
1690
1630
  <section className="mx-auto flex w-full max-w-3xl flex-col gap-6">
@@ -1694,29 +1634,16 @@ export function UnkeyApiKeysConsole() {
1694
1634
  </div>
1695
1635
  <Card>
1696
1636
  <CardHeader>
1697
- <CardTitle className="text-xl">Key console</CardTitle>
1698
- <CardDescription>API key lifecycle controls.</CardDescription>
1637
+ <CardTitle className="text-xl">Protected API</CardTitle>
1638
+ <CardDescription>Requests are verified by Unkey before the route runs.</CardDescription>
1699
1639
  </CardHeader>
1700
- <CardContent className="space-y-4">
1701
- <div className="grid gap-4 sm:grid-cols-2">
1702
- <div className="space-y-2">
1703
- <Label htmlFor="name">Name</Label>
1704
- <Input id="name" value={name} onChange={(event) => setName(event.target.value)} />
1705
- </div>
1706
- <div className="space-y-2">
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>
1640
+ <CardContent className="space-y-3">
1641
+ <code className="block overflow-x-auto rounded-md border bg-muted/30 p-3 text-xs">
1642
+ curl http://localhost:3000/api/protected -H &quot;Authorization: Bearer YOUR_KEY&quot;
1643
+ </code>
1644
+ <p className="text-sm text-muted-foreground">
1645
+ Create and rotate keys from trusted server code or the Unkey dashboard.
1646
+ </p>
1720
1647
  </CardContent>
1721
1648
  </Card>
1722
1649
  </section>
@@ -1725,6 +1652,15 @@ export function UnkeyApiKeysConsole() {
1725
1652
  }
1726
1653
  `;
1727
1654
  }
1655
+ function unkeyProtectedRouteTemplate() {
1656
+ return `export function GET() {
1657
+ return Response.json({
1658
+ ok: true,
1659
+ message: "Valid Unkey API key.",
1660
+ });
1661
+ }
1662
+ `;
1663
+ }
1728
1664
  function pascalCase(input) {
1729
1665
  return input.split(/[^A-Za-z0-9]+/g).filter(Boolean).map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`).join("");
1730
1666
  }
@@ -1752,6 +1688,7 @@ const PROVIDERS = [
1752
1688
  "chat"
1753
1689
  ],
1754
1690
  defaultKey: "chat",
1691
+ packageName: "@farm.js/ai",
1755
1692
  fileName: "chat",
1756
1693
  exportName: "POST",
1757
1694
  description: "Vercel AI SDK chat route",
@@ -1762,7 +1699,7 @@ const PROVIDERS = [
1762
1699
  "No farm.config integration wiring is required for this route."
1763
1700
  ],
1764
1701
  ui: aiChatUIFeature(),
1765
- template: () => `import { aiChatRoute } from "@farm.js/integrations/ai";
1702
+ template: () => `import { aiChatRoute } from "@farm.js/ai";
1766
1703
 
1767
1704
  export const POST = aiChatRoute({
1768
1705
  model: "openai/gpt-4o-mini",
@@ -1778,17 +1715,19 @@ export const POST = aiChatRoute({
1778
1715
  "stripe-billing"
1779
1716
  ],
1780
1717
  defaultKey: "billing",
1718
+ packageName: "@farm.js/stripe",
1781
1719
  fileName: "stripe",
1782
1720
  exportName: "stripeIntegration",
1783
1721
  description: "Stripe billing and checkout routes",
1784
1722
  env: ["STRIPE_SECRET_KEY", "STRIPE_WEBHOOK_SECRET"],
1785
- template: () => `import { stripe } from "@farm.js/integrations/stripe";
1723
+ template: () => `import type { FarmIntegrationLogEvent } from "@farm.js/core";
1724
+ import { stripe } from "@farm.js/stripe";
1786
1725
 
1787
1726
  export const stripeIntegration = stripe({
1788
1727
  secretKey: process.env.STRIPE_SECRET_KEY,
1789
1728
  webhookSecret: process.env.STRIPE_WEBHOOK_SECRET,
1790
1729
  products: [],
1791
- log(event) {
1730
+ log(event: FarmIntegrationLogEvent) {
1792
1731
  console.log("[stripe]", event.phase, event.route?.path || "none");
1793
1732
  },
1794
1733
  });
@@ -1799,6 +1738,7 @@ export const stripeIntegration = stripe({
1799
1738
  provider: "supabase",
1800
1739
  aliases: ["auth-supabase", "supabase-auth"],
1801
1740
  defaultKey: "auth",
1741
+ packageName: "@farm.js/supabase",
1802
1742
  fileName: "supabase",
1803
1743
  exportName: "supabaseIntegration",
1804
1744
  description: "Supabase auth routes and middleware",
@@ -1808,7 +1748,7 @@ export const stripeIntegration = stripe({
1808
1748
  "APP_BASE_URL"
1809
1749
  ],
1810
1750
  ui: supabaseAuthUIFeature(),
1811
- template: () => `import { supabase } from "@farm.js/integrations/supabase";
1751
+ template: () => `import { supabase } from "@farm.js/supabase";
1812
1752
 
1813
1753
  export const supabaseIntegration = supabase({
1814
1754
  callbackUrl: \`\${process.env.APP_BASE_URL || "http://localhost:3000"}/auth/callback\`,
@@ -1827,6 +1767,7 @@ export const supabaseIntegration = supabase({
1827
1767
  provider: "workos",
1828
1768
  aliases: ["auth-workos", "workos-auth"],
1829
1769
  defaultKey: "auth",
1770
+ packageName: "@farm.js/workos",
1830
1771
  fileName: "workos",
1831
1772
  exportName: "workosIntegration",
1832
1773
  description: "WorkOS auth routes and protected route middleware",
@@ -1836,7 +1777,7 @@ export const supabaseIntegration = supabase({
1836
1777
  "WORKOS_COOKIE_PASSWORD"
1837
1778
  ],
1838
1779
  ui: workosAuthUIFeature(),
1839
- template: () => `import { workos } from "@farm.js/integrations/workos";
1780
+ template: () => `import { workos } from "@farm.js/workos";
1840
1781
 
1841
1782
  export const workosIntegration = workos({
1842
1783
  protectedRoutes: ["/dashboard(.*)"],
@@ -1850,6 +1791,7 @@ export const workosIntegration = workos({
1850
1791
  provider: "auth0",
1851
1792
  aliases: ["auth-auth0", "auth0-auth"],
1852
1793
  defaultKey: "auth",
1794
+ packageName: "@farm.js/auth0",
1853
1795
  fileName: "auth0",
1854
1796
  exportName: "auth0Integration",
1855
1797
  description: "Auth0 login, callback, logout, and profile routes",
@@ -1860,7 +1802,7 @@ export const workosIntegration = workos({
1860
1802
  "AUTH0_SECRET"
1861
1803
  ],
1862
1804
  ui: auth0AuthUIFeature(),
1863
- template: () => `import { auth0 } from "@farm.js/integrations/auth0";
1805
+ template: () => `import { auth0 } from "@farm.js/auth0";
1864
1806
 
1865
1807
  export const auth0Integration = auth0({
1866
1808
  callbackUrl: \`\${process.env.APP_BASE_URL || "http://localhost:3000"}/auth/callback\`,
@@ -1875,12 +1817,14 @@ export const auth0Integration = auth0({
1875
1817
  provider: "clerk",
1876
1818
  aliases: ["auth-clerk", "clerk-auth"],
1877
1819
  defaultKey: "auth",
1820
+ packageName: "@farm.js/clerk",
1878
1821
  fileName: "clerk",
1879
1822
  exportName: "clerkIntegration",
1880
1823
  description: "Clerk auth provider and protected route middleware",
1881
1824
  env: ["NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY", "CLERK_SECRET_KEY"],
1825
+ dependencies: { "@clerk/react": "^6.1.0" },
1882
1826
  ui: clerkAuthUIFeature(),
1883
- template: () => `import { clerk } from "@farm.js/integrations/clerk";
1827
+ template: () => `import { clerk } from "@farm.js/clerk";
1884
1828
 
1885
1829
  export const clerkIntegration = clerk({
1886
1830
  signInUrl: "/sign-in",
@@ -1896,6 +1840,7 @@ export const clerkIntegration = clerk({
1896
1840
  provider: "resend",
1897
1841
  aliases: ["email", "resend-email"],
1898
1842
  defaultKey: "email",
1843
+ packageName: "@farm.js/email",
1899
1844
  fileName: "resend",
1900
1845
  exportName: "resendIntegration",
1901
1846
  description: "Resend email send, preview, schedule, and webhook routes",
@@ -1906,7 +1851,7 @@ export const clerkIntegration = clerk({
1906
1851
  ],
1907
1852
  ui: resendEmailUIFeature(),
1908
1853
  template: () => `import { createElement } from "react";
1909
- import { resend, template } from "@farm.js/integrations/email";
1854
+ import { resend, template } from "@farm.js/email";
1910
1855
 
1911
1856
  function WelcomeEmail(props: { name: string }) {
1912
1857
  return createElement("div", null, \`Welcome \${props.name}\`);
@@ -1945,6 +1890,7 @@ export const resendIntegration = resend({
1945
1890
  provider: "jobs-inngest",
1946
1891
  aliases: ["inngest", "jobs"],
1947
1892
  defaultKey: "jobs",
1893
+ packageName: "@farm.js/jobs",
1948
1894
  fileName: "jobs-inngest",
1949
1895
  exportName: "jobsIntegration",
1950
1896
  description: "Jobs integration backed by Inngest",
@@ -1955,7 +1901,7 @@ export const resendIntegration = resend({
1955
1901
  ],
1956
1902
  notes: ["Add tasks to jobTasks before using the generated jobs API."],
1957
1903
  ui: jobsUIFeature("inngest"),
1958
- template: () => `import { defineTasks, inngest, jobs } from "@farm.js/integrations/jobs";
1904
+ template: () => `import { defineTasks, inngest, jobs } from "@farm.js/jobs";
1959
1905
 
1960
1906
  export const jobTasks = defineTasks({});
1961
1907
 
@@ -1980,6 +1926,7 @@ export const jobsIntegration = jobs({
1980
1926
  "jobs-triggerdev"
1981
1927
  ],
1982
1928
  defaultKey: "jobs",
1929
+ packageName: "@farm.js/jobs",
1983
1930
  fileName: "jobs-trigger",
1984
1931
  exportName: "jobsIntegration",
1985
1932
  description: "Jobs integration backed by Trigger.dev",
@@ -1990,7 +1937,7 @@ export const jobsIntegration = jobs({
1990
1937
  ],
1991
1938
  notes: ["Add tasks to jobTasks before using the generated jobs API."],
1992
1939
  ui: jobsUIFeature("trigger"),
1993
- template: () => `import { defineTasks, jobs, trigger } from "@farm.js/integrations/jobs";
1940
+ template: () => `import { defineTasks, jobs, trigger } from "@farm.js/jobs";
1994
1941
 
1995
1942
  export const jobTasks = defineTasks({});
1996
1943
 
@@ -2011,6 +1958,7 @@ export const jobsIntegration = jobs({
2011
1958
  provider: "polar",
2012
1959
  aliases: ["polar-billing", "billing-polar"],
2013
1960
  defaultKey: "billing",
1961
+ packageName: "@farm.js/polar",
2014
1962
  fileName: "polar",
2015
1963
  exportName: "polarIntegration",
2016
1964
  description: "Polar billing and checkout routes",
@@ -2022,9 +1970,9 @@ export const jobsIntegration = jobs({
2022
1970
  notes: ["Replace resolveBillingOwner with your app user or organization lookup."],
2023
1971
  ui: polarBillingUIFeature(),
2024
1972
  template: () => `import type { FarmIntegrationHandlerContext } from "@farm.js/core";
2025
- import { polar } from "@farm.js/integrations/polar";
1973
+ import { polar } from "@farm.js/polar";
2026
1974
 
2027
- async function resolveBillingOwner(_context: FarmIntegrationHandlerContext) {
1975
+ function resolveBillingOwner(_context: FarmIntegrationHandlerContext): never {
2028
1976
  throw new Error("Configure Polar billing owner resolution for your app.");
2029
1977
  }
2030
1978
 
@@ -2052,6 +2000,7 @@ export const polarIntegration = polar({
2052
2000
  provider: "autumn",
2053
2001
  aliases: ["autumn-billing", "billing-autumn"],
2054
2002
  defaultKey: "billing",
2003
+ packageName: "@farm.js/autumn",
2055
2004
  fileName: "autumn",
2056
2005
  exportName: "autumnIntegration",
2057
2006
  description: "Autumn billing and checkout routes",
@@ -2063,9 +2012,9 @@ export const polarIntegration = polar({
2063
2012
  notes: ["Replace resolveBillingOwner with your app user or organization lookup."],
2064
2013
  ui: autumnBillingUIFeature(),
2065
2014
  template: () => `import type { FarmIntegrationHandlerContext } from "@farm.js/core";
2066
- import { autumn } from "@farm.js/integrations/autumn";
2015
+ import { autumn } from "@farm.js/autumn";
2067
2016
 
2068
- async function resolveBillingOwner(_context: FarmIntegrationHandlerContext) {
2017
+ function resolveBillingOwner(_context: FarmIntegrationHandlerContext): never {
2069
2018
  throw new Error("Configure Autumn billing owner resolution for your app.");
2070
2019
  }
2071
2020
 
@@ -2092,6 +2041,7 @@ export const autumnIntegration = autumn({
2092
2041
  provider: "better-auth",
2093
2042
  aliases: ["betterauth", "auth-better-auth"],
2094
2043
  defaultKey: "auth",
2044
+ packageName: "@farm.js/better-auth",
2095
2045
  fileName: "better-auth",
2096
2046
  exportName: "betterAuthIntegration",
2097
2047
  description: "Better Auth route adapter",
@@ -2146,7 +2096,7 @@ better-auth.sqlite-wal
2146
2096
  }
2147
2097
  ],
2148
2098
  ui: betterAuthUIFeature(),
2149
- template: () => `import { betterAuth } from "@farm.js/integrations/better-auth";
2099
+ template: () => `import { betterAuth } from "@farm.js/better-auth";
2150
2100
  import { auth } from "../auth.ts";
2151
2101
 
2152
2102
  export const betterAuthIntegration = betterAuth({
@@ -2165,13 +2115,45 @@ export const betterAuthIntegration = betterAuth({
2165
2115
  "next-auth"
2166
2116
  ],
2167
2117
  defaultKey: "auth",
2118
+ packageName: "@farm.js/authjs",
2168
2119
  fileName: "authjs",
2169
2120
  exportName: "authjsIntegration",
2170
2121
  description: "Auth.js route adapter",
2171
- env: [],
2172
- notes: ["This template expects src/lib/auth.ts to export an Auth.js instance named auth."],
2122
+ env: [
2123
+ "AUTH_SECRET",
2124
+ "AUTH_GITHUB_ID",
2125
+ "AUTH_GITHUB_SECRET"
2126
+ ],
2127
+ dependencies: { "@auth/core": "0.34.3" },
2128
+ setupFiles: [{
2129
+ path: "src/lib/auth.ts",
2130
+ source: () => `import { Auth } from "@auth/core";
2131
+ import GitHub from "@auth/core/providers/github";
2132
+
2133
+ const config = {
2134
+ providers: [
2135
+ GitHub({
2136
+ clientId: process.env.AUTH_GITHUB_ID!,
2137
+ clientSecret: process.env.AUTH_GITHUB_SECRET!,
2138
+ }),
2139
+ ],
2140
+ secret: process.env.AUTH_SECRET,
2141
+ trustHost: true,
2142
+ };
2143
+
2144
+ const handler = (request: Request) => Auth(request, config);
2145
+
2146
+ export const auth = {
2147
+ handlers: {
2148
+ GET: handler,
2149
+ POST: handler,
2150
+ },
2151
+ };
2152
+ `
2153
+ }],
2154
+ notes: ["The generated Auth.js instance uses GitHub OAuth through @auth/core; add or replace providers in src/lib/auth.ts."],
2173
2155
  ui: authjsUIFeature(),
2174
- template: () => `import { authjs } from "@farm.js/integrations/authjs";
2156
+ template: () => `import { authjs } from "@farm.js/authjs";
2175
2157
  import { auth } from "../auth.ts";
2176
2158
 
2177
2159
  export const authjsIntegration = authjs({
@@ -2191,6 +2173,7 @@ export const authjsIntegration = authjs({
2191
2173
  "unkey-api-keys"
2192
2174
  ],
2193
2175
  defaultKey: "apiKeys",
2176
+ packageName: "@farm.js/unkey",
2194
2177
  fileName: "unkey",
2195
2178
  exportName: "unkeyIntegration",
2196
2179
  description: "Unkey API key creation, verification, and route protection",
@@ -2200,7 +2183,7 @@ export const authjsIntegration = authjs({
2200
2183
  "UNKEY_BASE_URL"
2201
2184
  ],
2202
2185
  ui: unkeyApiKeysUIFeature(),
2203
- template: () => `import { unkey } from "@farm.js/integrations/unkey";
2186
+ template: () => `import { unkey } from "@farm.js/unkey";
2204
2187
 
2205
2188
  export const unkeyIntegration = unkey({
2206
2189
  rootKey: process.env.UNKEY_ROOT_KEY,
@@ -2217,6 +2200,7 @@ export const unkeyIntegration = unkey({
2217
2200
  function listFarmIntegrationProviders() {
2218
2201
  return PROVIDERS.map((provider) => ({
2219
2202
  name: provider.provider,
2203
+ packageName: provider.packageName,
2220
2204
  aliases: [...provider.aliases],
2221
2205
  defaultKey: provider.defaultKey,
2222
2206
  description: provider.description,
@@ -2452,7 +2436,7 @@ async function updatePackageJson(input) {
2452
2436
  const devDependencies = missingDependencies(manifest, input.definition.devDependencies);
2453
2437
  manifest.dependencies = {
2454
2438
  ...manifest.dependencies,
2455
- ...hasPackageDependency(manifest, "@farm.js/integrations") ? {} : { "@farm.js/integrations": getFarmIntegrationsVersion(manifest) },
2439
+ ...hasPackageDependency(manifest, input.definition.packageName) ? {} : { [input.definition.packageName]: getFarmIntegrationVersion(manifest) },
2456
2440
  ...dependencies
2457
2441
  };
2458
2442
  if (Object.keys(devDependencies).length) manifest.devDependencies = {
@@ -2535,8 +2519,10 @@ function findFarmConfig(root) {
2535
2519
  function hasPackageDependency(manifest, dependency) {
2536
2520
  return dependency in (manifest.dependencies || {}) || dependency in (manifest.devDependencies || {}) || dependency in (manifest.peerDependencies || {}) || dependency in (manifest.optionalDependencies || {});
2537
2521
  }
2538
- function getFarmIntegrationsVersion(manifest) {
2539
- return (manifest.dependencies?.["@farm.js/core"] ?? manifest.devDependencies?.["@farm.js/core"] ?? manifest.peerDependencies?.["@farm.js/core"] ?? manifest.optionalDependencies?.["@farm.js/core"])?.startsWith("workspace:") ? "workspace:*" : "latest";
2522
+ function getFarmIntegrationVersion(manifest) {
2523
+ const farmCoreVersion = manifest.dependencies?.["@farm.js/core"] ?? manifest.devDependencies?.["@farm.js/core"] ?? manifest.peerDependencies?.["@farm.js/core"] ?? manifest.optionalDependencies?.["@farm.js/core"];
2524
+ if (!farmCoreVersion) return "latest";
2525
+ return farmCoreVersion.startsWith("workspace:") ? "workspace:*" : farmCoreVersion;
2540
2526
  }
2541
2527
  function toImportPath(relativePath) {
2542
2528
  const normalized = relativePath.split(node_path.default.sep).join("/");
@@ -2546,12 +2532,6 @@ function escapeRegExp(input) {
2546
2532
  return input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2547
2533
  }
2548
2534
  //#endregion
2549
- Object.defineProperty(exports, "__toESM", {
2550
- enumerable: true,
2551
- get: function() {
2552
- return __toESM;
2553
- }
2554
- });
2555
2535
  Object.defineProperty(exports, "addFarmIntegration", {
2556
2536
  enumerable: true,
2557
2537
  get: function() {
@@ -2565,4 +2545,4 @@ Object.defineProperty(exports, "listFarmIntegrationProviders", {
2565
2545
  }
2566
2546
  });
2567
2547
 
2568
- //# sourceMappingURL=add-integration-Xc0p-k-m.js.map
2548
+ //# sourceMappingURL=add-integration-Bz7WjUfh.js.map