Skip to content

Commit 7f89c78

Browse files
authored
Merge pull request #162 from get-convex/component-api
component api
2 parents 698c8c3 + eb1306d commit 7f89c78

30 files changed

+1585
-886
lines changed

.github/workflows/node.js.yml

Lines changed: 0 additions & 18 deletions
This file was deleted.

.github/workflows/test.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: Test and lint
2+
concurrency:
3+
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
4+
cancel-in-progress: true
5+
6+
on:
7+
push:
8+
branches: [main]
9+
pull_request:
10+
branches: ["**"]
11+
12+
jobs:
13+
check:
14+
name: Test and lint
15+
runs-on: ubuntu-latest
16+
timeout-minutes: 30
17+
18+
steps:
19+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
20+
21+
- name: Node setup
22+
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5
23+
with:
24+
cache-dependency-path: package.json
25+
node-version: "20.x"
26+
cache: "npm"
27+
28+
- name: Install and build
29+
run: |
30+
npm i
31+
npm run build
32+
- name: Publish package for testing branch
33+
run: npx pkg-pr-new publish || echo "Have you set up pkg-pr-new for this repo?"
34+
- name: Test
35+
run: |
36+
npm run test
37+
npm run typecheck
38+
npm run lint

.gitignore

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ dist-ssr
99
explorations
1010
node_modules
1111
.eslintcache
12-
# components are libraries!
13-
.package-lock.json
1412

1513
# this is a package-json-redirect stub dir, see https://github.com/andrewbranch/example-subpath-exports-ts-compat?tab=readme-ov-file
1614
frontend/package.json

.prettierrc.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"trailingComma": "all",
3+
"proseWrap": "always"
4+
}

CHANGELOG.md

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,26 @@
11
# Changelog
22

3+
## 0.3.0
4+
5+
- Adds /test and /\_generated/component.js entrypoints
6+
- Drops commonjs support
7+
- Improves source mapping for generated files
8+
- Changes to a statically generated component API
9+
310
## 0.2.8 alpha
411

5-
- Adds asynchronous events - wait for an event in a workflow, send
6-
events asynchronously - allows pause/resume, human-in-loop, etc.
12+
- Adds asynchronous events - wait for an event in a workflow, send events
13+
asynchronously - allows pause/resume, human-in-loop, etc.
714
- Supports nested workflows with step.runWorkflow.
815
- Surfaces return value of the workflow in the status
916
- You can start a workflow directly from the CLI / dashboard without having to
1017
make a mutation to call workflow.start:
1118
- `{ fn: "path/to/file:workflowName", args: { ...your workflow args } }`
12-
- Reduces read bandwidth when reading the journal after running many steps in parallel.
13-
- Simplifies the onComplete type requirement so you can accept a workflowId as a string.
14-
This helps when you have statically generated types which can't do branded strings.
19+
- Reduces read bandwidth when reading the journal after running many steps in
20+
parallel.
21+
- Simplifies the onComplete type requirement so you can accept a workflowId as a
22+
string. This helps when you have statically generated types which can't do
23+
branded strings.
1524
- Adds a /test entrypoint to make testing easier
1625
- Exports the `WorkflowCtx` and `WorkflowStep` types
1726
- Support for Math.random via seeded PRNG.
@@ -23,8 +32,8 @@
2332
- Batches the call to start steps
2433
- Adds the workflow name to the workpool execution for observability
2534
- Logs any error that shows up in the workflow body
26-
- Will call onComplete for Workflows with startAsync that fail
27-
on their first invocation.
35+
- Will call onComplete for Workflows with startAsync that fail on their first
36+
invocation.
2837
- Increases the max journal size from 1MB to 8MB
2938
- Adds the WorkflowId type to step.workflowId
3039
- Exposes /test entrypoint to make testing easier
@@ -39,5 +48,5 @@
3948

4049
- Call the onComplete handler for canceled workflows
4150
- Canceling is more graceful - canceled steps generally won't print errors
42-
- Allow `startAsync` to enqueue the starting of the workflow
43-
to allow starting many workflows safely.
51+
- Allow `startAsync` to enqueue the starting of the workflow to allow starting
52+
many workflows safely.

CONTRIBUTING.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ npm run test
2323

2424
```sh
2525
npm run clean
26-
npm run build
26+
npm ci
2727
npm pack
2828
```
2929

@@ -33,7 +33,7 @@ npm pack
3333
npm run release
3434
```
3535

36-
#### Alpha release
36+
or for alpha release:
3737

3838
```sh
3939
npm run alpha

README.md

