fix: defer script restartSync until script.path lands (Path widget gated on $userStore + $workspaceStore)

This commit is contained in:
Diego Imbert
2026-06-05 21:32:20 +02:00
parent 75b8a08ce4
commit e4453e642c
2 changed files with 30 additions and 24 deletions
@@ -380,8 +380,34 @@
}
console.log('[draft-sync] ScriptBuilder: calling initContent', userDraftPath)
initContent(script.language, script.kind, template).finally(() => {
console.log('[draft-sync] ScriptBuilder: initContent finally → restartSync', userDraftPath)
UserDraft.restartSync('script', userDraftPath)
console.log('[draft-sync] ScriptBuilder: initContent finally', userDraftPath, {
pathAlreadySet: !!script.path
})
// The `Path` widget assigns `script.path` from its
// `$effect.pre` gated on `$workspaceStore + $userStore` —
// which on a HARD-REFRESH-then-first-nav can be unset when
// we get here, so we can't `restartSync` yet (its eventual
// path mutation would look like the user's first edit and
// POST). Wait for `script.path` to land instead; on
// subsequent in-app navs the stores are warm and this
// fires synchronously on the very first tick.
if (script.path) {
console.log('[draft-sync] ScriptBuilder: path already set → restartSync', userDraftPath)
UserDraft.restartSync('script', userDraftPath)
return
}
const stopWatch = $effect.root(() => {
$effect(() => {
if (!script.path) return
console.log('[draft-sync] ScriptBuilder: path settled → restartSync', userDraftPath, {
path: script.path
})
UserDraft.restartSync('script', userDraftPath)
// Tear down the scope so the watcher itself doesn't
// keep firing on future path edits.
queueMicrotask(stopWatch)
})
})
})
} else {
console.log('[draft-sync] ScriptBuilder: bootstrap SKIPPED (content non-empty)', userDraftPath)
@@ -22,7 +22,6 @@
type UserDraftHandle
} from '$lib/userDraft.svelte'
import { notifyDraftLoaded, notifyRestoredFromLocal } from '$lib/userDraftToast'
import { random_adj } from '$lib/components/random_positive_adjetive'
type EditableScript = NewScript & { draft_triggers?: Trigger[] }
@@ -163,34 +162,15 @@
const url = new URL(window.location.href)
url.searchParams.delete('new_draft')
window.history.replaceState(window.history.state, '', url.toString())
// Seed the path synchronously with the same `u/{user}/
// {adj}_script` shape the `Path` widget would auto-generate.
// Otherwise the widget mutates `script.path` on its own a
// few ticks AFTER our `restartSync` (the mutation chain runs
// in an `$effect.pre`), and that mutation looks like the
// user's first edit — firing an unwanted POST. With a path
// already set the widget's `initPath` branch that calls
// `reset()` is skipped entirely.
const username = $userStore?.username ?? ''
const ownerPrefix =
username && !username.includes('@')
? `u/${username}/`
: username
? `u/${username.split('@')[0].replace(/[^a-zA-Z0-9_]/g, '')}/`
: ''
const seededPath = ownerPrefix ? `${ownerPrefix}${random_adj()}_script` : ''
const empty: EditableScript = {
path: seededPath,
path: '',
summary: '',
description: '',
content: '',
language: 'bun',
schema: {}
} as unknown as EditableScript
// Path widget's `initPath` checks `initialPath` for the
// "reset to auto-name" decision — pass the same seeded path
// so it takes the "use initialPath" branch instead.
initialPath = seededPath
initialPath = ''
savedScript = structuredClone(empty)
console.log('[draft-sync] route: about to setDraftAndMeta(empty)', draftPath)
scriptHandle.setDraftAndMeta(empty, {})