@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.
- package/package.json +1 -1
- package/templates/agency/AGENTS.md +39 -0
- package/templates/agency/CLAUDE.md +7 -0
- package/templates/agency/package.json +2 -1
- package/templates/agency/tests/example.test.ts +12 -0
- package/templates/ai-chat/AGENTS.md +39 -0
- package/templates/ai-chat/CLAUDE.md +7 -0
- package/templates/ai-chat/package.json +2 -1
- package/templates/ai-chat/tests/example.test.ts +12 -0
- package/templates/ai-studio/AGENTS.md +39 -0
- package/templates/ai-studio/CLAUDE.md +7 -0
- package/templates/ai-studio/package.json +2 -1
- package/templates/ai-studio/tests/example.test.ts +12 -0
- package/templates/barebones/AGENTS.md +39 -0
- package/templates/barebones/CLAUDE.md +7 -0
- package/templates/barebones/package.json +2 -1
- package/templates/barebones/tests/example.test.ts +12 -0
- package/templates/chat/AGENTS.md +39 -0
- package/templates/chat/CLAUDE.md +7 -0
- package/templates/chat/package.json +2 -1
- package/templates/chat/tests/example.test.ts +12 -0
- package/templates/consumer/AGENTS.md +39 -0
- package/templates/consumer/CLAUDE.md +7 -0
- package/templates/consumer/package.json +2 -1
- package/templates/consumer/tests/example.test.ts +12 -0
- package/templates/creator/AGENTS.md +39 -0
- package/templates/creator/CLAUDE.md +7 -0
- package/templates/creator/package.json +2 -1
- package/templates/creator/tests/example.test.ts +12 -0
- package/templates/default/AGENTS.md +39 -0
- package/templates/default/CLAUDE.md +7 -0
- package/templates/default/package.json +2 -1
- package/templates/default/tests/example.test.ts +23 -0
- package/templates/directory/AGENTS.md +39 -0
- package/templates/directory/CLAUDE.md +7 -0
- package/templates/directory/package.json +2 -1
- package/templates/directory/tests/example.test.ts +12 -0
- package/templates/local-service/AGENTS.md +39 -0
- package/templates/local-service/CLAUDE.md +7 -0
- package/templates/local-service/package.json +2 -1
- package/templates/local-service/tests/example.test.ts +12 -0
- package/templates/marketplace/AGENTS.md +39 -0
- package/templates/marketplace/CLAUDE.md +7 -0
- package/templates/marketplace/package.json +2 -1
- package/templates/marketplace/tests/example.test.ts +12 -0
- package/templates/restaurant/AGENTS.md +39 -0
- package/templates/restaurant/CLAUDE.md +7 -0
- package/templates/restaurant/package.json +2 -1
- package/templates/restaurant/tests/example.test.ts +12 -0
- package/templates/shop/AGENTS.md +39 -0
- package/templates/shop/CLAUDE.md +7 -0
- package/templates/shop/package.json +2 -1
- package/templates/shop/tests/example.test.ts +12 -0
- package/templates/todo/AGENTS.md +39 -0
- package/templates/todo/CLAUDE.md +7 -0
- package/templates/todo/package.json +2 -1
- package/templates/todo/tests/example.test.ts +12 -0
- package/templates/waitlist/AGENTS.md +39 -0
- package/templates/waitlist/CLAUDE.md +7 -0
- package/templates/waitlist/package.json +2 -1
- 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.
|
|
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,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,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,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,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
|
+
});
|
package/templates/chat/AGENTS.md
CHANGED
|
@@ -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,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,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,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 |
|