@pylonsync/create-pylon 0.3.282 → 0.3.284

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 (61) hide show
  1. package/package.json +1 -1
  2. package/templates/agency/AGENTS.md +39 -0
  3. package/templates/agency/CLAUDE.md +7 -0
  4. package/templates/agency/package.json +2 -1
  5. package/templates/agency/tests/example.test.ts +12 -0
  6. package/templates/ai-chat/AGENTS.md +39 -0
  7. package/templates/ai-chat/CLAUDE.md +7 -0
  8. package/templates/ai-chat/package.json +2 -1
  9. package/templates/ai-chat/tests/example.test.ts +12 -0
  10. package/templates/ai-studio/AGENTS.md +39 -0
  11. package/templates/ai-studio/CLAUDE.md +7 -0
  12. package/templates/ai-studio/package.json +2 -1
  13. package/templates/ai-studio/tests/example.test.ts +12 -0
  14. package/templates/barebones/AGENTS.md +39 -0
  15. package/templates/barebones/CLAUDE.md +7 -0
  16. package/templates/barebones/package.json +2 -1
  17. package/templates/barebones/tests/example.test.ts +12 -0
  18. package/templates/chat/AGENTS.md +39 -0
  19. package/templates/chat/CLAUDE.md +7 -0
  20. package/templates/chat/package.json +2 -1
  21. package/templates/chat/tests/example.test.ts +12 -0
  22. package/templates/consumer/AGENTS.md +39 -0
  23. package/templates/consumer/CLAUDE.md +7 -0
  24. package/templates/consumer/package.json +2 -1
  25. package/templates/consumer/tests/example.test.ts +12 -0
  26. package/templates/creator/AGENTS.md +39 -0
  27. package/templates/creator/CLAUDE.md +7 -0
  28. package/templates/creator/package.json +2 -1
  29. package/templates/creator/tests/example.test.ts +12 -0
  30. package/templates/default/AGENTS.md +39 -0
  31. package/templates/default/CLAUDE.md +7 -0
  32. package/templates/default/package.json +2 -1
  33. package/templates/default/tests/example.test.ts +23 -0
  34. package/templates/directory/AGENTS.md +39 -0
  35. package/templates/directory/CLAUDE.md +7 -0
  36. package/templates/directory/package.json +2 -1
  37. package/templates/directory/tests/example.test.ts +12 -0
  38. package/templates/local-service/AGENTS.md +39 -0
  39. package/templates/local-service/CLAUDE.md +7 -0
  40. package/templates/local-service/package.json +2 -1
  41. package/templates/local-service/tests/example.test.ts +12 -0
  42. package/templates/marketplace/AGENTS.md +39 -0
  43. package/templates/marketplace/CLAUDE.md +7 -0
  44. package/templates/marketplace/package.json +2 -1
  45. package/templates/marketplace/tests/example.test.ts +12 -0
  46. package/templates/restaurant/AGENTS.md +39 -0
  47. package/templates/restaurant/CLAUDE.md +7 -0
  48. package/templates/restaurant/package.json +2 -1
  49. package/templates/restaurant/tests/example.test.ts +12 -0
  50. package/templates/shop/AGENTS.md +39 -0
  51. package/templates/shop/CLAUDE.md +7 -0
  52. package/templates/shop/package.json +2 -1
  53. package/templates/shop/tests/example.test.ts +12 -0
  54. package/templates/todo/AGENTS.md +39 -0
  55. package/templates/todo/CLAUDE.md +7 -0
  56. package/templates/todo/package.json +2 -1
  57. package/templates/todo/tests/example.test.ts +12 -0
  58. package/templates/waitlist/AGENTS.md +39 -0
  59. package/templates/waitlist/CLAUDE.md +7 -0
  60. package/templates/waitlist/package.json +2 -1
  61. package/templates/waitlist/tests/example.test.ts +12 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pylonsync/create-pylon",
3
- "version": "0.3.282",
3
+ "version": "0.3.284",
4
4
  "description": "Scaffold a new Pylon app — realtime backend + web/mobile/expo frontends in one command. Run via `npm create @pylonsync/pylon@latest`.",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -37,6 +37,45 @@ Operating rules for a coding agent in this Pylon app. Pylon is a Rails-like fram
37
37
  - **It's `db.useQueryOne`, not `useOne`.** Validators and field types have aliases: `v.bool`/`v.boolean`, `v.float`/`v.number`.
38
38
  - **There is no `ctx.files` or `defineWorkflow`/`defineJob`.** Files go through `<FileUpload>` + `/api/files/*`; deferred execution is `ctx.scheduler.runAfter/runAt/cancel`.
39
39
 
