feat: auth backend (#111)
* refactor(types): extract inline anonymous types into named classes
Problem: several functions used inline `{...}` table types in their
`@param` and `@return` annotations, making them hard to read and
impossible to reference from other modules.
Solution: extract each into a named `---@class`: `pending.Metadata`,
`pending.TaskFields`, `pending.CompletionItem`, `pending.SystemResult`,
and `pending.OAuthClientOpts`.
* refactor(sync): extract shared utilities into `sync/util.lua`
Problem: sync epilogue code (`s:save()`, `_recompute_counts()`,
`buffer.render()`) and `fmt_counts` were duplicated across `gcal.lua`
and `gtasks.lua`. The concurrency guard lived in `oauth.lua`, coupling
non-OAuth backends to the OAuth module.
Solution: create `sync/util.lua` with `async`, `system`, `with_guard`,
`finish`, and `fmt_counts`. Delegate from `oauth.lua` and replace
duplicated code in both backends. Add per-backend `auth()` and
`auth_complete()` methods to `gcal.lua` and `gtasks.lua`.
* feat(sync): auto-discover backends, per-backend auth, S3 backend
Problem: sync backends were hardcoded in `SYNC_BACKENDS` list in
`init.lua`, auth routed directly through `oauth.google_client`, and
adding a non-OAuth backend required editing multiple files.
Solution: replace hardcoded list with `discover_backends()` that globs
`lua/pending/sync/*.lua` at runtime. Rewrite `M.auth()` to dispatch
to per-backend `auth()` methods with `vim.ui.select` fallback. Add
`lua/pending/sync/s3.lua` with push/pull/sync via AWS CLI, per-task
merge by `_s3_sync_id` (UUID), and `pending.S3Config` type.
This commit is contained in:
parent
34a68db6d0
commit
d12838abbf
13 changed files with 1173 additions and 107 deletions
|
|
@ -183,7 +183,8 @@ end, {
|
|||
for word in after_filter:gmatch('%S+') do
|
||||
used[word] = true
|
||||
end
|
||||
local candidates = { 'clear', 'overdue', 'today', 'priority', 'done', 'pending', 'wip', 'blocked' }
|
||||
local candidates =
|
||||
{ 'clear', 'overdue', 'today', 'priority', 'done', 'pending', 'wip', 'blocked' }
|
||||
local store = require('pending.store')
|
||||
local s = store.new(store.resolve_path())
|
||||
s:load()
|
||||
|
|
@ -223,10 +224,22 @@ end, {
|
|||
end
|
||||
local trailing = after_auth:match('%s$')
|
||||
if #parts == 0 or (#parts == 1 and not trailing) then
|
||||
return filter_candidates(arg_lead, { 'gcal', 'gtasks', 'clear', 'reset' })
|
||||
local auth_names = {}
|
||||
for _, b in ipairs(pending.sync_backends()) do
|
||||
local ok, mod = pcall(require, 'pending.sync.' .. b)
|
||||
if ok and type(mod.auth) == 'function' then
|
||||
table.insert(auth_names, b)
|
||||
end
|
||||
end
|
||||
return filter_candidates(arg_lead, auth_names)
|
||||
end
|
||||
local backend_name = parts[1]
|
||||
if #parts == 1 or (#parts == 2 and not trailing) then
|
||||
return filter_candidates(arg_lead, { 'clear', 'reset' })
|
||||
local ok, mod = pcall(require, 'pending.sync.' .. backend_name)
|
||||
if ok and type(mod.auth_complete) == 'function' then
|
||||
return filter_candidates(arg_lead, mod.auth_complete())
|
||||
end
|
||||
return {}
|
||||
end
|
||||
return {}
|
||||
end
|
||||
|
|
@ -243,7 +256,13 @@ end, {
|
|||
end
|
||||
local actions = {}
|
||||
for k, v in pairs(mod) do
|
||||
if type(v) == 'function' and k:sub(1, 1) ~= '_' and k ~= 'health' then
|
||||
if
|
||||
type(v) == 'function'
|
||||
and k:sub(1, 1) ~= '_'
|
||||
and k ~= 'health'
|
||||
and k ~= 'auth'
|
||||
and k ~= 'auth_complete'
|
||||
then
|
||||
table.insert(actions, k)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue