merge v0.23.0-rc changes

This commit is contained in:
Gani Georgiev
2024-09-29 19:23:19 +03:00
parent ad92992324
commit 844f18cac3
753 changed files with 85141 additions and 63396 deletions
+70 -114
View File
@@ -10,130 +10,86 @@ import (
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/core"
"github.com/pocketbase/pocketbase/daos"
"github.com/pocketbase/pocketbase/models"
"github.com/pocketbase/pocketbase/tools/migrate"
)
const collectionsStoreKey = "migratecmd_collections"
// onCollectionChange handles the automigration snapshot generation on
// collection change event (create/update/delete).
func (p *plugin) afterCollectionChange() func(*core.ModelEvent) error {
return func(e *core.ModelEvent) error {
if e.Model.TableName() != "_collections" {
return nil // not a collection
// 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
}
}
// @todo replace with the OldModel when added to the ModelEvent
oldCollections, err := p.getCachedCollections()
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_" + old.Name
case old == nil:
action = "created_" + new.Name
default:
action = "updated_" + 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
}
old := oldCollections[e.Model.GetId()]
new, err := p.app.Dao().FindCollectionByNameOrId(e.Model.GetId())
if err != nil && !errors.Is(err, sql.ErrNoRows) {
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)
}
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, emptyTemplateErr) {
return nil // no changes
}
return fmt.Errorf("failed to resolve template: %w", templateErr)
if err := os.WriteFile(filePath, []byte(template), 0644); err != nil {
return fmt.Errorf("failed to save automigrate file: %w", err)
}
var action string
switch {
case new == nil:
action = "deleted_" + old.Name
case old == nil:
action = "created_" + new.Name
default:
action = "updated_" + 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.Dao().RunInTransaction(func(txDao *daos.Dao) error {
// insert the migration entry
_, err := txDao.DB().Insert(migrate.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)
}
p.updateSingleCachedCollection(new, old)
return nil
})
}
}
func (p *plugin) updateSingleCachedCollection(new, old *models.Collection) {
cached, _ := p.app.Store().Get(collectionsStoreKey).(map[string]*models.Collection)
switch {
case new == nil:
delete(cached, old.Id)
default:
cached[new.Id] = new
}
p.app.Store().Set(collectionsStoreKey, cached)
}
func (p *plugin) refreshCachedCollections() error {
if p.app.Dao() == nil {
return errors.New("app is not initialized yet")
}
var collections []*models.Collection
if err := p.app.Dao().CollectionQuery().All(&collections); err != nil {
return err
}
cached := map[string]*models.Collection{}
for _, c := range collections {
cached[c.Id] = c
}
p.app.Store().Set(collectionsStoreKey, cached)
return nil
}
func (p *plugin) getCachedCollections() (map[string]*models.Collection, error) {
if !p.app.Store().Has(collectionsStoreKey) {
if err := p.refreshCachedCollections(); err != nil {
return nil, err
}
}
result, _ := p.app.Store().Get(collectionsStoreKey).(map[string]*models.Collection)
return result, nil
return nil
})
}
+15 -28
View File
@@ -16,6 +16,7 @@
package migratecmd
import (
"errors"
"fmt"
"os"
"path"
@@ -24,10 +25,7 @@ import (
"github.com/AlecAivazis/survey/v2"
"github.com/pocketbase/pocketbase/core"
"github.com/pocketbase/pocketbase/migrations"
"github.com/pocketbase/pocketbase/models"
"github.com/pocketbase/pocketbase/tools/inflector"
"github.com/pocketbase/pocketbase/tools/migrate"
"github.com/spf13/cobra"
)
@@ -82,22 +80,9 @@ func Register(app core.App, rootCmd *cobra.Command, config Config) error {
// watch for collection changes
if p.config.Automigrate {
// refresh the cache right after app bootstap
p.app.OnAfterBootstrap().Add(func(e *core.BootstrapEvent) error {
p.refreshCachedCollections()
return nil
})
// refresh the cache to ensure that it constains the latest changes
// when migrations are applied on server start
p.app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
p.refreshCachedCollections()
return nil
})
p.app.OnModelAfterCreate().Add(p.afterCollectionChange())
p.app.OnModelAfterUpdate().Add(p.afterCollectionChange())
p.app.OnModelAfterDelete().Add(p.afterCollectionChange())
p.app.OnCollectionCreateRequest().BindFunc(p.automigrateOnCollectionChange)
p.app.OnCollectionUpdateRequest().BindFunc(p.automigrateOnCollectionChange)
p.app.OnCollectionDeleteRequest().BindFunc(p.automigrateOnCollectionChange)
}
return nil
@@ -139,10 +124,12 @@ func (p *plugin) createCommand() *cobra.Command {
return err
}
default:
runner, err := migrate.NewRunner(p.app.DB(), migrations.AppMigrations)
if err != nil {
return err
}
// note: system migrations are always applied as part of the bootstrap process
var list = core.MigrationsList{}
list.Copy(core.SystemMigrations)
list.Copy(core.AppMigrations)
runner := core.NewMigrationsRunner(p.app, list)
if err := runner.Run(args...); err != nil {
return err
@@ -158,7 +145,7 @@ func (p *plugin) createCommand() *cobra.Command {
func (p *plugin) migrateCreateHandler(template string, args []string, interactive bool) (string, error) {
if len(args) < 1 {
return "", fmt.Errorf("Missing migration file name")
return "", errors.New("Missing migration file name")
}
name := args[0]
@@ -214,9 +201,9 @@ func (p *plugin) migrateCollectionsHandler(args []string, interactive bool) (str
createArgs := []string{"collections_snapshot"}
createArgs = append(createArgs, args...)
collections := []*models.Collection{}
if err := p.app.Dao().CollectionQuery().OrderBy("created ASC").All(&collections); err != nil {
return "", fmt.Errorf("Failed to fetch migrations list: %v", err)
collections := []*core.Collection{}
if err := p.app.CollectionQuery().OrderBy("created ASC").All(&collections); err != nil {
return "", fmt.Errorf("Failed to fetch migrations list: %v\n", err)
}
var template string
@@ -227,7 +214,7 @@ func (p *plugin) migrateCollectionsHandler(args []string, interactive bool) (str
template, templateErr = p.goSnapshotTemplate(collections)
}
if templateErr != nil {
return "", fmt.Errorf("Failed to resolve template: %v", templateErr)
return "", fmt.Errorf("Failed to resolve template: %v\n", templateErr)
}
return p.migrateCreateHandler(template, createArgs, interactive)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff