@danieljvdm/dev-kit 0.11.3 → 0.13.0
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/README.md +111 -78
- package/dev-kit.example.jsonc +0 -4
- package/package.json +10 -6
- package/schema/dev-kit.schema.json +1 -46
- package/skills/build-effect-apis/SKILL.md +77 -0
- package/skills/build-effect-apis/agents/openai.yaml +4 -0
- package/skills/build-effect-apis/references/cloudflare-workers.md +71 -0
- package/skills/build-effect-apis/references/effect-atom-client.md +161 -0
- package/skills/build-effect-apis/references/effect-atom-lifecycle.md +78 -0
- package/skills/build-effect-apis/references/effect-atom-testing.md +74 -0
- package/skills/build-effect-apis/references/runtime-assembly.md +56 -0
- package/skills/build-effect-apis/references/server-and-middleware.md +174 -0
- package/skills/build-effect-apis/references/shared-contracts.md +108 -0
- package/skills/build-effect-apis/references/tanstack-start.md +86 -0
- package/skills/build-effect-apis/references/verification.md +50 -0
- package/skills/build-effect-clis/SKILL.md +61 -0
- package/skills/build-effect-clis/agents/openai.yaml +4 -0
- package/skills/build-effect-clis/references/command-design.md +93 -0
- package/skills/build-effect-clis/references/entrypoints-and-testing.md +59 -0
- package/skills/build-effect-clis/references/processes-and-platform.md +73 -0
- package/skills/dev-kit/SKILL.md +77 -48
- package/skills/effect-architecture-audit/SKILL.md +26 -0
- package/skills/effect-architecture-audit/agents/openai.yaml +4 -0
- package/skills/effect-architecture-audit/references/service-and-boundary-audit.md +150 -0
- package/skills/effect-ts/SKILL.md +21 -256
- package/skills/effect-ts/agents/openai.yaml +3 -3
- package/skills/testing/SKILL.md +5 -0
- package/src/catalog-manager.ts +16 -17
- package/src/catalog.ts +71 -16
- package/src/effect-source.ts +46 -24
- package/src/effect-tsgo.ts +86 -24
- package/src/gitignore.ts +5 -5
- package/src/index.ts +3 -6
- package/src/manifest.ts +0 -34
- package/src/node-symbolic-link.ts +2 -2
- package/src/oxfmt.js +5 -0
- package/src/oxfmt.ts +5 -0
- package/src/oxlint.js +5 -0
- package/src/oxlint.ts +5 -0
- package/src/package-skill-source.ts +51 -59
- package/src/path-digest.ts +7 -7
- package/src/project-package.ts +8 -7
- package/src/project-process-lock.ts +17 -12
- package/src/project-state.ts +1 -1
- package/src/skill-manager.ts +18 -16
- package/src/skill-selector.ts +12 -0
- package/src/sync.ts +181 -131
- package/src/tool-ignore-patterns.js +9 -0
- package/src/tool-ignore-patterns.ts +15 -0
- package/src/vendor.ts +67 -61
- package/src/vite-plus-dependency.ts +10 -11
- package/src/vite-plus-hooks.ts +24 -14
- package/src/vite-plus-quality.ts +21 -172
- package/src/vite-plus.js +81 -0
- package/src/vite-plus.ts +102 -0
- package/templates/AGENTS.md +1 -1
- package/skills/effect-ts/UPSTREAM.md +0 -28
- package/skills/effect-ts/references/atom-cache-lifecycle.md +0 -78
- package/skills/effect-ts/references/atom-http-and-invalidation.md +0 -97
- package/skills/effect-ts/references/atom-tanstack-start.md +0 -69
- package/skills/effect-ts/references/atom-testing.md +0 -67
- package/skills/effect-ts/references/audit-services.md +0 -144
- package/skills/effect-ts/references/features.md +0 -525
- package/skills/effect-ts/references/guide-atom-data-fetching.md +0 -44
- package/skills/effect-ts/references/guide-cli.md +0 -107
- package/skills/effect-ts/references/guide-datetime.md +0 -72
- package/skills/effect-ts/references/guide-effect.md +0 -440
- package/skills/effect-ts/references/guide-error-handling.md +0 -565
- package/skills/effect-ts/references/guide-http-boundaries.md +0 -55
- package/skills/effect-ts/references/guide-layers.md +0 -989
- package/skills/effect-ts/references/guide-observability.md +0 -746
- package/skills/effect-ts/references/guide-retries.md +0 -434
- package/skills/effect-ts/references/guide-schedule.md +0 -343
- package/skills/effect-ts/references/guide-schema.md +0 -664
- package/skills/effect-ts/references/guide-sql.md +0 -536
- package/skills/effect-ts/references/guide-testing.md +0 -532
- package/skills/effect-ts/references/guide-type-safety-and-boundaries.md +0 -131
- package/skills/effect-ts/references/version-and-source.md +0 -86
- package/templates/vite-plus/vite.config.ts +0 -22
|
@@ -1,343 +0,0 @@
|
|
|
1
|
-
# Schedule Guide
|
|
2
|
-
|
|
3
|
-
Use Effect test services and `TestClock` for schedule and polling tests. Keep
|
|
4
|
-
time authority in the Effect environment and avoid wall-clock sleeps.
|
|
5
|
-
|
|
6
|
-
This guide targets the `Schedule` API in Effect v4 beta.102.
|
|
7
|
-
|
|
8
|
-
Key source files:
|
|
9
|
-
|
|
10
|
-
- `packages/effect/src/Schedule.ts`
|
|
11
|
-
- `packages/effect/test/Schedule.test.ts`
|
|
12
|
-
- `packages/effect/src/Effect.ts`
|
|
13
|
-
- `packages/effect/src/Stream.ts`
|
|
14
|
-
|
|
15
|
-
## Mental Model
|
|
16
|
-
|
|
17
|
-
`Schedule<Output, Input, Error, Env>` describes whether an operation should
|
|
18
|
-
recur, how long it should wait, what it emits as schedule output, what input it
|
|
19
|
-
examines, and which services or failures the policy itself introduces.
|
|
20
|
-
|
|
21
|
-
Schedules drive:
|
|
22
|
-
|
|
23
|
-
- `Effect.retry` for failed effects
|
|
24
|
-
- `Effect.repeat` for successful effects
|
|
25
|
-
- `Effect.schedule` for scheduled execution
|
|
26
|
-
- `Stream.fromSchedule` and other stream recurrence APIs
|
|
27
|
-
|
|
28
|
-
Prefer a schedule over mutable counters, hand-written sleep loops, or recursive
|
|
29
|
-
retry code.
|
|
30
|
-
|
|
31
|
-
## Preferred Rule
|
|
32
|
-
|
|
33
|
-
Start with the smallest policy that expresses the requirement:
|
|
34
|
-
|
|
35
|
-
- count only: `Schedule.recurs`
|
|
36
|
-
- constant spacing: `Schedule.spaced`
|
|
37
|
-
- interval cadence: `Schedule.fixed` or `Schedule.windowed`
|
|
38
|
-
- growing backoff: `Schedule.exponential` or `Schedule.fibonacci`
|
|
39
|
-
- elapsed-time or count bound: `Schedule.upTo`
|
|
40
|
-
- phase change: `Schedule.andThen`
|
|
41
|
-
- parallel policy combination: `Schedule.max` or `Schedule.min`
|
|
42
|
-
- custom delay: `Schedule.modifyDelay` or `Schedule.addDelay`
|
|
43
|
-
|
|
44
|
-
Keep retryability classification in the typed error model. Keep timing,
|
|
45
|
-
attempt limits, and backoff in the schedule.
|
|
46
|
-
|
|
47
|
-
## Retry, Repeat, And Schedule
|
|
48
|
-
|
|
49
|
-
Use the operator that matches the control flow:
|
|
50
|
-
|
|
51
|
-
```ts
|
|
52
|
-
const retried = Effect.retry(loadRemote, retryPolicy);
|
|
53
|
-
const repeated = Effect.repeat(refreshCache, refreshPolicy);
|
|
54
|
-
const scheduled = Effect.schedule(runJob, nightly);
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
- `retry` steps the schedule when the effect fails; the schedule input is the
|
|
58
|
-
typed error.
|
|
59
|
-
- `repeat` steps the schedule after success; the schedule input is the success
|
|
60
|
-
value.
|
|
61
|
-
- `schedule` applies schedule timing to an effect directly.
|
|
62
|
-
|
|
63
|
-
## Core Constructors
|
|
64
|
-
|
|
65
|
-
### `Schedule.recurs`
|
|
66
|
-
|
|
67
|
-
Use `recurs(n)` for at most `n` recurrences. The first effect evaluation occurs
|
|
68
|
-
before the schedule is stepped, so `recurs(3)` permits one initial attempt and
|
|
69
|
-
up to three retries.
|
|
70
|
-
|
|
71
|
-
```ts
|
|
72
|
-
const retryThreeTimes = Schedule.recurs(3);
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
### `Schedule.forever`
|
|
76
|
-
|
|
77
|
-
`forever` recurs indefinitely with no delay. Combine it with delay or bounding
|
|
78
|
-
combinators unless a tight loop is intentional.
|
|
79
|
-
|
|
80
|
-
```ts
|
|
81
|
-
const unbounded = Schedule.forever;
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
### `Schedule.spaced`
|
|
85
|
-
|
|
86
|
-
Use `spaced` when each delay starts after the preceding action completes.
|
|
87
|
-
|
|
88
|
-
```ts
|
|
89
|
-
const pollEverySecond = Schedule.spaced("1 second");
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### `Schedule.fixed`
|
|
93
|
-
|
|
94
|
-
Use `fixed` for a regular cadence that accounts for the time spent running the
|
|
95
|
-
action. This differs from naïve spacing when the action itself is slow.
|
|
96
|
-
|
|
97
|
-
```ts
|
|
98
|
-
const everyMinute = Schedule.fixed("1 minute");
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
### `Schedule.windowed`
|
|
102
|
-
|
|
103
|
-
Use `windowed` to align work to the nearest interval boundary.
|
|
104
|
-
|
|
105
|
-
```ts
|
|
106
|
-
const flushOnTenSecondWindows = Schedule.windowed("10 seconds");
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
### `Schedule.duration`
|
|
110
|
-
|
|
111
|
-
`duration` recurs once after the given delay, then completes.
|
|
112
|
-
|
|
113
|
-
```ts
|
|
114
|
-
const onceAfterOneSecond = Schedule.duration("1 second");
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
### `Schedule.during`
|
|
118
|
-
|
|
119
|
-
`during` recurs only within an elapsed-time window.
|
|
120
|
-
|
|
121
|
-
```ts
|
|
122
|
-
const forThirtySeconds = Schedule.during("30 seconds");
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
### `Schedule.cron`
|
|
126
|
-
|
|
127
|
-
Use `cron` for calendar-based wall-clock schedules. String parsing can fail
|
|
128
|
-
with `CronParseError`, so keep that failure visible where the expression is not
|
|
129
|
-
a trusted constant.
|
|
130
|
-
|
|
131
|
-
```ts
|
|
132
|
-
const nightly = Schedule.cron("0 0 * * *");
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
## Backoff
|
|
136
|
-
|
|
137
|
-
### `Schedule.exponential`
|
|
138
|
-
|
|
139
|
-
Use exponential backoff for transient external failures.
|
|
140
|
-
|
|
141
|
-
```ts
|
|
142
|
-
const backoff = Schedule.exponential("100 millis", 2);
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
Bound the policy explicitly:
|
|
146
|
-
|
|
147
|
-
```ts
|
|
148
|
-
const boundedBackoff = Schedule.exponential("100 millis").pipe(
|
|
149
|
-
Schedule.upTo({ duration: "30 seconds", times: 6 }),
|
|
150
|
-
Schedule.jittered,
|
|
151
|
-
);
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
### `Schedule.fibonacci`
|
|
155
|
-
|
|
156
|
-
Use Fibonacci backoff when growth should be gentler than exponential.
|
|
157
|
-
|
|
158
|
-
```ts
|
|
159
|
-
const fibonacciBackoff = Schedule.fibonacci("100 millis").pipe(Schedule.upTo({ times: 6 }));
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
### `Schedule.jittered`
|
|
163
|
-
|
|
164
|
-
Use jitter for distributed clients, workers, or polling loops that might
|
|
165
|
-
otherwise synchronize their retries.
|
|
166
|
-
|
|
167
|
-
```ts
|
|
168
|
-
const jittered = Schedule.exponential("200 millis").pipe(Schedule.jittered);
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
## Bounding Policies
|
|
172
|
-
|
|
173
|
-
Use `Schedule.upTo` to bound an existing schedule by recurrence count, elapsed
|
|
174
|
-
duration, or both. When both are present, the first reached limit stops the
|
|
175
|
-
schedule.
|
|
176
|
-
|
|
177
|
-
```ts
|
|
178
|
-
const bounded = Schedule.spaced("1 second").pipe(
|
|
179
|
-
Schedule.upTo({
|
|
180
|
-
duration: "20 seconds",
|
|
181
|
-
times: 5,
|
|
182
|
-
}),
|
|
183
|
-
);
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
Prefer `upTo` over rebuilding count and elapsed-time checks with mutable state.
|
|
187
|
-
|
|
188
|
-
## Sequencing Policies
|
|
189
|
-
|
|
190
|
-
### `Schedule.andThen`
|
|
191
|
-
|
|
192
|
-
Use `andThen` when one policy should complete before another begins.
|
|
193
|
-
|
|
194
|
-
```ts
|
|
195
|
-
const quickThenSlow = Schedule.exponential("100 millis").pipe(
|
|
196
|
-
Schedule.upTo({ times: 3 }),
|
|
197
|
-
Schedule.andThen(Schedule.spaced("5 seconds").pipe(Schedule.upTo({ times: 5 }))),
|
|
198
|
-
);
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
This is the v4 replacement for older examples that used `Schedule.either` to
|
|
202
|
-
describe retry phases.
|
|
203
|
-
|
|
204
|
-
### `Schedule.andThenResult`
|
|
205
|
-
|
|
206
|
-
Use `andThenResult` when downstream logic needs to distinguish which phase
|
|
207
|
-
produced the current output. It emits a `Result` carrying the phase output.
|
|
208
|
-
|
|
209
|
-
## Combining Policies
|
|
210
|
-
|
|
211
|
-
### `Schedule.max`
|
|
212
|
-
|
|
213
|
-
`max([...])` recurs only while every schedule can recur and waits for the
|
|
214
|
-
largest delay. Use it to enforce several stop conditions while retaining the
|
|
215
|
-
slowest applicable cadence.
|
|
216
|
-
|
|
217
|
-
```ts
|
|
218
|
-
const countedBackoff = Schedule.max([Schedule.exponential("100 millis"), Schedule.recurs(5)]);
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
### `Schedule.min`
|
|
222
|
-
|
|
223
|
-
`min([...])` continues while at least one schedule can recur and uses the
|
|
224
|
-
smallest available delay. Use it only when that "any policy may continue"
|
|
225
|
-
behavior is intended.
|
|
226
|
-
|
|
227
|
-
```ts
|
|
228
|
-
const fastestAvailable = Schedule.min([Schedule.spaced("1 second"), Schedule.spaced("5 seconds")]);
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
Do not treat `max` and `min` as ordinary numeric delay combinators without
|
|
232
|
-
considering their completion semantics.
|
|
233
|
-
|
|
234
|
-
## Transforming Delays And Outputs
|
|
235
|
-
|
|
236
|
-
### `Schedule.modifyDelay`
|
|
237
|
-
|
|
238
|
-
Use `modifyDelay` to replace the computed delay from schedule metadata.
|
|
239
|
-
|
|
240
|
-
```ts
|
|
241
|
-
const cappedDelay = Schedule.exponential("100 millis").pipe(
|
|
242
|
-
Schedule.modifyDelay(({ duration }) =>
|
|
243
|
-
Effect.succeed(Duration.min(duration, Duration.seconds(5))),
|
|
244
|
-
),
|
|
245
|
-
);
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
### `Schedule.addDelay`
|
|
249
|
-
|
|
250
|
-
Use `addDelay` to add an effectful duration to the schedule's existing delay.
|
|
251
|
-
For retries, inspect the typed error through `metadata.input`.
|
|
252
|
-
|
|
253
|
-
```ts
|
|
254
|
-
const serverAware = Schedule.spaced("1 second").pipe(
|
|
255
|
-
Schedule.setInputType<RateLimitedError>(),
|
|
256
|
-
Schedule.addDelay(({ input: error }) =>
|
|
257
|
-
error._tag === "RateLimited" ? Effect.succeed(error.retryAfter) : Effect.succeed(Duration.zero),
|
|
258
|
-
),
|
|
259
|
-
);
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
### `Schedule.map`
|
|
263
|
-
|
|
264
|
-
Use `map` to transform schedule output without changing its completion or
|
|
265
|
-
timing behavior.
|
|
266
|
-
|
|
267
|
-
### `Schedule.passthrough`
|
|
268
|
-
|
|
269
|
-
Use `passthrough` when the schedule should emit its inputs rather than its
|
|
270
|
-
native outputs.
|
|
271
|
-
|
|
272
|
-
### `Schedule.tap`
|
|
273
|
-
|
|
274
|
-
Use `tap` for attempt-level observability. The callback receives metadata
|
|
275
|
-
including `input`, `output`, `attempt`, `elapsed`, and `duration`.
|
|
276
|
-
|
|
277
|
-
```ts
|
|
278
|
-
const observed = Schedule.exponential("100 millis").pipe(
|
|
279
|
-
Schedule.setInputType<TransientError>(),
|
|
280
|
-
Schedule.upTo({ times: 5 }),
|
|
281
|
-
Schedule.tap(({ attempt, duration, input }) =>
|
|
282
|
-
Effect.logWarning("retry.scheduled").pipe(
|
|
283
|
-
Effect.annotateLogs({
|
|
284
|
-
attempt,
|
|
285
|
-
delay: String(duration),
|
|
286
|
-
errorTag: input._tag,
|
|
287
|
-
}),
|
|
288
|
-
),
|
|
289
|
-
),
|
|
290
|
-
);
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
## Advanced Construction And Inspection
|
|
294
|
-
|
|
295
|
-
Use these only when the standard constructors and combinators do not express
|
|
296
|
-
the policy:
|
|
297
|
-
|
|
298
|
-
- `Schedule.fromStep` and `Schedule.fromStepWithMetadata` for custom schedules
|
|
299
|
-
- `Schedule.toStep` and `Schedule.toStepWithMetadata` for manual stepping
|
|
300
|
-
- `Schedule.toStepWithSleep` when a low-level consumer should apply delays
|
|
301
|
-
- `Schedule.setInputType<T>()` when adapting an input-independent schedule
|
|
302
|
-
|
|
303
|
-
The old collection helpers `collectInputs`, `collectOutputs`, `collectWhile`,
|
|
304
|
-
`delays`, and `reduce` are not part of the current v4 Schedule API. Use
|
|
305
|
-
`map`, `tap`, explicit stepping, or a purpose-built accumulator instead.
|
|
306
|
-
|
|
307
|
-
## Testing Schedules
|
|
308
|
-
|
|
309
|
-
- Use `TestClock` or the test clock provided by `@effect/vitest`.
|
|
310
|
-
- Advance virtual time explicitly.
|
|
311
|
-
- Assert retry counts, outputs, and final typed failures.
|
|
312
|
-
- Use low-level stepping only when the schedule itself is the unit under test.
|
|
313
|
-
- Do not add wall-clock sleeps or timing tolerances to hide nondeterminism.
|
|
314
|
-
|
|
315
|
-
## Best Practices
|
|
316
|
-
|
|
317
|
-
1. Express recurrence policy with `Schedule`, not custom loops.
|
|
318
|
-
2. Bound production retries by count, duration, or both.
|
|
319
|
-
3. Add jitter for distributed retry behavior.
|
|
320
|
-
4. Use `andThen` for phases and `max`/`min` only for their documented combined
|
|
321
|
-
completion semantics.
|
|
322
|
-
5. Inspect typed errors through schedule metadata instead of broadening them to
|
|
323
|
-
`unknown`.
|
|
324
|
-
6. Instrument meaningful attempts with `Schedule.tap`.
|
|
325
|
-
7. Test timing with `TestClock`.
|
|
326
|
-
8. Verify constructors and combinators against the target repository's
|
|
327
|
-
installed Effect version.
|
|
328
|
-
|
|
329
|
-
## Anti-Patterns
|
|
330
|
-
|
|
331
|
-
- mutable retry counters embedded in business workflows
|
|
332
|
-
- `Effect.forever` plus hand-written sleeps as a Schedule substitute
|
|
333
|
-
- unbounded retries for external calls without an explicit operational reason
|
|
334
|
-
- retrying authorization, validation, or other non-transient failures
|
|
335
|
-
- using removed v4 beta APIs copied from an older guide
|
|
336
|
-
- wall-clock schedule tests
|
|
337
|
-
|
|
338
|
-
## Canonical Source To Study
|
|
339
|
-
|
|
340
|
-
- `packages/effect/src/Schedule.ts`
|
|
341
|
-
- `packages/effect/test/Schedule.test.ts`
|
|
342
|
-
- `packages/effect/src/Effect.ts`
|
|
343
|
-
- `packages/effect/src/Stream.ts`
|