* refactor(sync): extract backend interface, adapt gcal module
Problem: :Pending sync hardcodes Google Calendar — M.sync() does
pcall(require, 'pending.sync.gcal') and calls gcal.sync() directly.
The config has a flat gcal field. This prevents adding new sync backends
without modifying init.lua.
Solution: Define a backend interface contract (name, auth, sync, health
fields), refactor :Pending sync to dispatch via require('pending.sync.'
.. backend_name), add sync table to config with legacy gcal migration,
rename gcal.authorize to gcal.auth, add gcal.health for checkhealth,
and add tab completion for backend names and actions.
* docs(sync): update vimdoc for backend interface
Problem: Vimdoc documents :Pending sync as a bare command that pushes
to Google Calendar, with no mention of backends or the sync table config.
Solution: Update :Pending sync section to show {backend} [{action}]
syntax with examples, add SYNC BACKENDS section documenting the interface
contract, update config example to use sync.gcal, document legacy gcal
migration, and update health check description.
* test(sync): add backend dispatch tests
Problem: No test coverage for sync dispatch logic, config migration,
or gcal module interface conformance.
Solution: Add spec/sync_spec.lua with tests for: bare sync errors,
empty backend errors, unknown backend errors, unknown action errors,
default-to-sync routing, explicit sync/auth routing, legacy gcal config
migration, explicit sync.gcal precedence, and gcal module interface
fields (name, auth, sync, health).
65 lines
2 KiB
Lua
65 lines
2 KiB
Lua
local M = {}
|
|
|
|
---@return nil
|
|
function M.check()
|
|
vim.health.start('pending.nvim')
|
|
|
|
local ok, config = pcall(require, 'pending.config')
|
|
if not ok then
|
|
vim.health.error('Failed to load pending.config')
|
|
return
|
|
end
|
|
|
|
local cfg = config.get()
|
|
vim.health.ok('Config loaded')
|
|
vim.health.info('Data path: ' .. cfg.data_path)
|
|
|
|
local data_dir = vim.fn.fnamemodify(cfg.data_path, ':h')
|
|
if vim.fn.isdirectory(data_dir) == 1 then
|
|
vim.health.ok('Data directory exists: ' .. data_dir)
|
|
else
|
|
vim.health.warn('Data directory does not exist yet: ' .. data_dir)
|
|
end
|
|
|
|
if vim.fn.filereadable(cfg.data_path) == 1 then
|
|
local store_ok, store = pcall(require, 'pending.store')
|
|
if store_ok then
|
|
local load_ok, err = pcall(store.load)
|
|
if load_ok then
|
|
local tasks = store.tasks()
|
|
vim.health.ok('Data file loaded: ' .. #tasks .. ' tasks')
|
|
local recur = require('pending.recur')
|
|
local invalid_count = 0
|
|
for _, task in ipairs(tasks) do
|
|
if task.recur and not recur.validate(task.recur) then
|
|
invalid_count = invalid_count + 1
|
|
vim.health.warn('Task ' .. task.id .. ' has invalid recurrence spec: ' .. task.recur)
|
|
end
|
|
end
|
|
if invalid_count == 0 then
|
|
vim.health.ok('All recurrence specs are valid')
|
|
end
|
|
else
|
|
vim.health.error('Failed to load data file: ' .. tostring(err))
|
|
end
|
|
end
|
|
else
|
|
vim.health.info('No data file yet (will be created on first save)')
|
|
end
|
|
|
|
local sync_paths = vim.fn.globpath(vim.o.runtimepath, 'lua/pending/sync/*.lua', false, true)
|
|
if #sync_paths == 0 then
|
|
vim.health.info('No sync backends found')
|
|
else
|
|
for _, path in ipairs(sync_paths) do
|
|
local name = vim.fn.fnamemodify(path, ':t:r')
|
|
local bok, backend = pcall(require, 'pending.sync.' .. name)
|
|
if bok and type(backend.health) == 'function' then
|
|
vim.health.start('pending.nvim: sync/' .. name)
|
|
backend.health()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return M
|