40
+ ## Testing
41
+
42
+ `pylon test` discovers every `*.test.ts` (or `.test.js`) file under `tests/` (or `functions/`) and runs it with **Bun's test runner** (`import { test, expect } from "bun:test"`) against an in-memory Pylon. Run the whole suite with `pylon test`, or `npm test`; filter with `pylon test <substring>`. A starter test ships in `tests/example.test.ts` — replace it with your own.
43
+
44
+ **Pure logic — no server needed.** Import the helper and assert. This is the cheapest, fastest shape; use it for validators, formatters, and data transforms.
45
+
46
+ ```ts
47
+ import { expect, test } from "bun:test";
48
+ import { productBySlug } from "../lib/site.config";
49
+
50
+ test("unknown slug → undefined", () => {
51
+ expect(productBySlug("nope")).toBeUndefined();
52
+ });
53
+ ```
54
+
55
+ **Functions + the database — over HTTP against a running dev server.** A function's real behavior (policies, `ctx.db`, auth) lives in the running app, so test it the way a client calls it: start `pylon dev` in another terminal, then hit the API. Use `resetDb()` from `@pylonsync/functions` to clear the in-memory DB between cases (no-ops safely if the server isn't up, and refuses to run against production).
56
+
57
+ ```ts
58
+ import { afterEach, expect, test } from "bun:test";
59
+ import { resetDb } from "@pylonsync/functions";
60
+
61
+ const BASE = "http://localhost:4321";
62
+ afterEach(() => resetDb(BASE)); // or installTestIsolation(BASE) once at top-of-file
63
+
64
+ test("createThing then it shows up", async () => {
65
+ const created = await fetch(`${BASE}/api/fn/createThing`, {
66
+ method: "POST",
67
+ headers: { "Content-Type": "application/json" },
68
+ body: JSON.stringify({ name: "hello" }),
69
+ }).then((r) => r.json());
70
+ expect(created.name).toBe("hello");
71
+
72
+ const rows = await fetch(`${BASE}/api/entities/Thing`).then((r) => r.json());
73
+ expect(rows.some((t: { id: string }) => t.id === created.id)).toBe(true);
74
+ });
75
+ ```
76
+
77
+ `pylon test:security` is a separate adversarial probe — it hits a running app and reports auth/policy holes (run `pylon dev`, then `pylon test:security`).
78
+
40
79
  ## Use the CLI — don't guess
41
80
 
42
81
  | Need | Command |
@@ -0,0 +1,7 @@
1
+ # CLAUDE.md
2
+
3
+ Agent guidance for this Pylon project lives in **AGENTS.md** — the cross-editor
4
+ standard that Claude Code, Cursor, Codex, and others all read. It's imported
5
+ below so Claude Code picks it up automatically:
6
+
7
+ @AGENTS.md
@@ -6,7 +6,8 @@
6
6
  "scripts": {
7
7
  "dev": "pylon dev",
8
8
  "deploy": "pylon deploy",
9
- "check": "tsc --noEmit"
9
+ "check": "tsc --noEmit",
10
+ "test": "pylon test"
10
11
  },
11
12
  "dependencies": {
12
13
  "@pylonsync/react": "^__PYLON_VERSION__",
@@ -0,0 +1,12 @@
1
+ import { expect, test } from "bun:test";
2
+
3
+ // Your first test. Run the suite with: pylon test (or: npm test)
4
+ //
5
+ // `pylon test` discovers every *.test.ts file under tests/ (or functions/) and
6
+ // runs it with Bun's test runner against an in-memory Pylon. Replace this
7
+ // placeholder with tests for your functions and helpers — see AGENTS.md →
8
+ // Testing for the pure-logic and HTTP-against-`pylon dev` patterns.
9
+
10
+ test("placeholder — replace me with a real test", () => {
11
+ expect(true).toBe(true);
12
+ });
@@ -37,6 +37,45 @@ Operating rules for a coding agent in this Pylon app. Pylon is a Rails-like fram
37
37
  - **It's `db.useQueryOne`, not `useOne`.** Validators and field types have aliases: `v.bool`/`v.boolean`, `v.float`/`v.number`.
38
38
  - **There is no `ctx.files` or `defineWorkflow`/`defineJob`.** Files go through `<FileUpload>` + `/api/files/*`; deferred execution is `ctx.scheduler.runAfter/runAt/cancel`.
39
39
 
40
+ ## Testing
41
+
42
+ `pylon test` discovers every `*.test.ts` (or `.test.js`) file under `tests/` (or `functions/`) and runs it with **Bun's test runner** (`import { test, expect } from "bun:test"`) against an in-memory Pylon. Run the whole suite with `pylon test`, or `npm test`; filter with `pylon test <substring>`. A starter test ships in `tests/example.test.ts` — replace it with your own.
43
+
44
+ **Pure logic — no server needed.** Import the helper and assert. This is the cheapest, fastest shape; use it for validators, formatters, and data transforms.
45
+
46
+ ```ts
47
+ import { expect, test } from "bun:test";
48
+ import { productBySlug } from "../lib/site.config";
49
+
50
+ test("unknown slug → undefined", () => {
51
+ expect(productBySlug("nope")).toBeUndefined();
52
+ });
53
+ ```
54
+
55
+ **Functions + the database — over HTTP against a running dev server.** A function's real behavior (policies, `ctx.db`, auth) lives in the running app, so test it the way a client calls it: start `pylon dev` in another terminal, then hit the API. Use `resetDb()` from `@pylonsync/functions` to clear the in-memory DB between cases (no-ops safely if the server isn't up, and refuses to run against production).
56
+
57
+ ```ts
58
+ import { afterEach, expect, test } from "bun:test";
59
+ import { resetDb } from "@pylonsync/functions";
60
+
61
+ const BASE = "http://localhost:4321";
62
+ afterEach(() => resetDb(BASE)); // or installTestIsolation(BASE) once at top-of-file
63
+
64
+ test("createThing then it shows up", async () => {
65
+ const created = await fetch(`${BASE}/api/fn/createThing`, {
66
+ method: "POST",
67
+ headers: { "Content-Type": "application/json" },
68
+ body: JSON.stringify({ name: "hello" }),
69
+ }).then((r) => r.json());
70
+ expect(created.name).toBe("hello");
71
+
72
+ const rows = await fetch(`${BASE}/api/entities/Thing`).then((r) => r.json());
73
+ expect(rows.some((t: { id: string }) => t.id === created.id)).toBe(true);
74
+ });
75
+ ```
76
+
77
+ `pylon test:security` is a separate adversarial probe — it hits a running app and reports auth/policy holes (run `pylon dev`, then `pylon test:security`).
78
+
40
79
  ## Use the CLI — don't guess
41
80
 
42
81
  | Need | Command |
@@ -0,0 +1,7 @@
1
+ # CLAUDE.md
2
+
3
+ Agent guidance for this Pylon project lives in **AGENTS.md** — the cross-editor
4
+ standard that Claude Code, Cursor, Codex, and others all read. It's imported
5
+ below so Claude Code picks it up automatically:
6
+
7
+ @AGENTS.md
@@ -6,7 +6,8 @@
6
6
  "scripts": {
7
7
  "dev": "pylon dev",
8
8
  "deploy": "pylon deploy",
9
- "check": "tsc --noEmit"
9
+ "check": "tsc --noEmit",
10
+ "test": "pylon test"
10
11
  },
11
12
  "dependencies": {
12
13
  "@pylonsync/react": "^__PYLON_VERSION__",
@@ -0,0 +1,12 @@
1
+ import { expect, test } from "bun:test";
2
+
3
+ // Your first test. Run the suite with: pylon test (or: npm test)
4
+ //
5
+ // `pylon test` discovers every *.test.ts file under tests/ (or functions/) and
6
+ // runs it with Bun's test runner against an in-memory Pylon. Replace this
7
+ // placeholder with tests for your functions and helpers — see AGENTS.md →
8
+ // Testing for the pure-logic and HTTP-against-`pylon dev` patterns.
9
+
10
+ test("placeholder — replace me with a real test", () => {
11
+ expect(true).toBe(true);
12
+ });
@@ -37,6 +37,45 @@ Operating rules for a coding agent in this Pylon app. Pylon is a Rails-like fram
37
37
  - **It's `db.useQueryOne`, not `useOne`.** Validators and field types have aliases: `v.bool`/`v.boolean`, `v.float`/`v.number`.
38
38
  - **There is no `ctx.files` or `defineWorkflow`/`defineJob`.** Files go through `<FileUpload>` + `/api/files/*`; deferred execution is `ctx.scheduler.runAfter/runAt/cancel`.
39
39
 
40
+ ## Testing
41
+
42
+ `pylon test` discovers every `*.test.ts` (or `.test.js`) file under `tests/` (or `functions/`) and runs it with **Bun's test runner** (`import { test, expect } from "bun:test"`) against an in-memory Pylon. Run the whole suite with `pylon test`, or `npm test`; filter with `pylon test <substring>`. A starter test ships in `tests/example.test.ts` — replace it with your own.
43
+
44
+ **Pure logic — no server needed.** Import the helper and assert. This is the cheapest, fastest shape; use it for validators, formatters, and data transforms.
45
+
46
+ ```ts
47
+ import { expect, test } from "bun:test";
48
+ import { productBySlug } from "../lib/site.config";
49
+
50
+ test("unknown slug → undefined", () => {
51
+ expect(productBySlug("nope")).toBeUndefined();
52
+ });
53
+ ```
54
+
55
+ **Functions + the database — over HTTP against a running dev server.** A function's real behavior (policies, `ctx.db`, auth) lives in the running app, so test it the way a client calls it: start `pylon dev` in another terminal, then hit the API. Use `resetDb()` from `@pylonsync/functions` to clear the in-memory DB between cases (no-ops safely if the server isn't up, and refuses to run against production).
56
+
57
+ ```ts
58
+ import { afterEach, expect, test } from "bun:test";
59
+ import { resetDb } from "@pylonsync/functions";
60
+
61
+ const BASE = "http://localhost:4321";
62
+ afterEach(() => resetDb(BASE)); // or installTestIsolation(BASE) once at top-of-file
63
+
64
+ test("createThing then it shows up", async () => {
65
+ const created = await fetch(`${BASE}/api/fn/createThing`, {
66
+ method: "POST",
67
+ headers: { "Content-Type": "application/json" },
68
+ body: JSON.stringify({ name: "hello" }),
69
+ }).then((r) => r.json());
70
+ expect(created.name).toBe("hello");
71
+
72
+ const rows = await fetch(`${BASE}/api/entities/Thing`).then((r) => r.json());
73
+ expect(rows.some((t: { id: string }) => t.id === created.id)).toBe(true);
74
+ });
75
+ ```
76
+
77
+ `pylon test:security` is a separate adversarial probe — it hits a running app and reports auth/policy holes (run `pylon dev`, then `pylon test:security`).
78
+
40
79
  ## Use the CLI — don't guess
