@farm.js/create-app 0.1.0-beta.31 → 0.1.0-beta.33

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.
Files changed (57) hide show
  1. package/README.md +12 -2
  2. package/dist/index.js +84 -22
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.mjs +84 -22
  5. package/dist/index.mjs.map +1 -1
  6. package/package.json +1 -1
  7. package/templates/_integrations/better-auth/preact/farm.config.ts +17 -0
  8. package/templates/_integrations/better-auth/preact/src/app/dashboard/page.tsx +73 -0
  9. package/templates/_integrations/better-auth/preact/src/app/layout.tsx +14 -0
  10. package/templates/_integrations/better-auth/preact/src/app/page.tsx +36 -0
  11. package/templates/_integrations/better-auth/preact/src/app/sign-in/page.tsx +10 -0
  12. package/templates/_integrations/better-auth/preact/src/app/sign-up/page.tsx +10 -0
  13. package/templates/_integrations/better-auth/preact/src/components/auth-form.tsx +92 -0
  14. package/templates/_integrations/better-auth/preact/src/components/auth-shell.tsx +16 -0
  15. package/templates/_integrations/better-auth/preact/src/lib/auth-client.ts +5 -0
  16. package/templates/_integrations/better-auth/solid/farm.config.ts +17 -0
  17. package/templates/_integrations/better-auth/solid/src/app/dashboard/page.tsx +67 -0
  18. package/templates/_integrations/better-auth/solid/src/app/layout.tsx +14 -0
  19. package/templates/_integrations/better-auth/solid/src/app/page.tsx +36 -0
  20. package/templates/_integrations/better-auth/solid/src/app/sign-in/page.tsx +10 -0
  21. package/templates/_integrations/better-auth/solid/src/app/sign-up/page.tsx +10 -0
  22. package/templates/_integrations/better-auth/solid/src/components/auth-form.tsx +91 -0
  23. package/templates/_integrations/better-auth/solid/src/components/auth-shell.tsx +16 -0
  24. package/templates/_integrations/better-auth/solid/src/lib/auth-client.ts +5 -0
  25. package/templates/_integrations/better-auth/svelte/farm.config.ts +17 -0
  26. package/templates/_integrations/better-auth/svelte/src/app/dashboard/page.svelte +62 -0
  27. package/templates/_integrations/better-auth/svelte/src/app/layout.svelte +20 -0
  28. package/templates/_integrations/better-auth/svelte/src/app/page.svelte +32 -0
  29. package/templates/_integrations/better-auth/svelte/src/app/sign-in/page.svelte +10 -0
  30. package/templates/_integrations/better-auth/svelte/src/app/sign-up/page.svelte +10 -0
  31. package/templates/_integrations/better-auth/svelte/src/components/auth-form.svelte +83 -0
  32. package/templates/_integrations/better-auth/svelte/src/components/auth-shell.svelte +16 -0
  33. package/templates/_integrations/better-auth/svelte/src/components/resource-links.svelte +47 -0
  34. package/templates/_integrations/better-auth/svelte/src/lib/auth-client.ts +5 -0
  35. package/templates/_integrations/better-auth/vue/farm.config.ts +17 -0
  36. package/templates/_integrations/better-auth/vue/src/app/dashboard/page.vue +62 -0
  37. package/templates/_integrations/better-auth/vue/src/app/layout.vue +20 -0
  38. package/templates/_integrations/better-auth/vue/src/app/page.vue +34 -0
  39. package/templates/_integrations/better-auth/vue/src/app/sign-in/page.vue +12 -0
  40. package/templates/_integrations/better-auth/vue/src/app/sign-up/page.vue +12 -0
  41. package/templates/_integrations/better-auth/vue/src/components/auth-form.vue +86 -0
  42. package/templates/_integrations/better-auth/vue/src/components/auth-shell.vue +15 -0
  43. package/templates/_integrations/better-auth/vue/src/components/resource-links.vue +43 -0
  44. package/templates/_integrations/better-auth/vue/src/lib/auth-client.ts +5 -0
  45. package/templates/_renderers/preact/package.json +2 -2
  46. package/templates/_renderers/preact/src/app/api/greeting/route.ts +1 -1
  47. package/templates/_renderers/solid/package.json +2 -2
  48. package/templates/_renderers/solid/src/app/api/greeting/route.ts +1 -1
  49. package/templates/_renderers/svelte/farm.config.ts +1 -1
  50. package/templates/_renderers/svelte/package.json +2 -2
  51. package/templates/_renderers/svelte/src/app/api/greeting/route.ts +1 -1
  52. package/templates/_renderers/vue/package.json +2 -2
  53. package/templates/_renderers/vue/src/app/api/greeting/route.ts +1 -1
  54. package/templates/auth/package.json +3 -3
  55. package/templates/basic/package.json +2 -2
  56. package/templates/better-auth/README.md +5 -3
  57. package/templates/better-auth/package.json +3 -3
package/README.md CHANGED
@@ -10,11 +10,20 @@ cd my-app
10
10
  pnpm dev
