@farm.js/create-app 0.1.0-beta.34 → 0.1.0-beta.36

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farm.js/create-app",
3
- "version": "0.1.0-beta.34",
3
+ "version": "0.1.0-beta.36",
4
4
  "description": "Create a new FARMJS application",
5
5
  "keywords": [
6
6
  "@farm.js/create-app",
@@ -11,7 +11,7 @@
11
11
  "type-check": "tsc --noEmit"
12
12
  },
13
13
  "dependencies": {
14
- "@farm.js/core": "0.1.0-beta.34",
14
+ "@farm.js/core": "0.1.0-beta.36",
15
15
  "@farm.js/preact": "0.1.0-beta.30",
16
16
  "@fontsource-variable/geist": "5.3.0",
17
17
  "@fontsource-variable/geist-mono": "5.3.0",
@@ -19,7 +19,7 @@
19
19
  "zod": "4.1.12"
20
20
  },
21
21
  "devDependencies": {
22
- "@farm.js/cli": "0.1.0-beta.34",
22
+ "@farm.js/cli": "0.1.0-beta.36",
23
23
  "tailwindcss": "^4.0.0",
24
24
  "typescript": "^5.3.3"
25
25
  },
@@ -10,7 +10,7 @@
10
10
  "type-check": "tsc --noEmit"
11
11
  },
12
12
  "dependencies": {
13
- "@farm.js/core": "0.1.0-beta.34",
13
+ "@farm.js/core": "0.1.0-beta.36",
14
14
  "@farm.js/solid": "0.1.0-beta.26",
15
15
  "@fontsource-variable/geist": "5.3.0",
16
16
  "@fontsource-variable/geist-mono": "5.3.0",
@@ -18,7 +18,7 @@
18
18
  "zod": "4.1.12"
19
19
  },
20
20
  "devDependencies": {
21
- "@farm.js/cli": "0.1.0-beta.34",
21
+ "@farm.js/cli": "0.1.0-beta.36",
22
22
  "tailwindcss": "^4.0.0",
23
23
  "typescript": "^5.3.3"
24
24
  },
@@ -11,7 +11,7 @@
11
11
  "type-check": "svelte-check --tsconfig ./tsconfig.json"
12
12
  },
13
13
  "dependencies": {
14
- "@farm.js/core": "0.1.0-beta.34",
14
+ "@farm.js/core": "0.1.0-beta.36",
15
15
  "@farm.js/svelte": "0.1.0-beta.29",
16
16
  "@fontsource-variable/geist": "5.3.0",
17
17
  "@fontsource-variable/geist-mono": "5.3.0",
@@ -19,7 +19,7 @@
19
19
  "zod": "4.1.12"
20
20
  },
21
21
  "devDependencies": {
22
- "@farm.js/cli": "0.1.0-beta.34",
22
+ "@farm.js/cli": "0.1.0-beta.36",
23
23
  "svelte-check": "4.7.5",
24
24
  "tailwindcss": "^4.0.0",
25
25
  "typescript": "^5.3.3"
@@ -10,7 +10,7 @@
10
10
  "type-check": "vue-tsc --noEmit"
11
11
  },
12
12
  "dependencies": {
13
- "@farm.js/core": "0.1.0-beta.34",
13
+ "@farm.js/core": "0.1.0-beta.36",
14
14
  "@farm.js/vue": "0.1.0-beta.26",
15
15
  "@fontsource-variable/geist": "5.3.0",
16
16
  "@fontsource-variable/geist-mono": "5.3.0",
@@ -18,7 +18,7 @@
18
18
  "zod": "4.1.12"
19
19
  },
20
20
  "devDependencies": {
21
- "@farm.js/cli": "0.1.0-beta.34",
21
+ "@farm.js/cli": "0.1.0-beta.36",
22
22
  "tailwindcss": "^4.0.0",
23
23
  "typescript": "^5.3.3",
24
24
  "vue-tsc": "3.3.9"
@@ -12,8 +12,8 @@
12
12
  "type-check": "tsc --noEmit"
13
13
  },