41
80
 
42
81
  | Need | Command |
@@ -0,0 +1,7 @@
1
+ # CLAUDE.md
2
+
3
+ Agent guidance for this Pylon project lives in **AGENTS.md** — the cross-editor
4
+ standard that Claude Code, Cursor, Codex, and others all read. It's imported
5
+ below so Claude Code picks it up automatically:
6
+
7
+ @AGENTS.md
@@ -6,7 +6,8 @@
6
6
  "scripts": {
7
7
  "dev": "pylon dev",
8
8
  "deploy": "pylon deploy",
9
- "check": "tsc --noEmit"
9
+ "check": "tsc --noEmit",
10
+ "test": "pylon test"
10
11
  },
11
12
  "dependencies": {
12
13
  "@pylonsync/react": "^__PYLON_VERSION__",
@@ -0,0 +1,12 @@
1
+ import { expect, test } from "bun:test";
2
+
3
+ // Your first test. Run the suite with: pylon test (or: npm test)
4
+ //
5
+ // `pylon test` discovers every *.test.ts file under tests/ (or functions/) and
6
+ // runs it with Bun's test runner against an in-memory Pylon. Replace this
7
+ // placeholder with tests for your functions and helpers — see AGENTS.md →
8
+ // Testing for the pure-logic and HTTP-against-`pylon dev` patterns.
9
+
10
+ test("placeholder — replace me with a real test", () => {
11
+ expect(true).toBe(true);
12
+ });
@@ -37,6 +37,45 @@ Operating rules for a coding agent in this Pylon app. Pylon is a Rails-like fram
37
37
  - **It's `db.useQueryOne`, not `useOne`.** Validators and field types have aliases: `v.bool`/`v.boolean`, `v.float`/`v.number`.
38
38
  - **There is no `ctx.files` or `defineWorkflow`/`defineJob`.** Files go through `<FileUpload>` + `/api/files/*`; deferred execution is `ctx.scheduler.runAfter/runAt/cancel`.
39
39
 
40
+ ## Testing
41
+
42
+ `pylon test` discovers every `*.test.ts` (or `.test.js`) file under `tests/` (or `functions/`) and runs it with **Bun's test runner** (`import { test, expect } from "bun:test"`) against an in-memory Pylon. Run the whole suite with `pylon test`, or `npm test`; filter with `pylon test <substring>`. A starter test ships in `tests/example.test.ts` — replace it with your own.
43
+
44
+ **Pure logic — no server needed.** Import the helper and assert. This is the cheapest, fastest shape; use it for validators, formatters, and data transforms.
45
+
46
+ ```ts
47
+ import { expect, test } from "bun:test";
48
+ import { productBySlug } from "../lib/site.config";
49
+
50
+ test("unknown slug → undefined", () => {
51
+ expect(productBySlug("nope")).toBeUndefined();
52
+ });
53
+ ```
54
+
55
+ **Functions + the database — over HTTP against a running dev server.** A function's real behavior (policies, `ctx.db`, auth) lives in the running app, so test it the way a client calls it: start `pylon dev` in another terminal, then hit the API. Use `resetDb()` from `@pylonsync/functions` to clear the in-memory DB between cases (no-ops safely if the server isn't up, and refuses to run against production).
56
+
57
+ ```ts
58
+ import { afterEach, expect, test } from "bun:test";
59
+ import { resetDb } from "@pylonsync/functions";
60
+
61
+ const BASE = "http://localhost:4321";
62
+ afterEach(() => resetDb(BASE)); // or installTestIsolation(BASE) once at top-of-file
63
+
64
+ test("createThing then it shows up", async () => {
65
+ const created = await fetch(`${BASE}/api/fn/createThing`, {
66
+ method: "POST",
67
+ headers: { "Content-Type": "application/json" },
68
+ body: JSON.stringify({ name: "hello" }),
69
+ }).then((r) => r.json());
70
+ expect(created.name).toBe("hello");
71
+
72
+ const rows = await fetch(`${BASE}/api/entities/Thing`).then((r) => r.json());
73
+ expect(rows.some((t: { id: string }) => t.id === created.id)).toBe(true);
74
+ });
75
+ ```
76
+
77
+ `pylon test:security` is a separate adversarial probe — it hits a running app and reports auth/policy holes (run `pylon dev`, then `pylon test:security`).
78
+
40
79
  ## Use the CLI — don't guess