11
11
  ```
12
12
 
13
- The scaffolder installs React, React DOM, FARMJS, TypeScript, and the other starter dependencies
13
+ The scaffolder installs FARMJS, React by default, TypeScript, and the other starter dependencies
14
14
  automatically. The command explicitly selects the minimal Basic starter. Use `pnpm create`, not
15
15
  `pnpm add`; pnpm resolves this initializer command to the published `@farm.js/create-app` package.
16
16
  Pass `--skip-install` when you only want to generate the project files.
17
17
 
18
+ Choose React, Preact, Solid, Vue, or Svelte for the Basic and Better Auth starters:
19
+
20
+ ```bash
21
+ pnpm create @farm.js/app@beta my-app --template better-auth --renderer solid --typescript
22
+ ```
23
+
24
+ React remains the default when `--renderer` is omitted. The interactive Basic and Better Auth
25
+ flows also offer a renderer chooser.
26
+
18
27
  List every starter:
19
28
 
20
29
  ```bash
@@ -29,7 +38,8 @@ Available templates:
29
38
  - Product integrations: `ai`, `jobs-inngest`, `jobs-trigger`, `resend`, `unkey`
30
39
 
31
40
  Integration templates include provider wiring, a local UI feature, `.env.example`, a minimal dark
32
- home page, and setup documentation. For example:
41
+ home page, and setup documentation. Better Auth has renderer-native UI for all five renderers;
42
+ other integration templates currently use React. For example:
33
43
 
