Skip to content

Commit e487747

Browse files
seefeldbclaude
andcommitted
feat(runner): Add ability to create cells without links and unify cell implementations
Implements the ability to create cells before they have a full link, allowing deferred link creation based on cause information. This also unifies the previous RegularCell and StreamCell implementations into a single CellImpl class. Key architectural changes: - Merged RegularCell and StreamCell into unified CellImpl class - Stream detection now happens at runtime via isStream() check - Both regular cells and streams share the same interface - .set() automatically handles stream vs regular cell behavior - Use NormalizedLink (with optional id/space) instead of requiring NormalizedFullLink - Cells can start with just { path: [] } and get id/space populated later - hasFullLink() checks for presence of both id and space fields - ensureLink() populates missing fields from cause information - Add .for(cause) method to associate causes with cells - Stores cause for later link creation - Supports optional { force } parameter for future extensions - Returns cell for method chaining - Deferred link creation using createRef() - ensureLink() creates entity IDs from causes when needed - Uses frame context or explicit .for() cause - Helpful error messages when context is insufficient - Update .key() to build paths incrementally - Works with partial links (just path[]) - Inherits cause from parent cell - Seamless transition to full links when needed API simplification: - Removed isStream() checks from client code (now handled internally) - Updated createCell() signature (removed noResolve parameter) - Consistent Cell interface regardless of stream/regular distinction Test coverage: - 23 new tests for optional link functionality - All 124 existing cell tests still passing - Full type checking passes Rollout plan updates: - Marked completed tasks in rollout-plan.md - Documented implementation approach This enables more flexible cell creation patterns where cells can be created and manipulated before their final identity is determined, which is essential for the recipe construction work. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent a5ad113 commit e487747

File tree

10 files changed

+545
-141
lines changed

10 files changed

+545
-141
lines changed

docs/specs/recipe-construction/rollout-plan.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,17 @@
2424
- [ ] Make passing the output of the second into the first work. Tricky
2525
because we're doing almost opposite expansions on the type.
2626
- [ ] Add ability to create a cell without a link yet.
27-
- [ ] Change constructor for RegularCell to make link optional
28-
- [ ] Add .for method to set a cause (within current context)
27+
- [x] Merge StreamCell into RegularCell and rename RegularCell to CellImpl
28+
- [x] Primarily this means changing `.set` to first read the resolved value
29+
to see whether we have a stream and then use the stream behavior instead
30+
of regular set.
31+
- [x] Change constructor for RegularCell to make link optional
32+
- [x] Add .for method to set a cause (within current context)
2933
- [ ] second parameter to make it optional/flexible:
3034
- [ ] ignores the .for if link already exists
3135
- [ ] adds extension if cause already exists (see tracker below)
3236
- [ ] Make .key work even if there is no cause yet.
33-
- [ ] Add some method to force creation of cause, which errors if in
37+
- [x] Add some method to force creation of cause, which errors if in
3438
non-handler context and no other information was given (as e.g. deriving
3539
nodes, which do have ids, after asking for them -- this walks the graph up
3640
until it hits the passed in cells)

packages/html/src/render.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ const bindProps = (
269269
const setProperty = options.setProp ?? setProp;
270270
const [cancel, addCancel] = useCancelGroup();
271271
for (const [propKey, propValue] of Object.entries(props)) {
272-
if (isCell(propValue) || isStream(propValue)) {
272+
if (isCell(propValue)) {
273273
// If prop is an event, we need to add an event listener
274274
if (isEventProp(propKey)) {
275275
const key = cleanEventProp(propKey);

0 commit comments

Comments
 (0)