41
80
 
42
81
  | Need | Command |
@@ -0,0 +1,7 @@
1
+ # CLAUDE.md
2
+
3
+ Agent guidance for this Pylon project lives in **AGENTS.md** — the cross-editor
4
+ standard that Claude Code, Cursor, Codex, and others all read. It's imported
5
+ below so Claude Code picks it up automatically:
6
+
7
+ @AGENTS.md
@@ -6,7 +6,8 @@
6
6
  "scripts": {
7
7
  "dev": "pylon dev",
8
8
  "deploy": "pylon deploy",
9
- "check": "tsc --noEmit"
9
+ "check": "tsc --noEmit",
10
+ "test": "pylon test"
10
11
  },
11
12
  "dependencies": {
12
13
  "@pylonsync/react": "^__PYLON_VERSION__",
@@ -0,0 +1,12 @@
1
+ import { expect, test } from "bun:test";
2
+
3
+ // Your first test. Run the suite with: pylon test (or: npm test)
4
+ //
5
+ // `pylon test` discovers every *.test.ts file under tests/ (or functions/) and
6
+ // runs it with Bun's test runner against an in-memory Pylon. Replace this
7
+ // placeholder with tests for your functions and helpers — see AGENTS.md →
8
+ // Testing for the pure-logic and HTTP-against-`pylon dev` patterns.
9
+
10
+ test("placeholder — replace me with a real test", () => {
11
+ expect(true).toBe(true);
12
+ });
@@ -37,6 +37,45 @@ Operating rules for a coding agent in this Pylon app. Pylon is a Rails-like fram
37
37
  - **It's `db.useQueryOne`, not `useOne`.** Validators and field types have aliases: `v.bool`/`v.boolean`, `v.float`/`v.number`.
38
38
  - **There is no `ctx.files` or `defineWorkflow`/`defineJob`.** Files go through `<FileUpload>` + `/api/files/*`; deferred execution is `ctx.scheduler.runAfter/runAt/cancel`.
39
39
 
40
+ ## Testing
41
+
42
+ `pylon test` discovers every `*.test.ts` (or `.test.js`) file under `tests/` (or `functions/`) and runs it with **Bun's test runner** (`import { test, expect } from "bun:test"`) against an in-memory Pylon. Run the whole suite with `pylon test`, or `npm test`; filter with `pylon test <substring>`. A starter test ships in `tests/example.test.ts` — replace it with your own.
43
+
44
+ **Pure logic — no server needed.** Import the helper and assert. This is the cheapest, fastest shape; use it for validators, formatters, and data transforms.
45
+
46
+ ```ts
47
+ import { expect, test } from "bun:test";
48
+ import { productBySlug } from "../lib/site.config";
49
+
50
+ test("unknown slug → undefined", () => {
51
+ expect(productBySlug("nope")).toBeUndefined();
52
+ });
53
+ ```
54
+
55
+ **Functions + the database — over HTTP against a running dev server.** A function's real behavior (policies, `ctx.db`, auth) lives in the running app, so test it the way a client calls it: start `pylon dev` in another terminal, then hit the API. Use `resetDb()` from `@pylonsync/functions` to clear the in-memory DB between cases (no-ops safely if the server isn't up, and refuses to run against production).
56
+
57
+ ```ts
58
+ import { afterEach, expect, test } from "bun:test";
59
+ import { resetDb } from "@pylonsync/functions";
60
+
61
+ const BASE = "http://localhost:4321";
62
+ afterEach(() => resetDb(BASE)); // or installTestIsolation(BASE) once at top-of-file
63
+
64
+ test("createThing then it shows up", async () => {
65
+ const created = await fetch(`${BASE}/api/fn/createThing`, {
66
+ method: "POST",
67
+ headers: { "Content-Type": "application/json" },
68
+ body: JSON.stringify({ name: "hello" }),
69
+ }).then((r) => r.json());
70
+ expect(created.name).toBe("hello");
71
+
72
+ const rows = await fetch(`${BASE}/api/entities/Thing`).then((r) => r.json());
73
+ expect(rows.some((t: { id: string }) => t.id === created.id)).toBe(true);
74
+ });
75
+ ```
76
+
77
+ `pylon test:security` is a separate adversarial probe — it hits a running app and reports auth/policy holes (run `pylon dev`, then `pylon test:security`).
78
+
40
79
  ## Use the CLI — don't guess