14
14
  "dependencies": {
15
- "@farm.js/auth": "0.1.0-beta.34",
16
- "@farm.js/core": "0.1.0-beta.34",
15
+ "@farm.js/auth": "0.1.0-beta.36",
16
+ "@farm.js/core": "0.1.0-beta.36",
17
17
  "@fontsource-variable/geist": "5.3.0",
18
18
  "@fontsource-variable/geist-mono": "5.3.0",
19
19
  "better-call": "1.3.2",
@@ -21,7 +21,7 @@
21
21
  "react-dom": "^19.0.0"
22
22
  },
23
23
  "devDependencies": {
24
- "@farm.js/cli": "0.1.0-beta.34",
24
+ "@farm.js/cli": "0.1.0-beta.36",
25
25
  "@types/node": "20.19.9",
26
26
  "@types/react": "^19.0.0",
27
27
  "@types/react-dom": "^19.0.0",
@@ -10,14 +10,14 @@
10
10
  "type-check": "tsc --noEmit"
11
11
  },
12
12
  "dependencies": {
13
- "@farm.js/core": "0.1.0-beta.34",
13
+ "@farm.js/core": "0.1.0-beta.36",
14
14
  "@fontsource-variable/geist": "5.3.0",
15
15
  "@fontsource-variable/geist-mono": "5.3.0",
16
16
  "react": "^19.0.0",
17
17
  "react-dom": "^19.0.0"
18
18
  },
19
19
  "devDependencies": {
20
- "@farm.js/cli": "0.1.0-beta.34",
20
+ "@farm.js/cli": "0.1.0-beta.36",
21
21
  "@types/react": "^19.0.0",
22
22
  "@types/react-dom": "^19.0.0",
23
23
  "tailwindcss": "^4.0.0",
@@ -11,8 +11,8 @@
11
11
  "type-check": "tsc --noEmit"
12
12
  },
13
13
  "dependencies": {
14
- "@farm.js/better-auth": "0.1.0-beta.34",
15
- "@farm.js/core": "0.1.0-beta.34",
14
+ "@farm.js/better-auth": "0.1.0-beta.36",
15
+ "@farm.js/core": "0.1.0-beta.36",
16
16
  "@fontsource-variable/geist": "5.3.0",
17
17
  "@fontsource-variable/geist-mono": "5.3.0",
18
18
  "better-auth": "1.6.25",
@@ -22,7 +22,7 @@
22
22
  "react-dom": "^19.0.0"
23
23
  },