Lines changed: 51 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,12 @@ export const userOnboarding = workflow.define({
7171
});
7272
```
7373

74-
This component adds durably executed _workflows_ to Convex. Combine Convex queries, mutations,
75-
and actions into long-lived workflows, and the system will always fully execute a workflow
76-
to completion.
74+
This component adds durably executed _workflows_ to Convex. Combine Convex
75+
queries, mutations, and actions into long-lived workflows, and the system will
76+
always fully execute a workflow to completion.
7777

78-
Open a [GitHub issue](https://github.com/get-convex/workflow/issues) with any feedback or bugs you find.
78+
Open a [GitHub issue](https://github.com/get-convex/workflow/issues) with any
79+
feedback or bugs you find.
7980

8081
## Installation
8182

@@ -89,16 +90,16 @@ Then, install the component within your `convex/convex.config.ts` file:
8990

9091
```ts
9192
// convex/convex.config.ts
92-
import workflow from "@convex-dev/workflow/convex.config";
93+
import workflow from "@convex-dev/workflow/convex.config.js";
9394
import { defineApp } from "convex/server";
9495

9596
const app = defineApp();
9697
app.use(workflow);
9798
export default app;
9899
```
99100

100-
Finally, create a workflow manager within your `convex/` folder, and point it
101-
to the installed component:
101+
Finally, create a workflow manager within your `convex/` folder, and point it to
102+
the installed component:
102103

103104
```ts
104105
// convex/index.ts
@@ -114,13 +115,13 @@ The first step is to define a workflow using `workflow.define()`. This function
114115
is designed to feel like a Convex action but with a few restrictions:
115116

116117
1. The workflow runs in the background, so it can't return a value.
117-
2. The workflow must be _deterministic_, so it should implement most of its logic
118-
by calling out to other Convex functions. We restrict access to some
118+
2. The workflow must be _deterministic_, so it should implement most of its
119+
logic by calling out to other Convex functions. We restrict access to some
119120
non-deterministic functions like `fetch` and `crypto`. Others we patch, such
120121
as `console` for logging, `Math.random()` (seeded PRNG) and `Date` for time.
121122

122-
Note: To help avoid type cycles, always annotate the return type of the `handler`
123-
with the return type of the workflow.
123+
Note: To help avoid type cycles, always annotate the return type of the
124+
`handler` with the return type of the workflow.
124125