41
80
 
42
81
  | Need | Command |
@@ -0,0 +1,7 @@
1
+ # CLAUDE.md
2
+
3
+ Agent guidance for this Pylon project lives in **AGENTS.md** — the cross-editor
4
+ standard that Claude Code, Cursor, Codex, and others all read. It's imported
5
+ below so Claude Code picks it up automatically:
6
+
7
+ @AGENTS.md
@@ -6,7 +6,8 @@
6
6
  "scripts": {
7
7
  "dev": "pylon dev",
8
8
  "deploy": "pylon deploy",
9
- "check": "tsc --noEmit"
9
+ "check": "tsc --noEmit",
10
+ "test": "pylon test"
10
11
  },
11
12
  "dependencies": {
12
13
  "@pylonsync/react": "^__PYLON_VERSION__",
@@ -0,0 +1,12 @@
1
+ import { expect, test } from "bun:test";
2
+
3
+ // Your first test. Run the suite with: pylon test (or: npm test)
4
+ //
5
+ // `pylon test` discovers every *.test.ts file under tests/ (or functions/) and
6
+ // runs it with Bun's test runner against an in-memory Pylon. Replace this
7
+ // placeholder with tests for your functions and helpers — see AGENTS.md →
8
+ // Testing for the pure-logic and HTTP-against-`pylon dev` patterns.
9
+
10
+ test("placeholder — replace me with a real test", () => {
11
+ expect(true).toBe(true);
12
+ });
@@ -37,6 +37,45 @@ Operating rules for a coding agent in this Pylon app. Pylon is a Rails-like fram
37
37
  - **It's `db.useQueryOne`, not `useOne`.** Validators and field types have aliases: `v.bool`/`v.boolean`, `v.float`/`v.number`.
38
38
  - **There is no `ctx.files` or `defineWorkflow`/`defineJob`.** Files go through `<FileUpload>` + `/api/files/*`; deferred execution is `ctx.scheduler.runAfter/runAt/cancel`.
39
39
 
40
+ ## Testing
41
+
42
+ `pylon test` discovers every `*.test.ts` (or `.test.js`) file under `tests/` (or `functions/`) and runs it with **Bun's test runner** (`import { test, expect } from "bun:test"`) against an in-memory Pylon. Run the whole suite with `pylon test`, or `npm test`; filter with `pylon test <substring>`. A starter test ships in `tests/example.test.ts` — replace it with your own.
43
+
44
+ **Pure logic — no server needed.** Import the helper and assert. This is the cheapest, fastest shape; use it for validators, formatters, and data transforms.
45
+
46
+ ```ts
47
+ import { expect, test } from "bun:test";
48
+ import { productBySlug } from "../lib/site.config";
49
+
50
+ test("unknown slug → undefined", () => {
51
+ expect(productBySlug("nope")).toBeUndefined();
52
+ });
53
+ ```
54
+
55
+ **Functions + the database — over HTTP against a running dev server.** A function's real behavior (policies, `ctx.db`, auth) lives in the running app, so test it the way a client calls it: start `pylon dev` in another terminal, then hit the API. Use `resetDb()` from `@pylonsync/functions` to clear the in-memory DB between cases (no-ops safely if the server isn't up, and refuses to run against production).
56
+
57
+ ```ts
58
+ import { afterEach, expect, test } from "bun:test";
59
+ import { resetDb } from "@pylonsync/functions";
60
+
61
+ const BASE = "http://localhost:4321";
62
+ afterEach(() => resetDb(BASE)); // or installTestIsolation(BASE) once at top-of-file
63
+
64
+ test("createThing then it shows up", async () => {
65
+ const created = await fetch(`${BASE}/api/fn/createThing`, {
66
+ method: "POST",
67
+ headers: { "Content-Type": "application/json" },
68
+ body: JSON.stringify({ name: "hello" }),
69
+ }).then((r) => r.json());
70
+ expect(created.name).toBe("hello");
71
+
72
+ const rows = await fetch(`${BASE}/api/entities/Thing`).then((r) => r.json());
73
+ expect(rows.some((t: { id: string }) => t.id === created.id)).toBe(true);
74
+ });
75
+ ```
76
+
77
+ `pylon test:security` is a separate adversarial probe — it hits a running app and reports auth/policy holes (run `pylon dev`, then `pylon test:security`).
78
+
40
79
  ## Use the CLI — don't guess