34
44
  ```bash
35
45
  pnpm create @farm.js/app@beta stripe-app --template stripe --typescript
package/dist/index.js CHANGED
@@ -2726,7 +2726,7 @@ async function createApp(projectName, options = {}) {
2726
2726
  require_utils.logger.error(`Unknown renderer "${options.renderer}". Available: "react", "preact", "solid", "vue", "svelte".`);
2727
2727
  process.exit(1);
2728
2728
  }
2729
- if (!renderer && !options.template && template === "basic") {
2729
+ if (!renderer && !options.template && (template === "basic" || template === "better-auth")) {
2730
2730
  const response = await (0, prompts.default)({
2731
2731
  type: "select",
2732
2732
  name: "renderer",
@@ -2767,8 +2767,8 @@ async function createApp(projectName, options = {}) {
2767
2767
  renderer = response.renderer;
2768
2768
  }
2769
2769
  renderer ||= "react";
2770
- if (renderer !== "react" && template !== "basic") {
2771
- require_utils.logger.error(`The "${template}" integration starter currently targets React. Use --template basic with --renderer ${renderer}.`);
2770
+ if (renderer !== "react" && template !== "basic" && !await hasRendererIntegrationTemplate(template, renderer)) {
2771
+ require_utils.logger.error(`The "${template}" integration starter currently targets React. Use --template basic or --template better-auth with --renderer ${renderer}.`);
2772
2772
  process.exit(1);
2773
2773
  }
2774
2774
  let useTypeScript = options.typescript;
@@ -2825,29 +2825,18 @@ async function createApp(projectName, options = {}) {
2825
2825
  async function copyTemplate(template, projectPath, useTypeScript, renderer) {
2826
2826
  const details = templateDetails[template];
2827
2827
  await copyDir(path.default.join(__dirname, "..", "templates", details?.integration ? "basic" : template), projectPath);
2828
+ const basePackageJson = await readPackageJson(projectPath);
2828
2829
  if (useTypeScript) {
2829
2830
  const tsTemplatePath = path.default.join(__dirname, "..", "templates", "_typescript");
2830
2831
  if (await dirExists(tsTemplatePath)) await copyDir(tsTemplatePath, projectPath);
2831
2832
  }
2832
- if (renderer === "solid") await copyDir(path.default.join(__dirname, "..", "templates", "_renderers", "solid"), projectPath);
2833
- if (renderer === "preact") await copyDir(path.default.join(__dirname, "..", "templates", "_renderers", "preact"), projectPath);
2834
- if (renderer === "vue") {
2835
- const rendererTemplatePath = path.default.join(__dirname, "..", "templates", "_renderers", "vue");
2836
- await Promise.all([
2837
- fs_promises.default.rm(path.default.join(projectPath, "src", "app", "page.tsx"), { force: true }),
2838
- fs_promises.default.rm(path.default.join(projectPath, "src", "app", "layout.tsx"), { force: true }),
2839
- fs_promises.default.rm(path.default.join(projectPath, "src", "components", "resource-links.tsx"), { force: true })
2840
- ]);
2841
- await copyDir(rendererTemplatePath, projectPath);
2842
- }
2843
- if (renderer === "svelte") {
2844
- const rendererTemplatePath = path.default.join(__dirname, "..", "templates", "_renderers", "svelte");
2845
- await Promise.all([
2846
- fs_promises.default.rm(path.default.join(projectPath, "src", "app", "page.tsx"), { force: true }),
2847
- fs_promises.default.rm(path.default.join(projectPath, "src", "app", "layout.tsx"), { force: true }),
2848
- fs_promises.default.rm(path.default.join(projectPath, "src", "components", "resource-links.tsx"), { force: true })
2849
- ]);
2850
- await copyDir(rendererTemplatePath, projectPath);
2833
+ if (renderer !== "react") {
2834
+ await applyRendererTemplate(projectPath, renderer, basePackageJson);
2835
+ const integrationRendererPath = getRendererIntegrationTemplatePath(template, renderer);
2836
+ if (await dirExists(integrationRendererPath)) {
2837
+ await removeRendererIntegrationConflicts(projectPath);
2838
+ await copyDir(integrationRendererPath, projectPath);
2839
+ }
2851
2840
  }
2852
2841
  if (!details?.integration) return;
2853
2842
  const result = await addFarmIntegration({
@@ -2860,6 +2849,79 @@ async function copyTemplate(template, projectPath, useTypeScript, renderer) {
2860
2849
  await writeIntegrationReadme(projectPath, details.integration, result.env);
2861
2850
  return result;
2862
2851
  }
2852
+ async function applyRendererTemplate(projectPath, renderer, basePackageJson) {
2853
+ const rendererTemplatePath = path.default.join(__dirname, "..", "templates", "_renderers", renderer);
2854
+ if (renderer === "vue" || renderer === "svelte") await Promise.all([
2855
+ fs_promises.default.rm(path.default.join(projectPath, "src", "app", "page.tsx"), { force: true }),
2856
+ fs_promises.default.rm(path.default.join(projectPath, "src", "app", "layout.tsx"), { force: true }),
2857
+ fs_promises.default.rm(path.default.join(projectPath, "src", "components", "resource-links.tsx"), { force: true })
2858
+ ]);
2859
+ await copyDir(rendererTemplatePath, projectPath);
2860
+ await writePackageJson(projectPath, mergeRendererPackageJson(basePackageJson, await readPackageJson(projectPath)));
2861
+ }
2862
+ function mergeRendererPackageJson(base, renderer) {
2863
+ const dependencies = {
2864
+ ...base.dependencies,
2865
+ ...renderer.dependencies
2866
+ };
2867
+ const devDependencies = {
2868
+ ...base.devDependencies,
2869
+ ...renderer.devDependencies
2870
+ };
2871
+ for (const name of ["react", "react-dom"]) delete dependencies[name];
2872
+ for (const name of ["@types/react", "@types/react-dom"]) delete devDependencies[name];
2873
+ return {
2874
+ ...base,
2875
+ ...renderer.type ? { type: renderer.type } : {},
2876
+ scripts: {
2877
+ ...base.scripts,
2878
+ ...renderer.scripts
2879
+ },
2880
+ dependencies,
2881
+ devDependencies
2882
+ };
2883
+ }
2884
+ async function readPackageJson(projectPath) {
2885
+ return JSON.parse(await fs_promises.default.readFile(path.default.join(projectPath, "package.json"), "utf8"));
2886
+ }
2887
+ async function writePackageJson(projectPath, packageJson) {
2888
+ await fs_promises.default.writeFile(path.default.join(projectPath, "package.json"), `${JSON.stringify(packageJson, null, 2)}\n`, "utf8");
2889
+ }
2890
+ function getRendererIntegrationTemplatePath(template, renderer) {
2891
+ return path.default.join(__dirname, "..", "templates", "_integrations", template, renderer);
2892
+ }
2893
+ async function hasRendererIntegrationTemplate(template, renderer) {
2894
+ return dirExists(getRendererIntegrationTemplatePath(template, renderer));
2895
+ }
2896
+ async function removeRendererIntegrationConflicts(projectPath) {
2897
+ const appFiles = [
2898
+ "page.tsx",
2899
+ "layout.tsx",
2900
+ "loading.tsx",
2901
+ "error.tsx",
2902
+ "not-found.tsx",
2903
+ "sign-in/page.tsx",
2904
+ "sign-up/page.tsx",
2905
+ "dashboard/page.tsx",
2906
+ "preact.css",
2907
+ "solid.css",
2908
+ "vue.css",
2909
+ "svelte.css",
2910
+ "api/greeting/route.ts"
2911
+ ];
2912
+ const componentFiles = [
2913
+ "auth-form.tsx",
2914
+ "auth-shell.tsx",
2915
+ "sign-out-button.tsx",
2916
+ "site-header.tsx"
2917
+ ];
2918
+ await Promise.all([
2919
+ ...appFiles.map((file) => fs_promises.default.rm(path.default.join(projectPath, "src", "app", file), { force: true })),
2920
+ ...componentFiles.map((file) => fs_promises.default.rm(path.default.join(projectPath, "src", "components", file), { force: true })),
2921
+ fs_promises.default.rm(path.default.join(projectPath, "src", "lib", "api-client.ts"), { force: true }),
2922
+ fs_promises.default.rm(path.default.join(projectPath, "src", "lib", "api.generated.ts"), { force: true })
2923
+ ]);
2924
+ }
2863
2925
  async function writeEnvironmentExample(projectPath, keys) {
2864
2926
  if (keys.length === 0) return;
2865
2927
  const envPath = path.default.join(projectPath, ".env.example");