mirror of
https://github.com/pocketbase/pocketbase.git
synced 2025-03-20 22:36:00 +02:00
107 lines
2.7 KiB
Go
107 lines
2.7 KiB
Go
package migratecmd
|
|
|
|
import (
|
|
"database/sql"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/pocketbase/dbx"
|
|
"github.com/pocketbase/pocketbase/core"
|
|
)
|
|
|
|
// automigrateOnCollectionChange handles the automigration snapshot
|
|
// generation on collection change request event (create/update/delete).
|
|
func (p *plugin) automigrateOnCollectionChange(e *core.CollectionRequestEvent) error {
|
|
var err error
|
|
var old *core.Collection
|
|
if !e.Collection.IsNew() {
|
|
old, err = e.App.FindCollectionByNameOrId(e.Collection.Id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
err = e.Next()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
new, err := p.app.FindCollectionByNameOrId(e.Collection.Id)
|
|
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
|
return err
|
|
}
|
|
|
|
// for now exclude OAuth2 configs from the migration
|
|
if old != nil && old.IsAuth() {
|
|
old.OAuth2.Providers = nil
|
|
}
|
|
if new != nil && new.IsAuth() {
|
|
new.OAuth2.Providers = nil
|
|
}
|
|
|
|
var template string
|
|
var templateErr error
|
|
if p.config.TemplateLang == TemplateLangJS {
|
|
template, templateErr = p.jsDiffTemplate(new, old)
|
|
} else {
|
|
template, templateErr = p.goDiffTemplate(new, old)
|
|
}
|
|
if templateErr != nil {
|
|
if errors.Is(templateErr, ErrEmptyTemplate) {
|
|
return nil // no changes
|
|
}
|
|
return fmt.Errorf("failed to resolve template: %w", templateErr)
|
|
}
|
|
|
|
var action string
|
|
switch {
|
|
case new == nil:
|
|
action = "deleted_" + normalizeCollectionName(old.Name)
|
|
case old == nil:
|
|
action = "created_" + normalizeCollectionName(new.Name)
|
|
default:
|
|
action = "updated_" + normalizeCollectionName(old.Name)
|
|
}
|
|
|
|
name := fmt.Sprintf("%d_%s.%s", time.Now().Unix(), action, p.config.TemplateLang)
|
|
filePath := filepath.Join(p.config.Dir, name)
|
|
|
|
return p.app.RunInTransaction(func(txApp core.App) error {
|
|
// insert the migration entry
|
|
_, err := txApp.DB().Insert(core.DefaultMigrationsTable, dbx.Params{
|
|
"file": name,
|
|
// use microseconds for more granular applied time in case
|
|
// multiple collection changes happens at the ~exact time
|
|
"applied": time.Now().UnixMicro(),
|
|
}).Execute()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// ensure that the local migrations dir exist
|
|
if err := os.MkdirAll(p.config.Dir, os.ModePerm); err != nil {
|
|
return fmt.Errorf("failed to create migration dir: %w", err)
|
|
}
|
|
|
|
if err := os.WriteFile(filePath, []byte(template), 0644); err != nil {
|
|
return fmt.Errorf("failed to save automigrate file: %w", err)
|
|
}
|
|
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func normalizeCollectionName(name string) string {
|
|
// adds an extra "_" suffix to the name in case the collection ends
|
|
// with "test" to prevent accidentally resulting in "_test.go"/"_test.js" files
|
|
if strings.HasSuffix(strings.ToLower(name), "test") {
|
|
name += "_"
|
|
}
|
|
|
|
return name
|
|
}
|