@ripplo/testing 0.7.9 → 0.7.11
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/DSL.md +66 -32
- package/dist/{engine-BfvzXgLg.d.ts → engine-Dv3trweR.d.ts} +249 -45
- package/dist/express.d.ts +1 -1
- package/dist/express.js +45 -21
- package/dist/index.d.ts +10 -10
- package/dist/index.js +649 -85
- package/package.json +3 -3
package/DSL.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# Ripplo DSL reference
|
|
2
2
|
|
|
3
|
-
The complete primitive catalog for `@ripplo/testing`. The `/ripplo:create` skill covers the
|
|
3
|
+
The complete primitive catalog for `@ripplo/testing`. The `/ripplo:create` skill covers the authoring flow and the model; this is the exhaustive "what exists" — every action, locator, assertion, and field axis with a signature and a one-line example.
|
|
4
4
|
|
|
5
5
|
A project has four layers:
|
|
6
6
|
|
|
7
7
|
- **Entities** (`.ripplo/entities/`) — the state model. Each entity gets a `seed`/`read` impl in the app's engine funnel.
|
|
8
|
-
- **Singletons** (`.ripplo/singletons/`) —
|
|
8
|
+
- **Singletons** (`.ripplo/singletons/`) — single app-wide values. Like entities, each has a `source` ("backend" or "client").
|
|
9
9
|
- **Worlds** (`.ripplo/worlds/`) — pure builder functions returning a flat record of entity handles (the starting state).
|
|
10
|
-
- **
|
|
10
|
+
- **Workflows** (`.ripplo/workflows/`) — `workflow("Intent", () => ({ given, steps }))`. The compiler enumerates concrete tests from each workflow.
|
|
11
11
|
|
|
12
12
|
Everything is imported from `@ripplo/testing`.
|
|
13
13
|
|
|
@@ -27,7 +27,7 @@ export const Task = entity("task", {
|
|
|
27
27
|
note: field({ optional: true, value: v.word() }), // nullable
|
|
28
28
|
},
|
|
29
29
|
identity: { id: id() },
|
|
30
|
-
source: "backend", // "backend" (
|
|
30
|
+
source: "backend", // "backend" (server-side) or "client" (browser-side)
|
|
31
31
|
});
|
|
32
32
|
```
|
|
33
33
|
|
|
@@ -38,7 +38,7 @@ export const Task = entity("task", {
|
|
|
38
38
|
Pick by where the state is persisted, not where it's displayed:
|
|
39
39
|
|
|
40
40
|
- `source: "backend"` — the default for anything long-lived: database rows, server-side session state, anything that survives a page reload because the server has it. Seeded/read by the **server engine** (`createEngine` in your app's `test/engine.ts`).
|
|
41
|
-
- `source: "client"` — state that lives only in the browser: localStorage, IndexedDB, in-memory stores that the app treats as state but never persists server-side. Seeded/read by the **client engine** (`mountClientEngine`, below). Reach for it when a flow's behavior depends on browser-local state you need to
|
|
41
|
+
- `source: "client"` — state that lives only in the browser: localStorage, IndexedDB, in-memory stores that the app treats as state but never persists server-side. Seeded/read by the **client engine** (`mountClientEngine`, below). Reach for it when a flow's behavior depends on browser-local state you need to seed or assert.
|
|
42
42
|
|
|
43
43
|
If you're unsure, it's backend. A value that's cached in the browser but owned by the server is backend — model the server's row, not the cache.
|
|
44
44
|
|
|
@@ -47,16 +47,16 @@ If you're unsure, it's backend. A value that's cached in the browser but owned b
|
|
|
47
47
|
### `field(options)`
|
|
48
48
|
|
|
49
49
|
```ts
|
|
50
|
-
field({ value: v.email() }); // required, stable
|
|
50
|
+
field({ value: v.email() }); // required, stable — Ripplo checks the app's value matches what the test expected
|
|
51
51
|
field({ value: v.word(), optional: true }); // nullable; `null` is a valid set/assert value
|
|
52
52
|
field({ value: v.number({ min: 0, max: 100 }), stable: false }); // adopt-only, drift not checked
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
-
| option | meaning
|
|
56
|
-
| ---------- |
|
|
57
|
-
| `value` | the value-space (`v.*`) — required
|
|
58
|
-
| `optional` | `true` ⇒ the field is nullable (`null` allowed in `of`/`updated`/assertions);
|
|
59
|
-
| `stable` | default `true` (
|
|
55
|
+
| option | meaning |
|
|
56
|
+
| ---------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
57
|
+
| `value` | the value-space (`v.*`) — required |
|
|
58
|
+
| `optional` | `true` ⇒ the field is nullable (`null` allowed in `of`/`updated`/assertions); Ripplo treats `null ≡ absent` |
|
|
59
|
+
| `stable` | default `true` (Ripplo checks the app's value matches what the test expected). `false` = adopt-only, drift unchecked |
|
|
60
60
|
|
|
61
61
|
### Identity: `id()` and `key(options)`
|
|
62
62
|
|
|
@@ -85,7 +85,7 @@ identity: {
|
|
|
85
85
|
| `v.oneOf([...])` | any | enum — one of the listed values |
|
|
86
86
|
| `v.datetime({ offsetDays: { min, max } })` | string | ISO-8601 timestamp, offset days relative to the run's start |
|
|
87
87
|
|
|
88
|
-
String spaces take optional constraints: `v.word({ minLength, maxLength, pattern })`. `v.number` requires `{ min, max }`. `v.oneOf` types narrowly with `as const`-style tuples: `v.oneOf(["PENDING", "ACCEPTED"])`. `v.datetime` values are generated relative to the run's start timestamp (e.g. `{ min: -30, max: 1 }` = up to 30 days past, 1 day future);
|
|
88
|
+
String spaces take optional constraints: `v.word({ minLength, maxLength, pattern })`. `v.number` requires `{ min, max }`. `v.oneOf` types narrowly with `as const`-style tuples: `v.oneOf(["PENDING", "ACCEPTED"])`. `v.datetime` values are generated relative to the run's start timestamp (e.g. `{ min: -30, max: 1 }` = up to 30 days past, 1 day future); Ripplo compares datetimes by UTC instant, so driver formatting/timezone rendering differences never cause a mismatch.
|
|
89
89
|
|
|
90
90
|
---
|
|
91
91
|
|
|
@@ -116,7 +116,7 @@ export const projectWithTask = () => {
|
|
|
116
116
|
| --------------------- | --------------------------------------------------------------------------------------- |
|
|
117
117
|
| `Entity.of(props)` | a row that is **guaranteed** present |
|
|
118
118
|
| `Entity.only(props)` | exactly one such row (singleton in the world) |
|
|
119
|
-
| `Entity.maybe(props)` | optionally present
|
|
119
|
+
| `Entity.maybe(props)` | optionally present — a compile-time degree of freedom the compiler solves per test |
|
|
120
120
|
| `Entity.none(where)` | asserts **absence** — no row matches (returns an absence handle; include it in `given`) |
|
|
121
121
|
|
|
122
122
|
- `arbitrary(Entity.field.x)` — draws a fresh value for field `x`. A fresh param each call.
|
|
@@ -126,17 +126,17 @@ export const projectWithTask = () => {
|
|
|
126
126
|
|
|
127
127
|
---
|
|
128
128
|
|
|
129
|
-
##
|
|
129
|
+
## Workflows
|
|
130
130
|
|
|
131
131
|
```ts
|
|
132
|
-
import { button, click, fill, goto,
|
|
132
|
+
import { button, click, fill, goto, textbox, visible, workflow } from "@ripplo/testing";
|
|
133
133
|
import { Task } from "../entities/index.js";
|
|
134
134
|
import { ownedProject } from "../worlds/index.js";
|
|
135
135
|
|
|
136
|
-
export const createTask =
|
|
136
|
+
export const createTask = workflow("Create a task", () => {
|
|
137
137
|
const { me, project } = ownedProject();
|
|
138
138
|
return {
|
|
139
|
-
given: [me, project], //
|
|
139
|
+
given: [me, project], // setup: all the handles this workflow needs
|
|
140
140
|
steps: [
|
|
141
141
|
// act + assert
|
|
142
142
|
goto`/projects/${project.id}/tasks`.expect(visible(button("New"))),
|
|
@@ -147,18 +147,23 @@ export const createTask = test("Create a task", () => {
|
|
|
147
147
|
};
|
|
148
148
|
});
|
|
149
149
|
|
|
150
|
-
export const renameTask =
|
|
150
|
+
export const renameTask = workflow("Rename a task"); // STUB — no body; gated until implemented
|
|
151
151
|
```
|
|
152
152
|
|
|
153
|
-
- `
|
|
154
|
-
- The
|
|
153
|
+
- `workflow(intent)` (no body) → a **stub**; `workflow(intent, () => body)` → an implemented workflow.
|
|
154
|
+
- The workflow body returns `{ given, steps }`. The setup/act boundary is `given:` vs `steps:`.
|
|
155
155
|
- Everything a step references must trace to a handle in `given`.
|
|
156
|
+
- Register workflows in `.ripplo/workflows/index.ts` (exports `workflows`); the funnel is `createRipplo({ entities, singletons, workflows })`.
|
|
157
|
+
|
|
158
|
+
### Workflows compile to tests
|
|
159
|
+
|
|
160
|
+
The compiler enumerates one concrete test per `when` branch at `ripplo compile`/`lint` time — a covering set across all when blocks. Each test gets a solved seed: the compiler picks which `maybe(...)` entities to seed and pins `arbitrary()` singleton values so the branch's condition holds after the steps' declared effects. A workflow with no when blocks compiles to a single test named "main". A branch no seed can reach is a compile error ("branch X is unreachable") — fix the condition or widen the world with maybe entities. The solver caps candidate seeds at 4096 (maybe subsets × singleton pin combinations) — past that it errors with "too many optional entities and singleton values to solve", so split the workflow or convert `maybe(...)` entities to `of(...)`. Runs are per test. `maybe()` entities are compile-time degrees of freedom, never randomly chosen at run time.
|
|
156
161
|
|
|
157
162
|
---
|
|
158
163
|
|
|
159
164
|
## Actions
|
|
160
165
|
|
|
161
|
-
Each returns a step; chain `.expect(...
|
|
166
|
+
Each returns a step; chain `.expect(...assertions)` to assert after it runs.
|
|
162
167
|
|
|
163
168
|
| action | signature | example |
|
|
164
169
|
| ---------- | ------------------------------ | ---------------------------------------- |
|
|
@@ -217,11 +222,11 @@ click(inside(main(), button("New"))); // disambiguate from a header CTA
|
|
|
217
222
|
|
|
218
223
|
---
|
|
219
224
|
|
|
220
|
-
##
|
|
225
|
+
## UI assertions
|
|
221
226
|
|
|
222
227
|
Used inside a step's `.expect(...)`.
|
|
223
228
|
|
|
224
|
-
|
|
|
229
|
+
| assertion | signature | asserts |
|
|
225
230
|
| ---------- | --------------------------------- | ----------------------------------------- |
|
|
226
231
|
| `visible` | `visible(locator)` | element is visible |
|
|
227
232
|
| `disabled` | `disabled(locator)` | element is disabled |
|
|
@@ -229,11 +234,38 @@ Used inside a step's `.expect(...)`.
|
|
|
229
234
|
| `focused` | `focused(locator)` | element has focus |
|
|
230
235
|
| `value` | `value(locator, string\|binding)` | input's value equals |
|
|
231
236
|
| `text` | `text(locator, string\|binding)` | element's text equals |
|
|
232
|
-
| `not` | `not(
|
|
237
|
+
| `not` | `not(assertion)` | negation — `not(visible(role("dialog")))` |
|
|
233
238
|
| `and` | `and(...conditions)` | conjunction |
|
|
234
|
-
| `when` | `when(...
|
|
239
|
+
| `when` | `when(...branches)` | named conditional branches (below) |
|
|
235
240
|
| `count` | `count(Entity).is(n)` | n rows of the entity exist |
|
|
236
241
|
|
|
242
|
+
### `when` — named branches
|
|
243
|
+
|
|
244
|
+
`when` takes `branch(...)` builders. Each branch names a scenario, optionally guards it with `.if(condition)`, and asserts with `.expect(...assertions)`:
|
|
245
|
+
|
|
246
|
+
```ts
|
|
247
|
+
when(
|
|
248
|
+
branch("deleting the last project")
|
|
249
|
+
.if(count(Project).is(0))
|
|
250
|
+
.expect(url.is`/connect`),
|
|
251
|
+
branch("deleting the first project, onboarding pending")
|
|
252
|
+
.if(and(count(Project).is(1), onboardingDismissed.is(false)))
|
|
253
|
+
.expect(url.is`/onboarding?projectId=${other.id}`),
|
|
254
|
+
branch("deleting one of several projects").expect(url.is`/projects`),
|
|
255
|
+
);
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Rules:
|
|
259
|
+
|
|
260
|
+
- Every branch is named.
|
|
261
|
+
- At most one unconditional branch, and it must be last.
|
|
262
|
+
- Names are unique within a workflow.
|
|
263
|
+
- No nested whens — a `when` inside a branch's `.expect(...)` is an error ("whens are one level deep"). A scenario that wants a second level is its own workflow.
|
|
264
|
+
|
|
265
|
+
The name labels the test, not the condition — describe the scenario from the user's point of view, including the state that drives the different outcome. Two failure modes to avoid: post-state names ("no projects left" describes the result, not the scenario) and seed-mechanics names ("first project, onboarding pending" describes how the world was built). Test: it should read as a sentence under the workflow name, and someone seeing the name as a failed-test label should know which situation broke. "Delete project → deleting the last project" works. "Delete project → deleting a project when the remaining project still needs onboarding" works. "Delete project → no projects left" and "Delete project → first project, onboarding pending" do not.
|
|
266
|
+
|
|
267
|
+
The compiler enumerates one test per branch (see "Workflows compile to tests" above).
|
|
268
|
+
|
|
237
269
|
### Browser singletons
|
|
238
270
|
|
|
239
271
|
```ts
|
|
@@ -243,9 +275,9 @@ goto`/projects/${p.id}`.expect(url.is`/projects/${p.id}`); // url/title/viewport
|
|
|
243
275
|
|
|
244
276
|
---
|
|
245
277
|
|
|
246
|
-
## Backend assertions
|
|
278
|
+
## Backend assertions — Ripplo verifies backend state
|
|
247
279
|
|
|
248
|
-
Put these in a step's `.expect(...)` alongside UI
|
|
280
|
+
Put these in a step's `.expect(...)` alongside UI assertions. After each step Ripplo compares your app's state against what the test declared and flags any mismatch — you never poll.
|
|
249
281
|
|
|
250
282
|
```ts
|
|
251
283
|
import { changed, within } from "@ripplo/testing";
|
|
@@ -259,7 +291,7 @@ Task.deleted({ id: task.id }); // the keyed row is gone
|
|
|
259
291
|
- `Entity.created(props)` — assert a creation.
|
|
260
292
|
- `Entity.updated(key, changes)` — assert an update on the row matching `key`. Use `changed()` as a value when the new value is server-chosen (assert it _differs_ without pinning it).
|
|
261
293
|
- `Entity.deleted(key)` — assert deletion.
|
|
262
|
-
- Consistency timing is automatic:
|
|
294
|
+
- Consistency timing is automatic: `strict` (the default) means the field must match immediately and fails fast on a wrong intermediate value, `consistency: "eventual"` (or a `changed()` baseline) means it may lag briefly and Ripplo waits for it.
|
|
263
295
|
|
|
264
296
|
### Relational selection (`where` / `within`)
|
|
265
297
|
|
|
@@ -275,7 +307,9 @@ Task.deleted({ projectId: within(Project.where({ ownerId: me.id }), "id") }); //
|
|
|
275
307
|
|
|
276
308
|
---
|
|
277
309
|
|
|
278
|
-
## Singletons (
|
|
310
|
+
## Singletons (single app-wide values)
|
|
311
|
+
|
|
312
|
+
A singleton is one app-wide value, where an entity has rows. Like entities, it has a `source` — `"backend"` (seeded/read by the server engine) or `"client"` (seeded/read by the client engine).
|
|
279
313
|
|
|
280
314
|
```ts
|
|
281
315
|
import { singleton, v } from "@ripplo/testing";
|
|
@@ -290,7 +324,7 @@ export const onboardingDismissed = singleton("onboardingDismissed", {
|
|
|
290
324
|
export const singletons = [onboardingDismissed];
|
|
291
325
|
```
|
|
292
326
|
|
|
293
|
-
Set in a
|
|
327
|
+
Set in a workflow's body (`singletons:`) and assert via UI assertions. The engine matching the singleton's source seeds and reads it.
|
|
294
328
|
|
|
295
329
|
### The client engine
|
|
296
330
|
|
|
@@ -353,5 +387,5 @@ export const engine = createEngine(ripplo, { entities: impls, singletons: {} },
|
|
|
353
387
|
```
|
|
354
388
|
|
|
355
389
|
- **`seed`** creates one row from `fields`, returns `{ row, session }` (`session` = an auth session for identity entities like `user`/`session`, else `undefined`).
|
|
356
|
-
- **`read`** returns this run's rows of the entity. Scope every query by the run so
|
|
357
|
-
- Isolation lives here, not in the
|
|
390
|
+
- **`read`** returns this run's rows of the entity. Scope every query by the run so Ripplo only sees this run's data.
|
|
391
|
+
- Isolation lives here, not in the workflow: run-scoped ids in `seed`, run-scoped queries in `read`. Never `update`/`delete` rows your run didn't create.
|
|
@@ -237,6 +237,11 @@ interface Within {
|
|
|
237
237
|
readonly selection: Selection$1;
|
|
238
238
|
}
|
|
239
239
|
type WhereValue = SetValue | Within;
|
|
240
|
+
interface WhenBranch {
|
|
241
|
+
readonly condition: Condition | undefined;
|
|
242
|
+
readonly consequence: Predicate;
|
|
243
|
+
readonly name: string;
|
|
244
|
+
}
|
|
240
245
|
type Predicate = {
|
|
241
246
|
readonly kind: "visible";
|
|
242
247
|
readonly locator: Locator;
|
|
@@ -290,10 +295,8 @@ type Predicate = {
|
|
|
290
295
|
readonly kind: "count";
|
|
291
296
|
readonly value: number;
|
|
292
297
|
} | {
|
|
293
|
-
readonly
|
|
294
|
-
readonly consequence: Predicate;
|
|
298
|
+
readonly branches: ReadonlyArray<WhenBranch>;
|
|
295
299
|
readonly kind: "when";
|
|
296
|
-
readonly otherwise: Predicate | undefined;
|
|
297
300
|
};
|
|
298
301
|
type Condition = Extract<Predicate, {
|
|
299
302
|
kind: "singleton" | "count";
|
|
@@ -367,7 +370,7 @@ declare const stepSchema: z.ZodObject<{
|
|
|
367
370
|
expect: z.ZodDefault<z.ZodArray<z.ZodType<Predicate, unknown, z.core.$ZodTypeInternals<Predicate, unknown>>>>;
|
|
368
371
|
}, z.core.$strip>;
|
|
369
372
|
type Step = z.infer<typeof stepSchema>;
|
|
370
|
-
declare const
|
|
373
|
+
declare const workflowSchema: z.ZodObject<{
|
|
371
374
|
absent: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
372
375
|
entity: z.ZodString;
|
|
373
376
|
where: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodObject<{
|
|
@@ -393,7 +396,6 @@ declare const testSchema: z.ZodObject<{
|
|
|
393
396
|
}, z.core.$strip>>>;
|
|
394
397
|
name: z.ZodString;
|
|
395
398
|
params: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
396
|
-
example: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
|
|
397
399
|
valueSpace: z.ZodString;
|
|
398
400
|
}, z.core.$strip>>;
|
|
399
401
|
singletons: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodObject<{
|
|
@@ -464,6 +466,103 @@ declare const testSchema: z.ZodObject<{
|
|
|
464
466
|
expect: z.ZodDefault<z.ZodArray<z.ZodType<Predicate, unknown, z.core.$ZodTypeInternals<Predicate, unknown>>>>;
|
|
465
467
|
}, z.core.$strip>>>;
|
|
466
468
|
stub: z.ZodDefault<z.ZodBoolean>;
|
|
469
|
+
tests: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
470
|
+
absent: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
471
|
+
entity: z.ZodString;
|
|
472
|
+
where: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodObject<{
|
|
473
|
+
ref: z.ZodString;
|
|
474
|
+
}, z.core.$strip>, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>, z.ZodObject<{
|
|
475
|
+
template: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
476
|
+
ref: z.ZodString;
|
|
477
|
+
}, z.core.$strip>]>>;
|
|
478
|
+
}, z.core.$strip>, z.ZodNull]>>;
|
|
479
|
+
}, z.core.$strip>>>;
|
|
480
|
+
exclusive: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
481
|
+
intent: z.ZodString;
|
|
482
|
+
name: z.ZodString;
|
|
483
|
+
params: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
484
|
+
valueSpace: z.ZodString;
|
|
485
|
+
}, z.core.$strip>>;
|
|
486
|
+
singletons: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodObject<{
|
|
487
|
+
ref: z.ZodString;
|
|
488
|
+
}, z.core.$strip>, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>, z.ZodObject<{
|
|
489
|
+
template: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
490
|
+
ref: z.ZodString;
|
|
491
|
+
}, z.core.$strip>]>>;
|
|
492
|
+
}, z.core.$strip>, z.ZodNull]>>>;
|
|
493
|
+
slug: z.ZodString;
|
|
494
|
+
steps: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
495
|
+
action: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
496
|
+
kind: z.ZodLiteral<"goto">;
|
|
497
|
+
url: z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
498
|
+
ref: z.ZodString;
|
|
499
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
500
|
+
template: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
501
|
+
ref: z.ZodString;
|
|
502
|
+
}, z.core.$strip>]>>;
|
|
503
|
+
}, z.core.$strip>]>;
|
|
504
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
505
|
+
kind: z.ZodLiteral<"fill">;
|
|
506
|
+
locator: z.ZodType<Locator, unknown, z.core.$ZodTypeInternals<Locator, unknown>>;
|
|
507
|
+
value: z.ZodUnion<readonly [z.ZodObject<{
|
|
508
|
+
ref: z.ZodString;
|
|
509
|
+
}, z.core.$strip>, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>, z.ZodObject<{
|
|
510
|
+
template: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
511
|
+
ref: z.ZodString;
|
|
512
|
+
}, z.core.$strip>]>>;
|
|
513
|
+
}, z.core.$strip>, z.ZodNull]>;
|
|
514
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
515
|
+
kind: z.ZodLiteral<"clear">;
|
|
516
|
+
locator: z.ZodType<Locator, unknown, z.core.$ZodTypeInternals<Locator, unknown>>;
|
|
517
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
518
|
+
kind: z.ZodLiteral<"click">;
|
|
519
|
+
locator: z.ZodType<Locator, unknown, z.core.$ZodTypeInternals<Locator, unknown>>;
|
|
520
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
521
|
+
kind: z.ZodLiteral<"dblclick">;
|
|
522
|
+
locator: z.ZodType<Locator, unknown, z.core.$ZodTypeInternals<Locator, unknown>>;
|
|
523
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
524
|
+
kind: z.ZodLiteral<"select">;
|
|
525
|
+
locator: z.ZodType<Locator, unknown, z.core.$ZodTypeInternals<Locator, unknown>>;
|
|
526
|
+
value: z.ZodUnion<readonly [z.ZodObject<{
|
|
527
|
+
ref: z.ZodString;
|
|
528
|
+
}, z.core.$strip>, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>, z.ZodObject<{
|
|
529
|
+
template: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
530
|
+
ref: z.ZodString;
|
|
531
|
+
}, z.core.$strip>]>>;
|
|
532
|
+
}, z.core.$strip>, z.ZodNull]>;
|
|
533
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
534
|
+
kind: z.ZodLiteral<"check">;
|
|
535
|
+
locator: z.ZodType<Locator, unknown, z.core.$ZodTypeInternals<Locator, unknown>>;
|
|
536
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
537
|
+
kind: z.ZodLiteral<"uncheck">;
|
|
538
|
+
locator: z.ZodType<Locator, unknown, z.core.$ZodTypeInternals<Locator, unknown>>;
|
|
539
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
540
|
+
kind: z.ZodLiteral<"hover">;
|
|
541
|
+
locator: z.ZodType<Locator, unknown, z.core.$ZodTypeInternals<Locator, unknown>>;
|
|
542
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
543
|
+
files: z.ZodArray<z.ZodString>;
|
|
544
|
+
kind: z.ZodLiteral<"upload">;
|
|
545
|
+
locator: z.ZodType<Locator, unknown, z.core.$ZodTypeInternals<Locator, unknown>>;
|
|
546
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
547
|
+
key: z.ZodString;
|
|
548
|
+
kind: z.ZodLiteral<"press">;
|
|
549
|
+
locator: z.ZodOptional<z.ZodType<Locator, unknown, z.core.$ZodTypeInternals<Locator, unknown>>>;
|
|
550
|
+
}, z.core.$strip>], "kind">;
|
|
551
|
+
expect: z.ZodDefault<z.ZodArray<z.ZodType<Predicate, unknown, z.core.$ZodTypeInternals<Predicate, unknown>>>>;
|
|
552
|
+
}, z.core.$strip>>>;
|
|
553
|
+
workflow: z.ZodString;
|
|
554
|
+
world: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
555
|
+
as: z.ZodString;
|
|
556
|
+
entity: z.ZodString;
|
|
557
|
+
set: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodObject<{
|
|
558
|
+
ref: z.ZodString;
|
|
559
|
+
}, z.core.$strip>, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>, z.ZodObject<{
|
|
560
|
+
template: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
561
|
+
ref: z.ZodString;
|
|
562
|
+
}, z.core.$strip>]>>;
|
|
563
|
+
}, z.core.$strip>, z.ZodNull]>>;
|
|
564
|
+
}, z.core.$strip>>>;
|
|
565
|
+
}, z.core.$strip>>>;
|
|
467
566
|
world: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
468
567
|
as: z.ZodString;
|
|
469
568
|
entity: z.ZodString;
|
|
@@ -476,7 +575,7 @@ declare const testSchema: z.ZodObject<{
|
|
|
476
575
|
}, z.core.$strip>, z.ZodNull]>>;
|
|
477
576
|
}, z.core.$strip>>>;
|
|
478
577
|
}, z.core.$strip>;
|
|
479
|
-
type
|
|
578
|
+
type Workflow = z.infer<typeof workflowSchema>;
|
|
480
579
|
declare const lockfileSchema: z.ZodObject<{
|
|
481
580
|
entities: z.ZodArray<z.ZodObject<{
|
|
482
581
|
description: z.ZodOptional<z.ZodString>;
|
|
@@ -528,7 +627,39 @@ declare const lockfileSchema: z.ZodObject<{
|
|
|
528
627
|
}>;
|
|
529
628
|
valueSpace: z.ZodOptional<z.ZodString>;
|
|
530
629
|
}, z.core.$strip>>>;
|
|
531
|
-
|
|
630
|
+
valueSpaces: z.ZodArray<z.ZodObject<{
|
|
631
|
+
constraints: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
632
|
+
kind: z.ZodLiteral<"string">;
|
|
633
|
+
maxLength: z.ZodOptional<z.ZodNumber>;
|
|
634
|
+
minLength: z.ZodOptional<z.ZodNumber>;
|
|
635
|
+
pattern: z.ZodOptional<z.ZodString>;
|
|
636
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
637
|
+
kind: z.ZodLiteral<"number">;
|
|
638
|
+
max: z.ZodOptional<z.ZodNumber>;
|
|
639
|
+
min: z.ZodOptional<z.ZodNumber>;
|
|
640
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
641
|
+
kind: z.ZodLiteral<"datetime">;
|
|
642
|
+
maxOffsetDays: z.ZodNumber;
|
|
643
|
+
minOffsetDays: z.ZodNumber;
|
|
644
|
+
}, z.core.$strip>], "kind">>;
|
|
645
|
+
generator: z.ZodEnum<{
|
|
646
|
+
"company.name": "company.name";
|
|
647
|
+
"date.iso": "date.iso";
|
|
648
|
+
"internet.email": "internet.email";
|
|
649
|
+
"internet.url": "internet.url";
|
|
650
|
+
"person.fullName": "person.fullName";
|
|
651
|
+
"lorem.slug": "lorem.slug";
|
|
652
|
+
"lorem.word": "lorem.word";
|
|
653
|
+
}>;
|
|
654
|
+
name: z.ZodString;
|
|
655
|
+
type: z.ZodEnum<{
|
|
656
|
+
string: "string";
|
|
657
|
+
number: "number";
|
|
658
|
+
boolean: "boolean";
|
|
659
|
+
}>;
|
|
660
|
+
values: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
|
|
661
|
+
}, z.core.$strip>>;
|
|
662
|
+
workflows: z.ZodArray<z.ZodObject<{
|
|
532
663
|
absent: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
533
664
|
entity: z.ZodString;
|
|
534
665
|
where: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodObject<{
|
|
@@ -554,7 +685,6 @@ declare const lockfileSchema: z.ZodObject<{
|
|
|
554
685
|
}, z.core.$strip>>>;
|
|
555
686
|
name: z.ZodString;
|
|
556
687
|
params: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
557
|
-
example: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
|
|
558
688
|
valueSpace: z.ZodString;
|
|
559
689
|
}, z.core.$strip>>;
|
|
560
690
|
singletons: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodObject<{
|
|
@@ -625,6 +755,103 @@ declare const lockfileSchema: z.ZodObject<{
|
|
|
625
755
|
expect: z.ZodDefault<z.ZodArray<z.ZodType<Predicate, unknown, z.core.$ZodTypeInternals<Predicate, unknown>>>>;
|
|
626
756
|
}, z.core.$strip>>>;
|
|
627
757
|
stub: z.ZodDefault<z.ZodBoolean>;
|
|
758
|
+
tests: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
759
|
+
absent: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
760
|
+
entity: z.ZodString;
|
|
761
|
+
where: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodObject<{
|
|
762
|
+
ref: z.ZodString;
|
|
763
|
+
}, z.core.$strip>, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>, z.ZodObject<{
|
|
764
|
+
template: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
765
|
+
ref: z.ZodString;
|
|
766
|
+
}, z.core.$strip>]>>;
|
|
767
|
+
}, z.core.$strip>, z.ZodNull]>>;
|
|
768
|
+
}, z.core.$strip>>>;
|
|
769
|
+
exclusive: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
770
|
+
intent: z.ZodString;
|
|
771
|
+
name: z.ZodString;
|
|
772
|
+
params: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
773
|
+
valueSpace: z.ZodString;
|
|
774
|
+
}, z.core.$strip>>;
|
|
775
|
+
singletons: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodObject<{
|
|
776
|
+
ref: z.ZodString;
|
|
777
|
+
}, z.core.$strip>, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>, z.ZodObject<{
|
|
778
|
+
template: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
779
|
+
ref: z.ZodString;
|
|
780
|
+
}, z.core.$strip>]>>;
|
|
781
|
+
}, z.core.$strip>, z.ZodNull]>>>;
|
|
782
|
+
slug: z.ZodString;
|
|
783
|
+
steps: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
784
|
+
action: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
785
|
+
kind: z.ZodLiteral<"goto">;
|
|
786
|
+
url: z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
787
|
+
ref: z.ZodString;
|
|
788
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
789
|
+
template: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
790
|
+
ref: z.ZodString;
|
|
791
|
+
}, z.core.$strip>]>>;
|
|
792
|
+
}, z.core.$strip>]>;
|
|
793
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
794
|
+
kind: z.ZodLiteral<"fill">;
|
|
795
|
+
locator: z.ZodType<Locator, unknown, z.core.$ZodTypeInternals<Locator, unknown>>;
|
|
796
|
+
value: z.ZodUnion<readonly [z.ZodObject<{
|
|
797
|
+
ref: z.ZodString;
|
|
798
|
+
}, z.core.$strip>, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>, z.ZodObject<{
|
|
799
|
+
template: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
800
|
+
ref: z.ZodString;
|
|
801
|
+
}, z.core.$strip>]>>;
|
|
802
|
+
}, z.core.$strip>, z.ZodNull]>;
|
|
803
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
804
|
+
kind: z.ZodLiteral<"clear">;
|
|
805
|
+
locator: z.ZodType<Locator, unknown, z.core.$ZodTypeInternals<Locator, unknown>>;
|
|
806
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
807
|
+
kind: z.ZodLiteral<"click">;
|
|
808
|
+
locator: z.ZodType<Locator, unknown, z.core.$ZodTypeInternals<Locator, unknown>>;
|
|
809
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
810
|
+
kind: z.ZodLiteral<"dblclick">;
|
|
811
|
+
locator: z.ZodType<Locator, unknown, z.core.$ZodTypeInternals<Locator, unknown>>;
|
|
812
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
813
|
+
kind: z.ZodLiteral<"select">;
|
|
814
|
+
locator: z.ZodType<Locator, unknown, z.core.$ZodTypeInternals<Locator, unknown>>;
|
|
815
|
+
value: z.ZodUnion<readonly [z.ZodObject<{
|
|
816
|
+
ref: z.ZodString;
|
|
817
|
+
}, z.core.$strip>, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>, z.ZodObject<{
|
|
818
|
+
template: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
819
|
+
ref: z.ZodString;
|
|
820
|
+
}, z.core.$strip>]>>;
|
|
821
|
+
}, z.core.$strip>, z.ZodNull]>;
|
|
822
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
823
|
+
kind: z.ZodLiteral<"check">;
|
|
824
|
+
locator: z.ZodType<Locator, unknown, z.core.$ZodTypeInternals<Locator, unknown>>;
|
|
825
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
826
|
+
kind: z.ZodLiteral<"uncheck">;
|
|
827
|
+
locator: z.ZodType<Locator, unknown, z.core.$ZodTypeInternals<Locator, unknown>>;
|
|
828
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
829
|
+
kind: z.ZodLiteral<"hover">;
|
|
830
|
+
locator: z.ZodType<Locator, unknown, z.core.$ZodTypeInternals<Locator, unknown>>;
|
|
831
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
832
|
+
files: z.ZodArray<z.ZodString>;
|
|
833
|
+
kind: z.ZodLiteral<"upload">;
|
|
834
|
+
locator: z.ZodType<Locator, unknown, z.core.$ZodTypeInternals<Locator, unknown>>;
|
|
835
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
836
|
+
key: z.ZodString;
|
|
837
|
+
kind: z.ZodLiteral<"press">;
|
|
838
|
+
locator: z.ZodOptional<z.ZodType<Locator, unknown, z.core.$ZodTypeInternals<Locator, unknown>>>;
|
|
839
|
+
}, z.core.$strip>], "kind">;
|
|
840
|
+
expect: z.ZodDefault<z.ZodArray<z.ZodType<Predicate, unknown, z.core.$ZodTypeInternals<Predicate, unknown>>>>;
|
|
841
|
+
}, z.core.$strip>>>;
|
|
842
|
+
workflow: z.ZodString;
|
|
843
|
+
world: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
844
|
+
as: z.ZodString;
|
|
845
|
+
entity: z.ZodString;
|
|
846
|
+
set: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodObject<{
|
|
847
|
+
ref: z.ZodString;
|
|
848
|
+
}, z.core.$strip>, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>, z.ZodObject<{
|
|
849
|
+
template: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
850
|
+
ref: z.ZodString;
|
|
851
|
+
}, z.core.$strip>]>>;
|
|
852
|
+
}, z.core.$strip>, z.ZodNull]>>;
|
|
853
|
+
}, z.core.$strip>>>;
|
|
854
|
+
}, z.core.$strip>>>;
|
|
628
855
|
world: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
629
856
|
as: z.ZodString;
|
|
630
857
|
entity: z.ZodString;
|
|
@@ -637,38 +864,6 @@ declare const lockfileSchema: z.ZodObject<{
|
|
|
637
864
|
}, z.core.$strip>, z.ZodNull]>>;
|
|
638
865
|
}, z.core.$strip>>>;
|
|
639
866
|
}, z.core.$strip>>;
|
|
640
|
-
valueSpaces: z.ZodArray<z.ZodObject<{
|
|
641
|
-
constraints: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
642
|
-
kind: z.ZodLiteral<"string">;
|
|
643
|
-
maxLength: z.ZodOptional<z.ZodNumber>;
|
|
644
|
-
minLength: z.ZodOptional<z.ZodNumber>;
|
|
645
|
-
pattern: z.ZodOptional<z.ZodString>;
|
|
646
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
647
|
-
kind: z.ZodLiteral<"number">;
|
|
648
|
-
max: z.ZodOptional<z.ZodNumber>;
|
|
649
|
-
min: z.ZodOptional<z.ZodNumber>;
|
|
650
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
651
|
-
kind: z.ZodLiteral<"datetime">;
|
|
652
|
-
maxOffsetDays: z.ZodNumber;
|
|
653
|
-
minOffsetDays: z.ZodNumber;
|
|
654
|
-
}, z.core.$strip>], "kind">>;
|
|
655
|
-
generator: z.ZodEnum<{
|
|
656
|
-
"company.name": "company.name";
|
|
657
|
-
"date.iso": "date.iso";
|
|
658
|
-
"internet.email": "internet.email";
|
|
659
|
-
"internet.url": "internet.url";
|
|
660
|
-
"person.fullName": "person.fullName";
|
|
661
|
-
"lorem.slug": "lorem.slug";
|
|
662
|
-
"lorem.word": "lorem.word";
|
|
663
|
-
}>;
|
|
664
|
-
name: z.ZodString;
|
|
665
|
-
type: z.ZodEnum<{
|
|
666
|
-
string: "string";
|
|
667
|
-
number: "number";
|
|
668
|
-
boolean: "boolean";
|
|
669
|
-
}>;
|
|
670
|
-
values: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
|
|
671
|
-
}, z.core.$strip>>;
|
|
672
867
|
}, z.core.$strip>;
|
|
673
868
|
type Lockfile = z.infer<typeof lockfileSchema>;
|
|
674
869
|
declare const sessionSchema: z.ZodObject<{
|
|
@@ -745,7 +940,6 @@ type Primitive = string | number | boolean;
|
|
|
745
940
|
type Fields = Record<string, Primitive>;
|
|
746
941
|
interface ParamToken {
|
|
747
942
|
readonly base: string;
|
|
748
|
-
readonly example: Primitive | undefined;
|
|
749
943
|
readonly valueSpace: string;
|
|
750
944
|
}
|
|
751
945
|
type EntityKind = "of" | "only" | "maybe";
|
|
@@ -830,9 +1024,19 @@ interface CountCondition {
|
|
|
830
1024
|
readonly is: (count: number) => ConditionPredicate;
|
|
831
1025
|
}
|
|
832
1026
|
declare function count(entity: Countable): CountCondition;
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
1027
|
+
interface BranchInput {
|
|
1028
|
+
readonly __branch: true;
|
|
1029
|
+
readonly branch: WhenBranch;
|
|
1030
|
+
}
|
|
1031
|
+
interface NamedBranch {
|
|
1032
|
+
readonly expect: (consequence: PredicateInput) => BranchInput;
|
|
1033
|
+
readonly if: (condition: ConditionInput) => ConditionedBranch;
|
|
1034
|
+
}
|
|
1035
|
+
interface ConditionedBranch {
|
|
1036
|
+
readonly expect: (consequence: PredicateInput) => BranchInput;
|
|
1037
|
+
}
|
|
1038
|
+
declare function branch(name: string): NamedBranch;
|
|
1039
|
+
declare function when(...branches: ReadonlyArray<BranchInput>): LeafPredicate;
|
|
836
1040
|
|
|
837
1041
|
interface ValueSpacePartial<T extends Primitive> {
|
|
838
1042
|
readonly __t: T | undefined;
|
|
@@ -1088,4 +1292,4 @@ interface Engine {
|
|
|
1088
1292
|
}
|
|
1089
1293
|
declare function createEngine<R extends DeclSource>(ripplo: R, impls: EngineImpls<R, "backend">, teardown: Teardown): Engine;
|
|
1090
1294
|
|
|
1091
|
-
export {
|
|
1295
|
+
export { field as $, type AnyBinding as A, type Binding as B, type Capture as C, type DeclSource as D, type Engine as E, type FieldHandle as F, type GivenItem as G, type Handle as H, type SingletonConfig as I, type SingletonImpl as J, type SingletonValue as K, type Locator as L, type WithinMatcher as M, type NamedBranch as N, and as O, type PredicateInput as P, branch as Q, type Row as R, type Step as S, changed as T, type UniqueNames as U, count as V, type Workflow as W, createEngine as X, disabled as Y, enabled as Z, entity as _, type EntityList as a, focused as a0, id as a1, key as a2, not as a3, singleton as a4, text as a5, v as a6, value as a7, visible as a8, when as a9, within as aa, type SingletonList as b, type Lockfile as c, type BrowserSingleton as d, type LeafPredicate as e, type Primitive as f, type Primitive$1 as g, type SingletonDef as h, type AbsenceHandle as i, type BranchInput as j, CLIENT_MOUNT_KEY as k, CLIENT_SEED_KEY as l, type ConditionInput as m, type ConditionPredicate as n, type ConditionedBranch as o, type CountCondition as p, type DuplicateEntityName as q, type EngineError as r, type EngineImpls as s, type EngineRead as t, type EntityDef as u, type EntityHandle as v, type EntityImpl as w, type FieldOptions as x, type Fields as y, type Selection as z };
|
package/dist/express.d.ts
CHANGED