docs(flows): DoD obligatorio con user-facing surface + abrir issues 0100-0103 (taxonomia, frontmatter migration, dev_console, work dashboard)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
registryDBOnce sync.Once
|
||||
registryDBConn *sql.DB
|
||||
registryDBErr error
|
||||
)
|
||||
|
||||
func resolveRegistryDBPath() string {
|
||||
if p := os.Getenv("FN_REGISTRY_DB"); p != "" {
|
||||
return p
|
||||
}
|
||||
if root := os.Getenv("FN_REGISTRY_ROOT"); root != "" {
|
||||
return filepath.Join(root, "registry.db")
|
||||
}
|
||||
return "/home/lucas/fn_registry/registry.db"
|
||||
}
|
||||
|
||||
func openRegistryDB() (*sql.DB, error) {
|
||||
registryDBOnce.Do(func() {
|
||||
path := resolveRegistryDBPath()
|
||||
// Read-only access — registry.db es source of truth gestionada via `fn index`.
|
||||
db, err := sql.Open("sqlite3", "file:"+path+"?mode=ro&_query_only=1")
|
||||
if err != nil {
|
||||
registryDBErr = err
|
||||
return
|
||||
}
|
||||
registryDBConn = db
|
||||
})
|
||||
return registryDBConn, registryDBErr
|
||||
}
|
||||
|
||||
func (s *Server) handleFunctionByID(w http.ResponseWriter, r *http.Request) {
|
||||
id := r.PathValue("id")
|
||||
if id == "" {
|
||||
writeError(w, http.StatusBadRequest, "id is required")
|
||||
return
|
||||
}
|
||||
|
||||
db, err := openRegistryDB()
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(r.Context(), queryTimeout)
|
||||
defer cancel()
|
||||
|
||||
// Try functions table first.
|
||||
const fnQuery = `SELECT id, name, kind, lang, domain, version, purity, signature,
|
||||
description, tags, returns, returns_optional, error_type, file_path, code, documentation
|
||||
FROM functions WHERE id = ?`
|
||||
var (
|
||||
fnID, name, kind, lang, domain, version, purity, signature string
|
||||
description, tags, returns, errorType, filePath string
|
||||
code, documentation string
|
||||
returnsOptional bool
|
||||
)
|
||||
err = db.QueryRowContext(ctx, fnQuery, id).Scan(
|
||||
&fnID, &name, &kind, &lang, &domain, &version, &purity, &signature,
|
||||
&description, &tags, &returns, &returnsOptional, &errorType, &filePath,
|
||||
&code, &documentation,
|
||||
)
|
||||
if err == nil {
|
||||
writeJSON(w, http.StatusOK, map[string]any{
|
||||
"entity": "function",
|
||||
"id": fnID,
|
||||
"name": name,
|
||||
"kind": kind,
|
||||
"lang": lang,
|
||||
"domain": domain,
|
||||
"version": version,
|
||||
"purity": purity,
|
||||
"signature": signature,
|
||||
"description": description,
|
||||
"tags": tags,
|
||||
"returns": returns,
|
||||
"returns_optional": returnsOptional,
|
||||
"error_type": errorType,
|
||||
"file_path": filePath,
|
||||
"code": code,
|
||||
"documentation": documentation,
|
||||
})
|
||||
return
|
||||
}
|
||||
if err != sql.ErrNoRows {
|
||||
writeError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Fallback: types table.
|
||||
const typeQuery = `SELECT id, name, lang, domain, version, description, tags, definition, file_path
|
||||
FROM types WHERE id = ?`
|
||||
var (
|
||||
tID, tName, tLang, tDomain, tVersion string
|
||||
tDescription, tTags, tDefinition string
|
||||
tFilePath string
|
||||
)
|
||||
err = db.QueryRowContext(ctx, typeQuery, id).Scan(
|
||||
&tID, &tName, &tLang, &tDomain, &tVersion,
|
||||
&tDescription, &tTags, &tDefinition, &tFilePath,
|
||||
)
|
||||
if err == nil {
|
||||
writeJSON(w, http.StatusOK, map[string]any{
|
||||
"entity": "type",
|
||||
"id": tID,
|
||||
"name": tName,
|
||||
"lang": tLang,
|
||||
"domain": tDomain,
|
||||
"version": tVersion,
|
||||
"description": tDescription,
|
||||
"tags": tTags,
|
||||
"definition": tDefinition,
|
||||
"file_path": tFilePath,
|
||||
})
|
||||
return
|
||||
}
|
||||
if err == sql.ErrNoRows {
|
||||
writeError(w, http.StatusNotFound, "not_found")
|
||||
return
|
||||
}
|
||||
writeError(w, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
Reference in New Issue
Block a user