fix type errors in autosave utils

keep the code around in case we revisit later
This commit is contained in:
Justin Edmund 2025-12-11 19:04:13 -08:00
parent 97bdccd218
commit 640a0d1c19
2 changed files with 59 additions and 8 deletions

View file

@ -70,6 +70,9 @@ export function createAutoSaveStore<TPayload, TResponse = unknown>(
function schedule() { function schedule() {
if (timer) clearTimeout(timer) if (timer) clearTimeout(timer)
if (typeof window !== 'undefined' && window.location.hostname === 'localhost') {
console.debug(`[AutoSave] Scheduled (${debounceMs}ms debounce)`)
}
timer = setTimeout(() => void run(), debounceMs) timer = setTimeout(() => void run(), debounceMs)
} }
@ -80,24 +83,44 @@ export function createAutoSaveStore<TPayload, TResponse = unknown>(
} }
const payload = opts.getPayload() const payload = opts.getPayload()
if (!payload) return if (!payload) {
if (typeof window !== 'undefined' && window.location.hostname === 'localhost') {
console.debug('[AutoSave] Skipped: getPayload returned null/undefined')
}
return
}
const hash = safeHash(payload) const hash = safeHash(payload)
if (lastSentHash && hash === lastSentHash) return if (lastSentHash && hash === lastSentHash) {
if (typeof window !== 'undefined' && window.location.hostname === 'localhost') {
console.debug('[AutoSave] Skipped: payload unchanged (hash match)')
}
return
}
if (controller) controller.abort() if (controller) controller.abort()
controller = new AbortController() controller = new AbortController()
if (typeof window !== 'undefined' && window.location.hostname === 'localhost') {
console.debug('[AutoSave] Saving...', { hashChanged: lastSentHash !== hash })
}
setStatus('saving') setStatus('saving')
lastError = null lastError = null
try { try {
const res = await opts.save(payload, { signal: controller.signal }) const res = await opts.save(payload, { signal: controller.signal })
lastSentHash = hash lastSentHash = hash
setStatus('saved') setStatus('saved')
if (typeof window !== 'undefined' && window.location.hostname === 'localhost') {
console.debug('[AutoSave] Saved successfully')
}
if (opts.onSaved) opts.onSaved(res, { prime }) if (opts.onSaved) opts.onSaved(res, { prime })
} catch (e: unknown) { } catch (e) {
if (e?.name === 'AbortError') { if (e instanceof Error && e.name === 'AbortError') {
// Newer save superseded this one // Newer save superseded this one
if (typeof window !== 'undefined' && window.location.hostname === 'localhost') {
console.debug('[AutoSave] Aborted: superseded by newer save')
}
return return
} }
if (typeof navigator !== 'undefined' && navigator.onLine === false) { if (typeof navigator !== 'undefined' && navigator.onLine === false) {
@ -105,7 +128,10 @@ export function createAutoSaveStore<TPayload, TResponse = unknown>(
} else { } else {
setStatus('error') setStatus('error')
} }
lastError = e?.message || 'Auto-save failed' lastError = e instanceof Error ? e.message : 'Auto-save failed'
if (typeof window !== 'undefined' && window.location.hostname === 'localhost') {
console.debug('[AutoSave] Error:', lastError)
}
} }
} }

View file

@ -10,6 +10,7 @@
lastSavedAt?: Date | string | null lastSavedAt?: Date | string | null
showTimestamp?: boolean showTimestamp?: boolean
compact?: boolean compact?: boolean
onclick?: () => void
} }
let { let {
@ -19,7 +20,8 @@
error: errorProp, error: errorProp,
lastSavedAt, lastSavedAt,
showTimestamp = true, showTimestamp = true,
compact = true compact = true,
onclick
}: Props = $props() }: Props = $props()
// Support both old subscription-based stores and new reactive values // Support both old subscription-based stores and new reactive values
@ -81,12 +83,19 @@
</script> </script>
{#if label} {#if label}
<div class="autosave-status" class:compact> <button
type="button"
class="autosave-status"
class:compact
class:clickable={!!onclick && status !== 'saving'}
onclick={onclick}
disabled={status === 'saving'}
>
{#if status === 'saving'} {#if status === 'saving'}
<span class="spinner" aria-hidden="true"></span> <span class="spinner" aria-hidden="true"></span>
{/if} {/if}
<span class="text">{label}</span> <span class="text">{label}</span>
</div> </button>
{/if} {/if}
<style lang="scss"> <style lang="scss">
@ -96,10 +105,26 @@
gap: 6px; gap: 6px;
color: $gray-40; color: $gray-40;
font-size: 0.875rem; font-size: 0.875rem;
background: none;
border: none;
padding: 0;
font-family: inherit;
&.compact { &.compact {
font-size: 0.75rem; font-size: 0.75rem;
} }
&.clickable {
cursor: pointer;
&:hover {
color: $gray-20;
}
}
&:disabled {
cursor: default;
}
} }
.spinner { .spinner {