Skip to content

Commit 03b312b

Browse files
committed
More blog post updates
1 parent 61d2dd3 commit 03b312b

File tree

1 file changed

+60
-2
lines changed

1 file changed

+60
-2
lines changed

src/blog/directives-and-the-platform-boundary.md

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,64 @@ Even durable tasks, caching strategies, and execution locations are now being en
192192

193193
---
194194

195+
### Considering APIs instead of directives for option‑rich features
196+
197+
Durable execution is a good example (e.g., `'use workflow'`, `'use step'`), but the point is general: directives can collapse behavior to a boolean, while many features benefit from options and room to evolve. Compilers and transforms can support either surface; this is about choosing the right one for longevity and clarity.
198+
199+
```js
200+
'use workflow'
201+
'use step'
202+
```
203+
204+
One option: an explicit API with provenance and options:
205+
206+
```js
207+
import { workflow, step } from '@workflows/workflow'
208+
209+
export const sendEmail = workflow(
210+
async (input) => {
211+
/* ... */
212+
},
213+
{ retries: 3, timeout: '1m' }
214+
)
215+
216+
export const handle = step(
217+
'fetchUser',
218+
async () => {
219+
/* ... */
220+
},
221+
{ cache: 60 }
222+
)
223+
```
224+
225+
Function forms can be just as AST/transform‑friendly as directives, and they carry provenance (imports) and type‑safety.
226+
227+
Another option is to inject a global once and type it:
228+
229+
```ts
230+
// bootstrap once
231+
globalThis.workflow = createWorkflow()
232+
// global types (e.g., global.d.ts)
233+
declare global {
234+
var workflow: typeof import('@workflows/workflow').workflow
235+
}
236+
```
237+
238+
Usage stays API‑shaped, without directives:
239+
240+
```ts
241+
export const task = workflow(
242+
async () => {
243+
/* ... */
244+
},
245+
{ retries: 5 }
246+
)
247+
```
248+
249+
Compilers that extend ergonomics are great. Just look at JSX is a useful precedent! We just need to do it carefully and responsibly: extend via APIs with clear provenance and types, not top‑level strings that look like the language. These are options, not prescriptions.
250+
251+
---
252+
195253
### Subtle forms of lock‑in can emerge
196254

197255
Even when there is no bad intent, directives create lock in by design:
@@ -222,7 +280,7 @@ If multiple frameworks truly want shared primitives, a responsible path is:
222280
- Propose primitives to TC39 when appropriate
223281
- Keep non standard features clearly scoped to API space, not language space
224282

225-
Directives should be rare, stable, and standardized—used judiciously rather than proliferating across vendors.
283+
Directives should be rare, stable, standardized and especially used judiciously rather than proliferating across vendors.
226284

227285
---
228286

@@ -234,7 +292,7 @@ It’s tempting to compare criticism of directives to the early skepticism aroun
234292

235293
### The bottom line
236294

237-
Framework directives might feel like DX magic today, but the current trend risks a more fragmented futuredialects defined not by standards, but by tools.
295+
Framework directives might feel like DX magic today, but the current trend risks a more fragmented future consisting of dialects defined not by standards, but by tools.
238296

239297
We can aim for clearer boundaries.
240298

0 commit comments

Comments
 (0)