41
80
 
42
81
  | Need | Command |
@@ -0,0 +1,7 @@
1
+ # CLAUDE.md
2
+
3
+ Agent guidance for this Pylon project lives in **AGENTS.md** — the cross-editor
4
+ standard that Claude Code, Cursor, Codex, and others all read. It's imported
5
+ below so Claude Code picks it up automatically:
6
+
7
+ @AGENTS.md
@@ -6,7 +6,8 @@
6
6
  "scripts": {
7
7
  "dev": "pylon dev",
8
8
  "deploy": "pylon deploy",
9
- "check": "tsc --noEmit"
9
+ "check": "tsc --noEmit",
10
+ "test": "pylon test"
10
11
  },
11
12
  "dependencies": {
12
13
  "@pylonsync/react": "^__PYLON_VERSION__",
@@ -0,0 +1,12 @@
1
+ import { expect, test } from "bun:test";
2
+
3
+ // Your first test. Run the suite with: pylon test (or: npm test)
4
+ //
5
+ // `pylon test` discovers every *.test.ts file under tests/ (or functions/) and
6
+ // runs it with Bun's test runner against an in-memory Pylon. Replace this
7
+ // placeholder with tests for your functions and helpers — see AGENTS.md →
8
+ // Testing for the pure-logic and HTTP-against-`pylon dev` patterns.
9
+
10
+ test("placeholder — replace me with a real test", () => {
11
+ expect(true).toBe(true);
12
+ });
@@ -37,6 +37,45 @@ Operating rules for a coding agent in this Pylon app. Pylon is a Rails-like fram
37
37
  - **It's `db.useQueryOne`, not `useOne`.** Validators and field types have aliases: `v.bool`/`v.boolean`, `v.float`/`v.number`.
38
38
  - **There is no `ctx.files` or `defineWorkflow`/`defineJob`.** Files go through `<FileUpload>` + `/api/files/*`; deferred execution is `ctx.scheduler.runAfter/runAt/cancel`.
39
39
 
40
+ ## Testing
41
+
42
+ `pylon test` discovers every `*.test.ts` (or `.test.js`) file under `tests/` (or `functions/`) and runs it with **Bun's test runner** (`import { test, expect } from "bun:test"`) against an in-memory Pylon. Run the whole suite with `pylon test`, or `npm test`; filter with `pylon test <substring>`. A starter test ships in `tests/example.test.ts` — replace it with your own.
43
+
44
+ **Pure logic — no server needed.** Import the helper and assert. This is the cheapest, fastest shape; use it for validators, formatters, and data transforms.
45
+
46
+ ```ts
47
+ import { expect, test } from "bun:test";
48
+ import { productBySlug } from "../lib/site.config";
49
+
50
+ test("unknown slug → undefined", () => {
51
+ expect(productBySlug("nope")).toBeUndefined();
52
+ });
53
+ ```
54
+
55
+ **Functions + the database — over HTTP against a running dev server.** A function's real behavior (policies, `ctx.db`, auth) lives in the running app, so test it the way a client calls it: start `pylon dev` in another terminal, then hit the API. Use `resetDb()` from `@pylonsync/functions` to clear the in-memory DB between cases (no-ops safely if the server isn't up, and refuses to run against production).
56
+
57
+ ```ts
58
+ import { afterEach, expect, test } from "bun:test";
59
+ import { resetDb } from "@pylonsync/functions";
60
+
61
+ const BASE = "http://localhost:4321";
62
+ afterEach(() => resetDb(BASE)); // or installTestIsolation(BASE) once at top-of-file
63
+
64
+ test("createThing then it shows up", async () => {
65
+ const created = await fetch(`${BASE}/api/fn/createThing`, {
66
+ method: "POST",
67
+ headers: { "Content-Type": "application/json" },
68
+ body: JSON.stringify({ name: "hello" }),
69
+ }).then((r) => r.json());
70
+ expect(created.name).toBe("hello");
71
+
72
+ const rows = await fetch(`${BASE}/api/entities/Thing`).then((r) => r.json());
73
+ expect(rows.some((t: { id: string }) => t.id === created.id)).toBe(true);
74
+ });
75
+ ```
76
+
77
+ `pylon test:security` is a separate adversarial probe — it hits a running app and reports auth/policy holes (run `pylon dev`, then `pylon test:security`).
78
+
40
79
  ## Use the CLI — don't guess
41
80
 
42
81
  | Need | Command |
