Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// IDMapDocument matches docs/schema-map.md (versioned unified ID map for cutover rehearsal).
|
||||
type IDMapDocument struct {
|
||||
Version int `json:"version"`
|
||||
GeneratedAt string `json:"generated_at"`
|
||||
Source string `json:"source"`
|
||||
Target string `json:"target"`
|
||||
Users map[string]string `json:"users"`
|
||||
Companies map[string]string `json:"companies"`
|
||||
Categories map[string]string `json:"categories,omitempty"`
|
||||
Attributes map[string]string `json:"attributes,omitempty"`
|
||||
Feeds map[string]string `json:"feeds,omitempty"`
|
||||
RawProducts map[string]string `json:"raw_products,omitempty"`
|
||||
Files map[string]string `json:"files,omitempty"`
|
||||
Meta IDMapMeta `json:"meta"`
|
||||
}
|
||||
|
||||
type IDMapMeta struct {
|
||||
UserCount int `json:"user_count"`
|
||||
CompanyCount int `json:"company_count"`
|
||||
DryRun bool `json:"dry_run"`
|
||||
Report map[string]int `json:"report,omitempty"`
|
||||
}
|
||||
|
||||
func copyMap(dst *map[string]string, src map[string]string) {
|
||||
if src == nil {
|
||||
return
|
||||
}
|
||||
if *dst == nil {
|
||||
*dst = map[string]string{}
|
||||
}
|
||||
for k, v := range src {
|
||||
(*dst)[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
// AttachEntityMaps merges optional catalog/feed entity remaps into the document.
|
||||
func (d *IDMapDocument) AttachEntityMaps(
|
||||
categories, attributes, feeds, rawProducts, files map[string]string,
|
||||
report map[string]int,
|
||||
) {
|
||||
if d == nil {
|
||||
return
|
||||
}
|
||||
copyMap(&d.Categories, categories)
|
||||
copyMap(&d.Attributes, attributes)
|
||||
copyMap(&d.Feeds, feeds)
|
||||
copyMap(&d.RawProducts, rawProducts)
|
||||
copyMap(&d.Files, files)
|
||||
d.Meta.UserCount = len(d.Users)
|
||||
d.Meta.CompanyCount = len(d.Companies)
|
||||
if report != nil {
|
||||
d.Meta.Report = report
|
||||
}
|
||||
}
|
||||
|
||||
func NewIDMapDocument(users, companies map[string]string, dryRun bool) IDMapDocument {
|
||||
if users == nil {
|
||||
users = map[string]string{}
|
||||
}
|
||||
if companies == nil {
|
||||
companies = map[string]string{}
|
||||
}
|
||||
return IDMapDocument{
|
||||
Version: 1,
|
||||
GeneratedAt: time.Now().UTC().Format(time.RFC3339),
|
||||
Source: "mysql",
|
||||
Target: "postgres",
|
||||
Users: users,
|
||||
Companies: companies,
|
||||
Meta: IDMapMeta{
|
||||
UserCount: len(users),
|
||||
CompanyCount: len(companies),
|
||||
DryRun: dryRun,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (d IDMapDocument) Validate() error {
|
||||
if d.Version != 1 {
|
||||
return fmt.Errorf("unsupported id map version %d", d.Version)
|
||||
}
|
||||
for legacy, id := range d.Users {
|
||||
if legacy == "" {
|
||||
return fmt.Errorf("empty user legacy id")
|
||||
}
|
||||
if _, err := uuid.Parse(id); err != nil {
|
||||
return fmt.Errorf("user %q maps to invalid uuid %q", legacy, id)
|
||||
}
|
||||
}
|
||||
for legacy, id := range d.Companies {
|
||||
if legacy == "" {
|
||||
return fmt.Errorf("empty company legacy id")
|
||||
}
|
||||
if _, err := uuid.Parse(id); err != nil {
|
||||
return fmt.Errorf("company %q maps to invalid uuid %q", legacy, id)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d IDMapDocument) ResolveUser(legacy string) (uuid.UUID, bool) {
|
||||
raw, ok := d.Users[legacy]
|
||||
if !ok {
|
||||
return uuid.Nil, false
|
||||
}
|
||||
id, err := uuid.Parse(raw)
|
||||
if err != nil {
|
||||
return uuid.Nil, false
|
||||
}
|
||||
return id, true
|
||||
}
|
||||
|
||||
func (d IDMapDocument) ResolveCompany(legacy string) (uuid.UUID, bool) {
|
||||
raw, ok := d.Companies[legacy]
|
||||
if !ok {
|
||||
return uuid.Nil, false
|
||||
}
|
||||
id, err := uuid.Parse(raw)
|
||||
if err != nil {
|
||||
return uuid.Nil, false
|
||||
}
|
||||
return id, true
|
||||
}
|
||||
|
||||
func WriteIDMap(path string, d IDMapDocument) error {
|
||||
if err := d.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
b, err := json.MarshalIndent(d, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(path, b, 0o644)
|
||||
}
|
||||
|
||||
func ReadIDMap(path string) (IDMapDocument, error) {
|
||||
b, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return IDMapDocument{}, err
|
||||
}
|
||||
var d IDMapDocument
|
||||
if err := json.Unmarshal(b, &d); err != nil {
|
||||
return IDMapDocument{}, err
|
||||
}
|
||||
if err := d.Validate(); err != nil {
|
||||
return IDMapDocument{}, err
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
|
||||
func WriteIDMapDir(dir string, users, companies map[string]string, dryRun bool) (string, error) {
|
||||
if err := os.MkdirAll(dir, 0o755); err != nil {
|
||||
return "", err
|
||||
}
|
||||
path := filepath.Join(dir, "id-map.json")
|
||||
doc := NewIDMapDocument(users, companies, dryRun)
|
||||
if err := WriteIDMap(path, doc); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return path, nil
|
||||
}
|
||||
Reference in New Issue
Block a user