125126
```ts
126127
export const exampleWorkflow = workflow.define({
@@ -157,8 +158,8 @@ export const exampleAction = internalAction({
157158

158159
### Starting a workflow
159160

160-
Once you've defined a workflow, you can start it from a mutation or action
161-
using `workflow.start()`.
161+
Once you've defined a workflow, you can start it from a mutation or action using
162+
`workflow.start()`.
162163

163164
```ts
164165
export const kickoffWorkflow = mutation({
@@ -228,8 +229,8 @@ export const handleOnComplete = mutation({
228229

229230
### Running steps in parallel
230231

231-
You can run steps in parallel by calling `step.runAction()` multiple times in
232-
a `Promise.all()` call.
232+
You can run steps in parallel by calling `step.runAction()` multiple times in a
233+
`Promise.all()` call.
233234

234235
```ts
235236
export const exampleWorkflow = workflow.define({
@@ -243,20 +244,21 @@ export const exampleWorkflow = workflow.define({
243244
});
244245
```
245246

246-
Note: The workflow will not proceed until all steps fired off at once have completed.
247+
Note: The workflow will not proceed until all steps fired off at once have
248+
completed.
247249

248250
### Specifying retry behavior
249251

250252
Sometimes actions fail due to transient errors, whether it was an unreliable
251253
third-party API or a server restart. You can have the workflow automatically
252-
retry actions using best practices (exponential backoff & jitter).
253-
By default there are no retries, and the workflow will fail.
254+
retry actions using best practices (exponential backoff & jitter). By default
255+
there are no retries, and the workflow will fail.
254256

255257
You can specify default retry behavior for all workflows on the WorkflowManager,
256258
or override it on a per-workflow basis.
257259

258-
You can also specify a custom retry behavior per-step, to opt-out of retries
259-
for actions that may want at-most-once semantics.
260+
You can also specify a custom retry behavior per-step, to opt-out of retries for
261+
actions that may want at-most-once semantics.
260262

261263
Workpool options:
262264

@@ -270,8 +272,8 @@ If you specify any of these, it will override the
270272
- `retryActionsByDefault`: Whether to retry actions, by default is false.
271273
- If you specify a retry behavior at the step level, it will always retry.
272274

273-
At the step level, you can also specify `true` or `false` to disable or use
274-
the default policy.
275+
At the step level, you can also specify `true` or `false` to disable or use the
276+
default policy.
275277

276278
```ts
277279
const workflow = new WorkflowManager(components.workflow, {
@@ -306,11 +308,10 @@ export const exampleWorkflow = workflow.define({
306308
### Specifying step parallelism
307309

308310
You can specify how many steps can run in parallel by setting the
309-
`maxParallelism` workpool option. It has a reasonable default.
310-
On the free tier, you should not exceed 20, otherwise your other scheduled
311-
functions may become delayed while competing for available functions with your
312-
workflow steps.
313-
On a Pro account, you should not exceed 100 across all your workflows and workpools.
311+
`maxParallelism` workpool option. It has a reasonable default. On the free tier,
312+
you should not exceed 20, otherwise your other scheduled functions may become
313+
delayed while competing for available functions with your workflow steps. On a
314+
Pro account, you should not exceed 100 across all your workflows and workpools.
314315
If you want to do a lot of work in parallel, you should employ batching, where
315316
each workflow operates on a batch of work, e.g. scraping a list of links instead
316317
of one link per workflow.
@@ -328,8 +329,8 @@ const workflow = new WorkflowManager(components.workflow, {
328329

329330
### Checking a workflow's status
330331

331-
The `workflow.start()` method returns a `WorkflowId`, which can then be used for querying
332-
a workflow's status.
332+
The `workflow.start()` method returns a `WorkflowId`, which can then be used for
333+
querying a workflow's status.
333334

334335
```ts
335336
export const kickoffWorkflow = action({
@@ -349,8 +350,9 @@ export const kickoffWorkflow = action({
349350

350351
### Canceling a workflow
351352

352-
You can cancel a workflow with `workflow.cancel()`, halting the workflow's execution immmediately.
353-
In-progress calls to `step.runAction()`, however, will finish executing.
353+
You can cancel a workflow with `workflow.cancel()`, halting the workflow's
354+
execution immmediately. In-progress calls to `step.runAction()`, however, will
355+
finish executing.
354356

355357
```ts
356358
export const kickoffWorkflow = action({
@@ -370,8 +372,9 @@ export const kickoffWorkflow = action({
370372

371373
### Cleaning up a workflow
372374

373-
After a workflow has completed, you can clean up its storage with `workflow.cleanup()`.
374-
Completed workflows are not automatically cleaned up by the system.
375+
After a workflow has completed, you can clean up its storage with
376+
`workflow.cleanup()`. Completed workflows are not automatically cleaned up by
377+
the system.
375378

376379
```ts
377380
export const kickoffWorkflow = action({
@@ -402,8 +405,8 @@ export const kickoffWorkflow = action({
402405

403406
You can specify a custom name for a step by passing a `name` option to the step.
404407

405-
This allows the events emitted to your logs to be more descriptive.
406-
By default it uses the `file/folder:function` name.
408+
This allows the events emitted to your logs to be more descriptive. By default
409+
it uses the `file/folder:function` name.
407410

408411
```ts
409412
export const exampleWorkflow = workflow.define({
@@ -418,9 +421,11 @@ export const exampleWorkflow = workflow.define({
418421

419422
### Circular dependencies
420423

421-
Having the return value of workflows depend on other Convex functions can lead to circular dependencies due to the
422-
`internal.foo.bar` way of specifying functions. The way to fix this is to explicitly type the return value of the
423-
workflow. When in doubt, add return types to more `handler` functions, like this:
424+
Having the return value of workflows depend on other Convex functions can lead
425+
to circular dependencies due to the `internal.foo.bar` way of specifying
426+
functions. The way to fix this is to explicitly type the return value of the
427+
workflow. When in doubt, add return types to more `handler` functions, like
428+
this:
424429

425430
```diff
426431
export const supportAgentWorkflow = workflow.define({
@@ -441,8 +446,8 @@ workflow. When in doubt, add return types to more `handler` functions, like this
441446

442447
### More concise workflows
443448

444-
To avoid the noise of `internal.foo.*` syntax, you can use a variable.
445-
For instance, if you define all your steps in `convex/steps.ts`, you can do this:
449+
To avoid the noise of `internal.foo.*` syntax, you can use a variable. For
450+
instance, if you define all your steps in `convex/steps.ts`, you can do this:
446451

447452
```diff
448453
const s = internal.steps;
@@ -469,15 +474,16 @@ Here are a few limitations to keep in mind:
469474
mutation apply and limit the number and size of steps you can perform to 16MiB
470475
(including the workflow state overhead). See more about mutation limits here:
471476
https://docs.convex.dev/production/state/limits#transactions
472-
- We currently do not collect backtraces from within function calls from workflows.
477+
- We currently do not collect backtraces from within function calls from
478+
workflows.
473479
- If you need to use side effects like `fetch` or use cryptographic randomness,
474480
you'll need to do that in a step, not in the workflow definition.
475481
- `Math.random` is deterministic and not suitable for cryptographic use. It is,
476482
however, useful for sharding, jitter, and other pseudo-random applications.
477483
- If the implementation of the workflow meaningfully changes (steps added,
478-
removed, or reordered) then it will fail with a determinism violation.
479-
The implementation should stay stable for the lifetime of active workflows.
480-
See [this issue](https://github.com/get-convex/workflow/issues/35) for ideas
481-
on how to make this better.
484+
removed, or reordered) then it will fail with a determinism violation. The
485+
implementation should stay stable for the lifetime of active workflows. See
486+
[this issue](https://github.com/get-convex/workflow/issues/35) for ideas on
487+
how to make this better.
482488

483489
<!-- END: Include on https://convex.dev/components -->

convex.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
{
2-
"functions": "example/convex"
2+
"functions": "example/convex",
3+
"$schema": "./node_modules/convex/schemas/convex.schema.json",
4+
"codegen": {
5+
"legacyComponentApi": true
6+
}
37
}

0 commit comments

Comments
 (0)