24
24
  "devDependencies": {
25
- "@farm.js/cli": "0.1.0-beta.34",
25
+ "@farm.js/cli": "0.1.0-beta.36",
26
26
  "@types/node": "20.19.9",
27
27
  "@types/pg": "8.20.0",
28
28
  "@types/react": "^19.0.0",
@@ -0,0 +1,62 @@
1
+ # FARMJS React Compiler Starter
2
+
3
+ A focused experimental starter for FARMJS's React AOT compiler. It uses the same minimal dark shell
4
+ as the other Create FARMJS App starters and includes one live comparison: an eligible local state
5
+ update beside ordinary React reconciliation.
6
+
7
+ > The compiler is experimental. Unsupported component shapes stay on React, so the optimization is
8
+ > never required for correctness.
9
+
10
+ ## Create this starter
11
+
12
+ ```bash
13
+ pnpm create @farm.js/app@beta my-compiler-app --template react-compiler --typescript
14
+ cd my-compiler-app
15
+ pnpm dev
16
+ ```
17
+
18
+ You can also clone the standalone
19
+ [farmjs-react-compiler-starter](https://github.com/farming-labs/farmjs-react-compiler-starter).
20
+
21
+ ## Compiler configuration
22
+
23
+ The starter enables the compiler through the React renderer:
24
+
25
+ ```ts
26
+ renderer: react({
27
+ experimental: {
28
+ compiler: true,
29
+ },
30
+ }),
31
+ ```
32
+
33
+ The included environment switch defaults to enabled and makes comparison builds easy:
34
+
35
+ ```bash
36
+ FARM_REACT_COMPILER=true pnpm build
37
+ FARM_REACT_COMPILER=false pnpm build
38
+ ```
39
+
40
+ The status shown on the starter page reflects the resolved value used for that build.
41
+
42
+ Components are considered automatically. Add `"use no compiler"` to a component when you need an
43
+ explicit React-only path.
44
+
45
+ ## Verify the compiled path
46
+
47
+ ```bash
48
+ pnpm install
49
+ pnpm exec playwright install chromium
50
+ pnpm experiment
51
+ ```
52
+
53
+ The command builds the app, opens the production output in Chromium, checks both counters, verifies
54
+ that the compiled update does not execute the component again, and saves a screenshot to
55
+ `/tmp/farm-react-compiler-starter.png`.
56
+
57
+ For batching, multiple bindings, safe keyed-list fallback, and the full compiler-on/off benchmark,
58
+ see the maintained
59
+ [React Compiler example](https://github.com/farming-labs/farm.js/tree/main/examples/react-compiler).
60
+
61
+ Read the [React compiler guide](https://farm.js.dev/docs/renderers/react#experimental-aot-compiler)
62
+ for the supported component contract and rollout guidance.
@@ -0,0 +1,23 @@
1
+ import { defineConfig } from "@farm.js/core";
2
+ import { react } from "@farm.js/react";
3
+
4
+ const compilerEnabled = process.env.FARM_REACT_COMPILER !== "false";
5
+
6
+ export default defineConfig({
7
+ env: {
8
+ public: {
9
+ FARM_REACT_COMPILER_ENABLED: () => compilerEnabled,
10
+ },
11
+ },
12
+ renderer: react({
13
+ experimental: {
14
+ compiler: compilerEnabled,
15
+ },
16
+ }),
17
+ theme: {
18
+ default: "dark",
19
+ },
20
+ deploy: {
21
+ target: "node",
22
+ },
23
+ });
@@ -0,0 +1,23 @@
1
+ # Dependencies
2
+ node_modules/
3
+
4
+ # Farm and deployment output
5
+ .farm/
6
+ .output/
7
+ .vercel/
8
+ dist/
9
+
10
+ # Local environment files
11
+ .env
12
+ .env.local
13
+ .env.*.local
14
+
15
+ # Local databases
16
+ *.sqlite
17
+ *.sqlite-*
18
+ *.db
19
+ *.db-*
20
+
21
+ # Logs and TypeScript cache
22
+ *.log
23
+ *.tsbuildinfo
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "farmjs-react-compiler-starter",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "farm dev",
8
+ "build": "farm build",
9
+ "start": "farm start",
10
+ "experiment": "pnpm run build && node scripts/verify-experiment.mjs",
11
+ "type-check": "tsc --noEmit"
12
+ },
13
+ "dependencies": {
14
+ "@farm.js/core": "0.1.0-beta.36",
15
+ "@farm.js/react": "0.1.0-beta.0",
16
+ "@fontsource-variable/geist": "5.3.0",
17
+ "@fontsource-variable/geist-mono": "5.3.0",
18
+ "react": "19.2.8",
19
+ "react-dom": "19.2.8"
20
+ },
21
+ "devDependencies": {
22
+ "@farm.js/cli": "0.1.0-beta.36",
23
+ "@playwright/test": "^1.52.0",
24
+ "@types/react": "^19.0.0",
25
+ "@types/react-dom": "^19.0.0",
26
+ "tailwindcss": "^4.0.0",
27
+ "typescript": "^5.3.3",
28
+ "vite": "^5.0.10"
29
+ },
30
+ "packageManager": "pnpm@8.12.1"
31
+ }
@@ -0,0 +1,8 @@
1
+ packages:
2
+ - "."
3
+
4
+ allowBuilds:
5
+ "@prisma/client": true
6
+ esbuild: true
7
+ sharp: true
8
+ vue-demi: true
@@ -0,0 +1,5 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-labelledby="title">
2
+ <title id="title">FARMJS React AOT</title>
3
+ <rect width="64" height="64" rx="14" fill="#0a0a09"/>
4
+ <path d="M18 16h30v8H28v8h17v8H28v16H18z" fill="#b8ff5b"/>
5
+ </svg>
@@ -0,0 +1,113 @@
1
+ import assert from "node:assert/strict";
2
+ import { spawn } from "node:child_process";
3
+ import { access } from "node:fs/promises";
4
+ import path from "node:path";
5
+ import { chromium } from "@playwright/test";
6
+
7
+ const port = Number(process.env.FARM_EXPERIMENT_PORT || 4327);
8
+ const origin = `http://127.0.0.1:${port}`;
9
+ const compilerEnabled = process.env.FARM_REACT_COMPILER !== "false";
10
+ const serverEntry = path.resolve(".farm/.output/server/index.mjs");
11
+ const screenshotPath =
12
+ process.env.FARM_EXPERIMENT_SCREENSHOT || "/tmp/farm-react-compiler-starter.png";
13
+
14
+ await access(serverEntry);
15
+
16
+ let serverOutput = "";
17
+ const server = spawn(process.execPath, [serverEntry], {
18
+ env: {
19
+ ...process.env,
20
+ HOST: "127.0.0.1",
21
+ NITRO_HOST: "127.0.0.1",
22
+ NITRO_PORT: String(port),
23
+ PORT: String(port),
24
+ },
25
+ stdio: ["ignore", "pipe", "pipe"],
26
+ });
27
+
28
+ server.stdout.on("data", (chunk) => {
29
+ serverOutput += chunk;
30
+ });
31
+ server.stderr.on("data", (chunk) => {
32
+ serverOutput += chunk;
33
+ });
34
+
35
+ async function waitForServer() {
36
+ for (let attempt = 0; attempt < 120; attempt += 1) {
37
+ if (server.exitCode !== null) {
38
+ throw new Error(`Production server exited early.\n${serverOutput}`);
39
+ }
40
+ try {
41
+ const response = await fetch(origin);
42
+ if (response.ok) return;
43
+ } catch {
44
+ // The server is still starting.
45
+ }
46
+ await new Promise((resolve) => setTimeout(resolve, 100));
47
+ }
48
+ throw new Error(`Production server did not start.\n${serverOutput}`);
49
+ }
50
+
51
+ async function readNumber(page, selector) {
52
+ return Number((await page.locator(selector).textContent())?.trim());
53
+ }
54
+
55
+ let browser;
56
+ try {
57
+ await waitForServer();
58
+ browser = await chromium.launch({ headless: true });
59
+ const page = await browser.newPage({ viewport: { width: 1280, height: 900 } });
60
+ const browserErrors = [];
61
+
62
+ page.on("console", (message) => {
63
+ if (message.type() === "error") browserErrors.push(message.text());
64
+ });
65
+ page.on("pageerror", (error) => browserErrors.push(error.message));
66
+
67
+ await page.goto(origin, { waitUntil: "networkidle" });
68
+ await page.getByRole("heading", { name: /compiler handles the rest/i }).waitFor();
69
+ assert.equal(
70
+ (await page.locator("[data-compiler-status]").textContent())?.trim(),
71
+ `experimental.compiler: ${String(compilerEnabled)}`,
72
+ );
73
+
74
+ const executions = {};
75
+ for (const pathName of ["compiled", "react"]) {
76
+ const root = `[data-path="${pathName}"]`;
77
+ executions[pathName] = {
78
+ initial: await readNumber(page, `${root} [data-metric="executions"]`),
79
+ };
80
+ await page.locator(`${root} [data-action="update"]`).click();
81
+ await page.locator(`${root} [data-action="update"]`).click();
82
+ await page.waitForFunction(
83
+ (selector) => document.querySelector(selector)?.textContent?.trim() === "2",
84
+ `${root} [data-metric="state"]`,
85
+ );
86
+ executions[pathName].final = await readNumber(page, `${root} [data-metric="executions"]`);
87
+ executions[pathName].added = executions[pathName].final - executions[pathName].initial;
88
+ }
89
+
90
+ assert.equal(executions.compiled.added, compilerEnabled ? 0 : 2);
91
+ assert.equal(executions.react.added, 2);
92
+ assert.deepEqual(browserErrors, []);
93
+
94
+ await page.screenshot({ path: screenshotPath, fullPage: true });
95
+
96
+ console.log(
97
+ JSON.stringify(
98
+ {
99
+ result: "PASS",
100
+ productionUrl: origin,
101
+ screenshot: screenshotPath,
102
+ compilerEnabled,
103
+ compiledUpdateExecutions: executions.compiled.added,
104
+ reactUpdateExecutions: executions.react.added,
105
+ },
106
+ null,
107
+ 2,
108
+ ),
109
+ );
110
+ } finally {
111
+ await browser?.close();
112
+ server.kill("SIGTERM");
113
+ }