@smthrs/plan 1.0.0-rc.5 → 1.0.0-rc.7
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/CHANGELOG.md +2 -0
- package/README.md +18 -18
- package/THIRD_PARTY_NOTICES.md +48 -0
- package/dist/cjs/KeyMaterial.d.ts +1 -1
- package/dist/cjs/KeyMaterial.js.map +1 -1
- package/dist/cjs/Node.d.ts +71 -0
- package/dist/cjs/Node.d.ts.map +1 -1
- package/dist/cjs/Node.js +7 -0
- package/dist/cjs/Node.js.map +2 -2
- package/dist/cjs/StepKey.d.ts +1 -1
- package/dist/cjs/StepKey.js.map +1 -1
- package/dist/cjs/internal/SchemaIdentity.d.ts +140 -0
- package/dist/cjs/internal/SchemaIdentity.d.ts.map +1 -0
- package/dist/cjs/internal/SchemaIdentity.js +718 -0
- package/dist/cjs/internal/SchemaIdentity.js.map +7 -0
- package/dist/cjs/internal/node.d.ts +1 -1
- package/dist/cjs/internal/node.d.ts.map +1 -1
- package/dist/cjs/internal/node.js +2 -1
- package/dist/cjs/internal/node.js.map +2 -2
- package/dist/esm/KeyMaterial.d.ts +1 -1
- package/dist/esm/KeyMaterial.js +1 -1
- package/dist/esm/KeyMaterial.js.map +1 -1
- package/dist/esm/Node.d.ts +71 -0
- package/dist/esm/Node.d.ts.map +1 -1
- package/dist/esm/Node.js +46 -0
- package/dist/esm/Node.js.map +1 -1
- package/dist/esm/StepKey.d.ts +1 -1
- package/dist/esm/StepKey.js +1 -1
- package/dist/esm/StepKey.js.map +1 -1
- package/dist/esm/internal/SchemaIdentity.d.ts +140 -0
- package/dist/esm/internal/SchemaIdentity.d.ts.map +1 -0
- package/dist/esm/internal/SchemaIdentity.js +1002 -0
- package/dist/esm/internal/SchemaIdentity.js.map +1 -0
- package/dist/esm/internal/node.d.ts +1 -1
- package/dist/esm/internal/node.d.ts.map +1 -1
- package/dist/esm/internal/node.js +3 -2
- package/dist/esm/internal/node.js.map +1 -1
- package/docs/README.md +1 -1
- package/docs/api.md +11 -1
- package/docs/concepts/authoring-ast.md +2 -1
- package/docs/guides/diff-two-plans.md +158 -13
- package/docs/installation.md +3 -3
- package/package.json +9 -8
- package/src/KeyMaterial.ts +1 -1
- package/src/Node.ts +79 -0
- package/src/StepKey.ts +1 -1
- package/src/internal/SchemaIdentity.ts +1096 -0
- package/src/internal/node.ts +3 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "Diff two plans"
|
|
3
|
-
description: "Compare a re-plan against the plan before it: what the verdict is, how a re-key is attributed to the field that caused it, and why the report is in no digest."
|
|
3
|
+
description: "Compare a re-plan against the plan before it: what the verdict is, how a re-key is attributed to the field that caused it, why node ids are positional, and why the report is in no digest."
|
|
4
4
|
sidebar:
|
|
5
5
|
order: 5
|
|
6
6
|
---
|
|
@@ -8,28 +8,81 @@ sidebar:
|
|
|
8
8
|
"What is different about this run" is a set comparison, not archaeology.
|
|
9
9
|
`PlanDiff.diff` is that comparison as a value.
|
|
10
10
|
|
|
11
|
+
## Before you start
|
|
12
|
+
|
|
13
|
+
The examples run with `node <file>.ts` on Node.js 26.4.0 or later and need no
|
|
14
|
+
engine, database, or jj. Compiling a plan needs Effect's `Crypto` service, which
|
|
15
|
+
`@effect/platform-node` supplies. In a project that installed `@smthrs/flows`,
|
|
16
|
+
add this package and `@smthrs/flow` at the version of `@smthrs/flows` you have,
|
|
17
|
+
plus the platform package:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @smthrs/plan@1.0.0-rc.7 @smthrs/flow@1.0.0-rc.7 @effect/platform-node
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The outputs below are real output from 1.0.0-rc.6.
|
|
24
|
+
|
|
25
|
+
## Compare a re-plan
|
|
26
|
+
|
|
27
|
+
Create `diff.ts`. It compiles the two drafts from
|
|
28
|
+
[Compile drafts into a plan](./compile-a-plan.md), edits one field of one
|
|
29
|
+
draft's body, compiles again, and compares:
|
|
30
|
+
|
|
11
31
|
```ts
|
|
12
32
|
import * as NodeCrypto from "@effect/platform-node/NodeCrypto"
|
|
33
|
+
import * as KeyMaterial from "@smthrs/plan/KeyMaterial"
|
|
13
34
|
import * as Plan from "@smthrs/plan/Plan"
|
|
14
35
|
import * as PlanDiff from "@smthrs/plan/PlanDiff"
|
|
15
|
-
import type * as Crypto from "effect/Crypto"
|
|
16
36
|
import * as Effect from "effect/Effect"
|
|
17
37
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
38
|
+
const readPr: Plan.NodeDraft = {
|
|
39
|
+
id: "read-pr",
|
|
40
|
+
material: {
|
|
41
|
+
version: KeyMaterial.version,
|
|
42
|
+
kind: "sealed",
|
|
43
|
+
body: { action: "read-pr", pr: 4821 },
|
|
44
|
+
inputs: [],
|
|
45
|
+
layers: [],
|
|
46
|
+
capabilities: ["net:get"]
|
|
47
|
+
},
|
|
48
|
+
effects: { reads: [], writes: ["pr.json"], boundaryMode: "hard" }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const runTests: Plan.NodeDraft = {
|
|
52
|
+
id: "run-tests",
|
|
53
|
+
material: {
|
|
54
|
+
version: KeyMaterial.version,
|
|
55
|
+
kind: "sealed",
|
|
56
|
+
body: { action: "run-tests" },
|
|
57
|
+
inputs: [{ _tag: "Ref", from: "read-pr", path: [] }],
|
|
58
|
+
layers: [],
|
|
59
|
+
capabilities: []
|
|
60
|
+
},
|
|
61
|
+
effects: { reads: ["pr.json"], writes: ["report.json"], boundaryMode: "hard" }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const compile = (nodes: ReadonlyArray<Plan.NodeDraft>) =>
|
|
65
|
+
Plan.compile({ planId: "review-4821", flow: "example/Review", nodes })
|
|
22
66
|
|
|
23
67
|
export const compare = Effect.gen(function*() {
|
|
24
|
-
const before = yield*
|
|
25
|
-
const after = yield*
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
})
|
|
68
|
+
const before = yield* compile([readPr, runTests])
|
|
69
|
+
const after = yield* compile([
|
|
70
|
+
readPr,
|
|
71
|
+
{ ...runTests, material: { ...runTests.material, body: { action: "run-tests", jobs: 4 } } }
|
|
72
|
+
])
|
|
30
73
|
const changes: PlanDiff.PlanDiff = PlanDiff.diff(before, after)
|
|
31
74
|
return changes.rekeyed.map((entry) => `${entry.id}: ${entry.changed.join(", ")}`)
|
|
32
75
|
}).pipe(Effect.provide(NodeCrypto.layer))
|
|
76
|
+
|
|
77
|
+
console.log(await Effect.runPromise(compare))
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
node diff.ts
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
```text
|
|
85
|
+
[ 'run-tests: body' ]
|
|
33
86
|
```
|
|
34
87
|
|
|
35
88
|
`compare` answers `["run-tests: body"]`. The edit moved one field of one node's
|
|
@@ -70,6 +123,94 @@ reported as nothing changed.
|
|
|
70
123
|
key moved for a reason the comparison does not model. Treat an empty `changed`
|
|
71
124
|
on a re-keyed node as a bug report, not as noise.
|
|
72
125
|
|
|
126
|
+
## Node ids are positional
|
|
127
|
+
|
|
128
|
+
A node id is the node's structural address in the body, such as
|
|
129
|
+
`root.flow.andThen`, not the name of its step. Appending a step to a flow
|
|
130
|
+
nests the steps before it one level deeper, so a diff by id reports an
|
|
131
|
+
unchanged step as `added` under its new address and reports the addresses it
|
|
132
|
+
left as `rekeyed`. The step's key does not change.
|
|
133
|
+
|
|
134
|
+
Create `positional.ts`. It compiles a two-step flow and the same flow with a
|
|
135
|
+
third step appended, diffs them, then matches the steps by key:
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
import * as NodeCrypto from "@effect/platform-node/NodeCrypto"
|
|
139
|
+
import { Action, Flow, Graph } from "@smthrs/flow"
|
|
140
|
+
import { Node } from "@smthrs/plan"
|
|
141
|
+
import * as Plan from "@smthrs/plan/Plan"
|
|
142
|
+
import * as PlanDiff from "@smthrs/plan/PlanDiff"
|
|
143
|
+
import * as Effect from "effect/Effect"
|
|
144
|
+
import * as Schema from "effect/Schema"
|
|
145
|
+
|
|
146
|
+
const Draft = Action.make("fix/Draft", { payload: { issue: Schema.String }, success: Schema.String })
|
|
147
|
+
const Test = Action.make("fix/Test", { payload: { plan: Schema.String }, success: Schema.String })
|
|
148
|
+
const Report = Action.make("fix/Report", { payload: { result: Schema.String }, success: Schema.String })
|
|
149
|
+
|
|
150
|
+
const before = Flow.make("fix/Fix", {
|
|
151
|
+
payload: { issue: Schema.String },
|
|
152
|
+
success: Schema.String,
|
|
153
|
+
body: (input) => Draft.call(input).pipe(Node.bindPlanned((plan) => Test.call({ plan })))
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
/** The same flow with one step appended. Draft and Test are unchanged. */
|
|
157
|
+
const after = Flow.make("fix/Fix", {
|
|
158
|
+
payload: { issue: Schema.String },
|
|
159
|
+
success: Schema.String,
|
|
160
|
+
body: (input) =>
|
|
161
|
+
Draft.call(input).pipe(
|
|
162
|
+
Node.bindPlanned((plan) => Test.call({ plan })),
|
|
163
|
+
Node.bindPlanned((result) => Report.call({ result }))
|
|
164
|
+
)
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
const planOf = (flow: Parameters<typeof Graph.build>[0]) =>
|
|
168
|
+
Plan.compile({ planId: "fix-1", flow: "fix/Fix", nodes: Graph.drafts(Graph.build(flow, { issue: "#42" })) })
|
|
169
|
+
|
|
170
|
+
/** The action a step node runs, read from its key material. */
|
|
171
|
+
const actionOf = (node: Plan.PlanNode) => {
|
|
172
|
+
const body = node.material.body
|
|
173
|
+
return typeof body === "object" && body !== null && "action" in body ? String(body.action) : undefined
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const program = Effect.gen(function*() {
|
|
177
|
+
const previous = yield* planOf(before)
|
|
178
|
+
const next = yield* planOf(after)
|
|
179
|
+
const changes = PlanDiff.diff(previous, next)
|
|
180
|
+
console.log("added ", changes.added)
|
|
181
|
+
console.log("rekeyed ", changes.rekeyed.map((entry) => entry.id))
|
|
182
|
+
console.log("unchanged", changes.unchanged)
|
|
183
|
+
|
|
184
|
+
// Match steps by key, not by id: an equal key is the same step.
|
|
185
|
+
const recorded = new Set(previous.nodes.map((node) => node.key))
|
|
186
|
+
for (const node of next.nodes) {
|
|
187
|
+
const action = actionOf(node)
|
|
188
|
+
if (action !== undefined) console.log(`${action.padEnd(11)} ${recorded.has(node.key) ? "same key" : "new key"}`)
|
|
189
|
+
}
|
|
190
|
+
}).pipe(Effect.provide(NodeCrypto.layer))
|
|
191
|
+
|
|
192
|
+
await Effect.runPromise(program)
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
node positional.ts
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
```text
|
|
200
|
+
added [ 'root.flow.andThen.andThen', 'root.flow.andThen.then' ]
|
|
201
|
+
rekeyed [ 'root.flow.andThen', 'root.flow.then', 'root.flow', 'root' ]
|
|
202
|
+
unchanged []
|
|
203
|
+
fix/Draft same key
|
|
204
|
+
fix/Test same key
|
|
205
|
+
fix/Report new key
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Only `Report` is new. `Draft` and `Test` moved to `root.flow.andThen.andThen`
|
|
209
|
+
and `root.flow.andThen.then` with the keys they had, so they come back under
|
|
210
|
+
`added`; their old ids now hold other nodes and come back under `rekeyed`. To
|
|
211
|
+
ask which steps changed, compare keys rather than ids, as the last loop does: a
|
|
212
|
+
key present in both plans is the same step.
|
|
213
|
+
|
|
73
214
|
## Comparison uses the key's own JSON semantics
|
|
74
215
|
|
|
75
216
|
Each compared field is projected through the same JSON mirror the keys are
|
|
@@ -88,7 +229,9 @@ The pairing this is built for is a re-plan of the same flow: compile the flow
|
|
|
88
229
|
again against the current source and compare the result with the plan an
|
|
89
230
|
operator last saw. `added` and `removed` are the shape change, `rekeyed` is the
|
|
90
231
|
work that will not come from cache, and `unchanged` is everything a cache hit
|
|
91
|
-
will skip.
|
|
232
|
+
will skip. That reading holds while the shape stays put. Once a step is added
|
|
233
|
+
or removed, ids move, so read the work by key as
|
|
234
|
+
[Node ids are positional](#node-ids-are-positional) shows.
|
|
92
235
|
|
|
93
236
|
The command line prints the same comparison through
|
|
94
237
|
[`smthrs flow plan`](/cli/flow), and the plan card it renders is what
|
|
@@ -96,6 +239,8 @@ The command line prints the same comparison through
|
|
|
96
239
|
|
|
97
240
|
## Next
|
|
98
241
|
|
|
242
|
+
- [Inspect the plan a body builds](../../../flow/docs/guides/inspect-the-plan.md):
|
|
243
|
+
build a flow's graph and read its nodes before anything runs.
|
|
99
244
|
- [Step keys](../concepts/step-keys.md): why an upstream edit re-keys a
|
|
100
245
|
downstream node whose own declaration did not change.
|
|
101
246
|
- [The plan value](../concepts/plan-value.md): the digests a diff sits beside.
|
package/docs/installation.md
CHANGED
|
@@ -8,8 +8,8 @@ sidebar:
|
|
|
8
8
|
## Requirements
|
|
9
9
|
|
|
10
10
|
- Node.js 26.4.0 or later.
|
|
11
|
-
- `effect` 4.0.
|
|
12
|
-
Effect values, so
|
|
11
|
+
- `effect` `^4.0.4`. The package's schemas, layers, and error classes are
|
|
12
|
+
Effect values, so it uses the one `effect` your application installs.
|
|
13
13
|
|
|
14
14
|
## Install
|
|
15
15
|
|
|
@@ -19,7 +19,7 @@ That is enough to build node graphs, compile plans, and diff them. Compiling
|
|
|
19
19
|
asks for Effect's `Crypto` service, which a platform package supplies:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
pnpm add @effect/platform-node
|
|
22
|
+
pnpm add @effect/platform-node @effect/platform-node-shared
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
`@smthrs/crypto`, `@smthrs/canonical` and [`@smthrs/keys`](/api/keys) arrive as
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smthrs/plan",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.0-rc.
|
|
4
|
+
"version": "1.0.0-rc.7",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"smthrs": {
|
|
7
7
|
"group": "engine"
|
|
@@ -207,6 +207,7 @@
|
|
|
207
207
|
"dist/**/*.d.ts.map",
|
|
208
208
|
"dist/**/package.json",
|
|
209
209
|
"LICENSE",
|
|
210
|
+
"THIRD_PARTY_NOTICES.md",
|
|
210
211
|
"README.md",
|
|
211
212
|
"CHANGELOG.md",
|
|
212
213
|
"docs/"
|
|
@@ -217,19 +218,19 @@
|
|
|
217
218
|
"tag": "next"
|
|
218
219
|
},
|
|
219
220
|
"dependencies": {
|
|
220
|
-
"@smthrs/crypto": "1.0.0-rc.
|
|
221
|
-
"@smthrs/keys": "1.0.0-rc.
|
|
222
|
-
"@smthrs/canonical": "1.0.0-rc.
|
|
221
|
+
"@smthrs/crypto": "1.0.0-rc.7",
|
|
222
|
+
"@smthrs/keys": "1.0.0-rc.7",
|
|
223
|
+
"@smthrs/canonical": "1.0.0-rc.7"
|
|
223
224
|
},
|
|
224
225
|
"devDependencies": {
|
|
225
226
|
"@effect/language-service": "0.87.2",
|
|
226
|
-
"@effect/platform-node": "4.0.
|
|
227
|
-
"@effect/vitest": "4.0.
|
|
227
|
+
"@effect/platform-node": "4.0.4",
|
|
228
|
+
"@effect/vitest": "4.0.4",
|
|
228
229
|
"@eslint/js": "9.39.5",
|
|
229
230
|
"@types/node": "26.4.1",
|
|
230
231
|
"@vitest/coverage-v8": "5.0.0",
|
|
231
232
|
"dprint": "0.57.1",
|
|
232
|
-
"effect": "4.0.
|
|
233
|
+
"effect": "4.0.4",
|
|
233
234
|
"esbuild": "0.28.2",
|
|
234
235
|
"eslint": "9.39.5",
|
|
235
236
|
"eslint-import-resolver-typescript": "4.4.5",
|
|
@@ -243,7 +244,7 @@
|
|
|
243
244
|
"fast-check": "4.9.0"
|
|
244
245
|
},
|
|
245
246
|
"peerDependencies": {
|
|
246
|
-
"effect": "4.0.
|
|
247
|
+
"effect": "^4.0.4"
|
|
247
248
|
},
|
|
248
249
|
"scripts": {
|
|
249
250
|
"lint": "eslint src --max-warnings=0 && dprint check",
|
package/src/KeyMaterial.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* lives here, above `@smthrs/keys`, so the key package stays a leaf.
|
|
8
8
|
*
|
|
9
9
|
* Governing contract: the step-key rules at
|
|
10
|
-
* https://
|
|
10
|
+
* https://github.com/smithersai/smithers/blob/main/packages/smithers/flows/plan/docs/concepts/step-keys.md. Material is computed with no I/O,
|
|
11
11
|
* and two hardening rules shape it: the nominal, never shape-sniffed
|
|
12
12
|
* `InputRef` and the hashed `version`.
|
|
13
13
|
*
|
package/src/Node.ts
CHANGED
|
@@ -31,9 +31,11 @@
|
|
|
31
31
|
import { dual } from "effect/Function"
|
|
32
32
|
import type * as Pipeable from "effect/Pipeable"
|
|
33
33
|
import type * as Schema from "effect/Schema"
|
|
34
|
+
import type * as SchemaAST from "effect/SchemaAST"
|
|
34
35
|
import type * as Types from "effect/Types"
|
|
35
36
|
import { GraphBuildError } from "./GraphBuildError.ts"
|
|
36
37
|
import * as internal from "./internal/node.ts"
|
|
38
|
+
import * as internalSchemaIdentity from "./internal/SchemaIdentity.ts"
|
|
37
39
|
import * as Planned from "./Planned.ts"
|
|
38
40
|
|
|
39
41
|
/**
|
|
@@ -843,6 +845,83 @@ export const catchFilter = (ast: Ast): Schema.Top | undefined => ast._tag === "C
|
|
|
843
845
|
*/
|
|
844
846
|
export const functionIdentity = (operation: unknown): FunctionIdentity => internal.functionIdentity(operation)
|
|
845
847
|
|
|
848
|
+
/**
|
|
849
|
+
* The document a schema's identity is: JSON-Schema-shaped, and the same bytes
|
|
850
|
+
* under every `effect` release this package supports.
|
|
851
|
+
*
|
|
852
|
+
* @since 1.0.0
|
|
853
|
+
* @category engine
|
|
854
|
+
*/
|
|
855
|
+
export type SchemaIdentity = internalSchemaIdentity.Document
|
|
856
|
+
|
|
857
|
+
/**
|
|
858
|
+
* The one option a schema's identity is taken under: whether an object closes
|
|
859
|
+
* over the keys it declares (`"error"`) or leaves others open (`"ignore"`,
|
|
860
|
+
* the default). It has the meaning it has in `Schema.toJsonSchemaDocument`.
|
|
861
|
+
*
|
|
862
|
+
* @since 1.0.0
|
|
863
|
+
* @category engine
|
|
864
|
+
*/
|
|
865
|
+
export type SchemaIdentityOptions = internalSchemaIdentity.Options
|
|
866
|
+
|
|
867
|
+
/**
|
|
868
|
+
* The refusal `schemaIdentity` and `representationIdentity` raise for a schema
|
|
869
|
+
* a step key cannot be derived from. Its message is the one
|
|
870
|
+
* `effect@4.0.0-rc.115` gave for the same schema, where it gave one.
|
|
871
|
+
*
|
|
872
|
+
* @since 1.0.0
|
|
873
|
+
* @category errors
|
|
874
|
+
*/
|
|
875
|
+
export const SchemaIdentityError = internalSchemaIdentity.SchemaIdentityError
|
|
876
|
+
|
|
877
|
+
/**
|
|
878
|
+
* The type of {@link SchemaIdentityError}.
|
|
879
|
+
*
|
|
880
|
+
* @since 1.0.0
|
|
881
|
+
* @category errors
|
|
882
|
+
*/
|
|
883
|
+
export type SchemaIdentityError = internalSchemaIdentity.SchemaIdentityError
|
|
884
|
+
|
|
885
|
+
/**
|
|
886
|
+
* Identifies a schema by the constraints it documents, so a call re-keys when
|
|
887
|
+
* what its callee accepts or produces changes, and a catch re-keys when its
|
|
888
|
+
* filter does.
|
|
889
|
+
*
|
|
890
|
+
* The document is what `Schema.toJsonSchemaDocument(schema, options)`
|
|
891
|
+
* returned under `effect@4.0.0-rc.115`. It is printed by this package, not by
|
|
892
|
+
* the installed `effect`, because a later release prints a different document
|
|
893
|
+
* for the same schema and a moved identity re-keys every recorded step. Use
|
|
894
|
+
* it wherever the document is hashed, compared or pinned; a JSON Schema shown
|
|
895
|
+
* to a model or a person comes from `Schema.toJsonSchemaDocument`.
|
|
896
|
+
*
|
|
897
|
+
* Reserved for the packages that derive identities. Authors never call it; it
|
|
898
|
+
* throws for a schema that has no JSON Schema form.
|
|
899
|
+
*
|
|
900
|
+
* @since 1.0.0
|
|
901
|
+
* @category engine
|
|
902
|
+
*/
|
|
903
|
+
export const schemaIdentity = (schema: Schema.Top, options?: SchemaIdentityOptions): SchemaIdentity =>
|
|
904
|
+
internalSchemaIdentity.schemaIdentity(schema, options)
|
|
905
|
+
|
|
906
|
+
/**
|
|
907
|
+
* Identifies a schema AST by its encoded representation, the material a
|
|
908
|
+
* sealed action's step key folds in for its success and error schemas.
|
|
909
|
+
*
|
|
910
|
+
* The value is what `SchemaRepresentation.toJson(SchemaRepresentation.toRepresentation(ast))`
|
|
911
|
+
* returned under `effect@4.0.0-rc.115`, so a later `effect` release does not
|
|
912
|
+
* re-key recorded steps. The one exception is `Schema.brand`: from
|
|
913
|
+
* `effect@4.0.4` on a brand is not part of the AST, so a declaration with a
|
|
914
|
+
* brand re-keys once.
|
|
915
|
+
*
|
|
916
|
+
* Reserved for the packages that derive step keys. Authors never call it; it
|
|
917
|
+
* throws for an AST that has no representation.
|
|
918
|
+
*
|
|
919
|
+
* @since 1.0.0
|
|
920
|
+
* @category engine
|
|
921
|
+
*/
|
|
922
|
+
export const representationIdentity = (ast: SchemaAST.AST): Schema.Json =>
|
|
923
|
+
internalSchemaIdentity.representationIdentity(ast)
|
|
924
|
+
|
|
846
925
|
/**
|
|
847
926
|
* Binds a frozen plain copy of inert captures as the callback's this receiver.
|
|
848
927
|
*
|
package/src/StepKey.ts
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* resolved references, and the hashed `version`.
|
|
23
23
|
*
|
|
24
24
|
* Governing contract: the step-key rules at
|
|
25
|
-
* https://
|
|
25
|
+
* https://github.com/smithersai/smithers/blob/main/packages/smithers/flows/plan/docs/concepts/step-keys.md.
|
|
26
26
|
*
|
|
27
27
|
* @since 0.1.0
|
|
28
28
|
*/
|