- internal/exporter: pure BuildScene + 21-char base62 IDs, port ellipses, device rect+text pairs, IO diamonds, arrow bindings, legend texts. Bundles intentionally omitted per design §4.1. - internal/db: PersistExcalidrawIDs idempotent updater per project. - internal/server: POST /api/projects/:pid/sync/export — loads snapshot, mints/reuses excalidraw_ids, PUTs scene to mxdrw with bearer auth. Returns viewer URL + element_count + mxdrw response. Roundtrip hand-tested against mxdrw.msbls.de: scene saved, IDs stable across re-exports.
61 lines
1.5 KiB
Go
61 lines
1.5 KiB
Go
package db
|
|
|
|
import (
|
|
"database/sql"
|
|
)
|
|
|
|
// PersistExcalidrawIDs writes the assignments returned by the exporter
|
|
// back onto the corresponding rows. Idempotent: only updates rows whose
|
|
// excalidraw_id is currently NULL (the first export "owns" the id; later
|
|
// exports reuse it so mxdrw's collab cursors / undo history survive).
|
|
//
|
|
// Caller passes one map per kind; keys are the in-project row ids,
|
|
// values are the 21-char Excalidraw element ids the exporter minted.
|
|
func (s *Store) PersistExcalidrawIDs(projectID int64,
|
|
frames, devices, ports, ios, cables map[int64]string,
|
|
) error {
|
|
tx, err := s.db.Begin()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer tx.Rollback()
|
|
|
|
if err := updateExIDs(tx, "frames", projectID, frames); err != nil {
|
|
return err
|
|
}
|
|
if err := updateExIDs(tx, "devices", projectID, devices); err != nil {
|
|
return err
|
|
}
|
|
if err := updateExIDs(tx, "ports", projectID, ports); err != nil {
|
|
return err
|
|
}
|
|
if err := updateExIDs(tx, "io_markers", projectID, ios); err != nil {
|
|
return err
|
|
}
|
|
if err := updateExIDs(tx, "cables", projectID, cables); err != nil {
|
|
return err
|
|
}
|
|
return tx.Commit()
|
|
}
|
|
|
|
func updateExIDs(tx *sql.Tx, table string, projectID int64, m map[int64]string) error {
|
|
if len(m) == 0 {
|
|
return nil
|
|
}
|
|
stmt, err := tx.Prepare(
|
|
`UPDATE ` + table + `
|
|
SET excalidraw_id = ?
|
|
WHERE id = ? AND project_id = ? AND excalidraw_id IS NULL`,
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer stmt.Close()
|
|
for id, exID := range m {
|
|
if _, err := stmt.Exec(exID, id, projectID); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|