@@ -0,0 +1,7 @@
1
+ # CLAUDE.md
2
+
3
+ Agent guidance for this Pylon project lives in **AGENTS.md** — the cross-editor
4
+ standard that Claude Code, Cursor, Codex, and others all read. It's imported
5
+ below so Claude Code picks it up automatically:
6
+
7
+ @AGENTS.md
@@ -6,7 +6,8 @@
6
6
  "scripts": {
7
7
  "dev": "pylon dev",
8
8
  "deploy": "pylon deploy",
9
- "check": "tsc --noEmit"
9
+ "check": "tsc --noEmit",
10
+ "test": "pylon test"
10
11
  },
11
12
  "dependencies": {
12
13
  "@pylonsync/react": "^__PYLON_VERSION__",
@@ -0,0 +1,12 @@
1
+ import { expect, test } from "bun:test";
2
+
3
+ // Your first test. Run the suite with: pylon test (or: npm test)
4
+ //
5
+ // `pylon test` discovers every *.test.ts file under tests/ (or functions/) and
6
+ // runs it with Bun's test runner against an in-memory Pylon. Replace this
7
+ // placeholder with tests for your functions and helpers — see AGENTS.md →
8
+ // Testing for the pure-logic and HTTP-against-`pylon dev` patterns.
9
+
10
+ test("placeholder — replace me with a real test", () => {
11
+ expect(true).toBe(true);
12
+ });
@@ -37,6 +37,45 @@ Operating rules for a coding agent in this Pylon app. Pylon is a Rails-like fram
37
37
  - **It's `db.useQueryOne`, not `useOne`.** Validators and field types have aliases: `v.bool`/`v.boolean`, `v.float`/`v.number`.
38
38
  - **There is no `ctx.files` or `defineWorkflow`/`defineJob`.** Files go through `<FileUpload>` + `/api/files/*`; deferred execution is `ctx.scheduler.runAfter/runAt/cancel`.
39
39
 
40
+ ## Testing
41
+
42
+ `pylon test` discovers every `*.test.ts` (or `.test.js`) file under `tests/` (or `functions/`) and runs it with **Bun's test runner** (`import { test, expect } from "bun:test"`) against an in-memory Pylon. Run the whole suite with `pylon test`, or `npm test`; filter with `pylon test <substring>`. A starter test ships in `tests/example.test.ts` — replace it with your own.
43
+
44
+ **Pure logic — no server needed.** Import the helper and assert. This is the cheapest, fastest shape; use it for validators, formatters, and data transforms.
45
+
46
+ ```ts
47
+ import { expect, test } from "bun:test";
48
+ import { productBySlug } from "../lib/site.config";
49
+
50
+ test("unknown slug → undefined", () => {
51
+ expect(productBySlug("nope")).toBeUndefined();
52
+ });
53
+ ```
54
+
55
+ **Functions + the database — over HTTP against a running dev server.** A function's real behavior (policies, `ctx.db`, auth) lives in the running app, so test it the way a client calls it: start `pylon dev` in another terminal, then hit the API. Use `resetDb()` from `@pylonsync/functions` to clear the in-memory DB between cases (no-ops safely if the server isn't up, and refuses to run against production).
56
+
57
+ ```ts
58
+ import { afterEach, expect, test } from "bun:test";
59
+ import { resetDb } from "@pylonsync/functions";
60
+
61
+ const BASE = "http://localhost:4321";
62
+ afterEach(() => resetDb(BASE)); // or installTestIsolation(BASE) once at top-of-file
63
+
64
+ test("createThing then it shows up", async () => {
65
+ const created = await fetch(`${BASE}/api/fn/createThing`, {
66
+ method: "POST",
67
+ headers: { "Content-Type": "application/json" },
68
+ body: JSON.stringify({ name: "hello" }),
69
+ }).then((r) => r.json());
70
+ expect(created.name).toBe("hello");
71
+
72
+ const rows = await fetch(`${BASE}/api/entities/Thing`).then((r) => r.json());
73
+ expect(rows.some((t: { id: string }) => t.id === created.id)).toBe(true);
74
+ });
75
+ ```
76
+
77
+ `pylon test:security` is a separate adversarial probe — it hits a running app and reports auth/policy holes (run `pylon dev`, then `pylon test:security`).
78
+
40
79
  ## Use the CLI — don't guess
41
80
 
42
81
  | Need | Command |
@@ -0,0 +1,7 @@
1
+ # CLAUDE.md
2
+
3
+ Agent guidance for this Pylon project lives in **AGENTS.md** — the cross-editor
4
+ standard that Claude Code, Cursor, Codex, and others all read. It's imported
5
+ below so Claude Code picks it up automatically:
6
+
7
+ @AGENTS.md
@@ -6,7 +6,8 @@
6
6
  "scripts": {
7
7
  "dev": "pylon dev",
8
8
  "deploy": "pylon deploy",
9
- "check": "tsc --noEmit"
9
+ "check": "tsc --noEmit",
10
+ "test": "pylon test"
10
11
  },
11
12
  "dependencies": {
12
13
  "@pylonsync/react": "^__PYLON_VERSION__",