mirror of
https://github.com/pocketbase/pocketbase.git
synced 2024-11-21 13:35:49 +02:00
added plugins subpackage and added basic support for js migrations
This commit is contained in:
parent
3e1a19685b
commit
d8963c6fc3
@ -138,10 +138,10 @@ func autoIgnoreAuthRecordsEmailVisibility(
|
||||
collection := records[0].Collection()
|
||||
|
||||
mappedRecords := make(map[string]*models.Record, len(records))
|
||||
recordIds := make([]any, 0, len(records))
|
||||
for _, rec := range records {
|
||||
recordIds := make([]any, len(records))
|
||||
for i, rec := range records {
|
||||
mappedRecords[rec.Id] = rec
|
||||
recordIds = append(recordIds, rec.Id)
|
||||
recordIds[i] = rec.Id
|
||||
}
|
||||
|
||||
if requestData != nil && requestData.AuthRecord != nil && mappedRecords[requestData.AuthRecord.Id] != nil {
|
||||
|
15
core/base.go
15
core/base.go
@ -714,7 +714,10 @@ func (app *BaseApp) createDaoWithHooks(db dbx.Builder) *daos.Dao {
|
||||
}
|
||||
|
||||
dao.AfterCreateFunc = func(eventDao *daos.Dao, m models.Model) {
|
||||
app.OnModelAfterCreate().Trigger(&ModelEvent{eventDao, m})
|
||||
err := app.OnModelAfterCreate().Trigger(&ModelEvent{eventDao, m})
|
||||
if err != nil && app.isDebug {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
dao.BeforeUpdateFunc = func(eventDao *daos.Dao, m models.Model) error {
|
||||
@ -722,7 +725,10 @@ func (app *BaseApp) createDaoWithHooks(db dbx.Builder) *daos.Dao {
|
||||
}
|
||||
|
||||
dao.AfterUpdateFunc = func(eventDao *daos.Dao, m models.Model) {
|
||||
app.OnModelAfterUpdate().Trigger(&ModelEvent{eventDao, m})
|
||||
err := app.OnModelAfterUpdate().Trigger(&ModelEvent{eventDao, m})
|
||||
if err != nil && app.isDebug {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
dao.BeforeDeleteFunc = func(eventDao *daos.Dao, m models.Model) error {
|
||||
@ -730,7 +736,10 @@ func (app *BaseApp) createDaoWithHooks(db dbx.Builder) *daos.Dao {
|
||||
}
|
||||
|
||||
dao.AfterDeleteFunc = func(eventDao *daos.Dao, m models.Model) {
|
||||
app.OnModelAfterDelete().Trigger(&ModelEvent{eventDao, m})
|
||||
err := app.OnModelAfterDelete().Trigger(&ModelEvent{eventDao, m})
|
||||
if err != nil && app.isDebug {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
return dao
|
||||
|
@ -93,8 +93,8 @@ func (dao *Dao) expandRecords(records []*models.Record, expandPath string, fetch
|
||||
}
|
||||
|
||||
recordIds := make([]any, len(records))
|
||||
for _, record := range records {
|
||||
recordIds = append(recordIds, record.Id)
|
||||
for i, record := range records {
|
||||
recordIds[i] = record.Id
|
||||
}
|
||||
|
||||
indirectRecords, err := dao.FindRecordsByExpr(
|
||||
|
@ -2,42 +2,29 @@ package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/pocketbase/pocketbase"
|
||||
"github.com/pocketbase/pocketbase/apis"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
"github.com/pocketbase/pocketbase/plugins/jsvm"
|
||||
"github.com/pocketbase/pocketbase/plugins/migratecmd"
|
||||
"github.com/pocketbase/pocketbase/plugins/publicdir"
|
||||
)
|
||||
|
||||
func defaultPublicDir() string {
|
||||
if strings.HasPrefix(os.Args[0], os.TempDir()) {
|
||||
// most likely ran with go run
|
||||
return "./pb_public"
|
||||
}
|
||||
|
||||
return filepath.Join(os.Args[0], "../pb_public")
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := pocketbase.New()
|
||||
|
||||
var publicDirFlag string
|
||||
// load js pb_migrations
|
||||
jsvm.MustRegisterMigrationsLoader(app, nil)
|
||||
|
||||
// add "--publicDir" option flag
|
||||
app.RootCmd.PersistentFlags().StringVar(
|
||||
&publicDirFlag,
|
||||
"publicDir",
|
||||
defaultPublicDir(),
|
||||
"the directory to serve static files",
|
||||
)
|
||||
// migrate command (with js templates)
|
||||
migratecmd.MustRegister(app, app.RootCmd, &migratecmd.Options{
|
||||
TemplateLang: migratecmd.TemplateLangJS,
|
||||
AutoMigrate: true,
|
||||
})
|
||||
|
||||
app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
|
||||
// serves static files from the provided public dir (if exists)
|
||||
e.Router.GET("/*", apis.StaticDirectoryHandler(os.DirFS(publicDirFlag), true))
|
||||
|
||||
return nil
|
||||
// pb_public dir
|
||||
publicdir.MustRegister(app, &publicdir.Options{
|
||||
FlagsCmd: app.RootCmd,
|
||||
IndexFallback: true,
|
||||
})
|
||||
|
||||
if err := app.Start(); err != nil {
|
||||
|
4
go.mod
4
go.mod
@ -7,6 +7,8 @@ require (
|
||||
github.com/aws/aws-sdk-go v1.44.141
|
||||
github.com/disintegration/imaging v1.6.2
|
||||
github.com/domodwyer/mailyak/v3 v3.3.4
|
||||
github.com/dop251/goja v0.0.0-20221118162653-d4bf6fde1b86
|
||||
github.com/dop251/goja_nodejs v0.0.0-20221009164102-3aa5028e57f6
|
||||
github.com/fatih/color v1.13.0
|
||||
github.com/gabriel-vasile/mimetype v1.4.1
|
||||
github.com/ganigeorgiev/fexpr v0.1.1
|
||||
@ -45,6 +47,8 @@ require (
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.8 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.17.4 // indirect
|
||||
github.com/aws/smithy-go v1.13.4 // indirect
|
||||
github.com/dlclark/regexp2 v1.7.0 // indirect
|
||||
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
|
65
go.sum
65
go.sum
@ -47,18 +47,16 @@ cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6m
|
||||
cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s=
|
||||
cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU=
|
||||
cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U=
|
||||
cloud.google.com/go/compute v1.10.0 h1:aoLIYaA1fX3ywihqpBk2APQKOo20nXsp1GEZQbx5Jk4=
|
||||
cloud.google.com/go/compute v1.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0=
|
||||
cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||
cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY=
|
||||
cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c=
|
||||
cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY=
|
||||
cloud.google.com/go/iam v0.6.0 h1:nsqQC88kT5Iwlm4MeNGTpfMWddp6NB/UOLFTH6m1QfQ=
|
||||
cloud.google.com/go/iam v0.7.0 h1:k4MuwOsS7zGJJ+QfZ5vBK8SgHBAvYN/23BWsiihJ1vs=
|
||||
cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA=
|
||||
cloud.google.com/go/longrunning v0.1.1 h1:y50CXG4j0+qvEukslYFBCrzaXX0qpFbBzc3PchSu/LE=
|
||||
cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs=
|
||||
cloud.google.com/go/monitoring v1.1.0/go.mod h1:L81pzz7HKn14QCMaCs6NTQkdBnE87TElyanS95vIcl4=
|
||||
cloud.google.com/go/monitoring v1.5.0/go.mod h1:/o9y8NYX5j91JjD/JvGLYbi86kL11OjyJXq2XziLJu4=
|
||||
@ -208,12 +206,6 @@ github.com/aws/aws-sdk-go v1.43.11/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4
|
||||
github.com/aws/aws-sdk-go v1.43.31/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/aws/aws-sdk-go v1.44.45/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/aws/aws-sdk-go v1.44.68/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/aws/aws-sdk-go v1.44.126 h1:7HQJw2DNiwpxqMe2H7odGNT2rhO4SRrUe5/8dYXl0Jk=
|
||||
github.com/aws/aws-sdk-go v1.44.126/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/aws/aws-sdk-go v1.44.127 h1:IoO2VfuIQg1aMXnl8l6OpNUKT4Qq5CnJMOyIWoTYXj0=
|
||||
github.com/aws/aws-sdk-go v1.44.127/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/aws/aws-sdk-go v1.44.130 h1:a/qwOxmYJF47xTZvTjECSJXnfRbjegb3YxvCXfETtnY=
|
||||
github.com/aws/aws-sdk-go v1.44.130/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/aws/aws-sdk-go v1.44.141 h1:kT/YIH9GUaKZa3yi8TEsZmVgvphwEzINJu19hYUzfGY=
|
||||
github.com/aws/aws-sdk-go v1.44.141/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
|
||||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
||||
@ -224,21 +216,15 @@ github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.3/go.mod h1:gNsR5CaXK
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.9 h1:RKci2D7tMwpvGpDNZnGQw9wk6v7o/xSwFcUAuNPoB8k=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.9/go.mod h1:vCmV1q1VK8eoQJ5+aYE7PkK1K6v41qJ5pJdK3ggCDvg=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.15.15/go.mod h1:A1Lzyy/o21I5/s2FbyX5AevQfSVXpvvIDCoVFD0BC4E=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.17.10 h1:zBy5QQ/mkvHElM1rygHPAzuH+sl8nsdSaxSWj0+rpdE=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.17.10/go.mod h1:/4np+UiJJKpWHN7Q+LZvqXYgyjgeXm5+lLfDI6TPZao=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.18.2 h1:tRhTb3xMZsB0gW0sXWpqs9FeIP8iQp5SvnvwiPXzHwo=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.18.2/go.mod h1:9XVoZTdD8ICjrgI5ddb8j918q6lEZkFYpb7uohgvU6c=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.12.10/go.mod h1:g5eIM5XRs/OzIIK81QMBl+dAuDyoLN0VYaLP+tBqEOk=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.12.23 h1:LctvcJMIb8pxvk5hQhChpCu0WlU6oKQmcYb1HA4IZSA=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.12.23/go.mod h1:0awX9iRr/+UO7OwRQFpV1hNtXxOVuehpjVEzrIAYNcA=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.13.2 h1:F/v1w0XcFDZjL0bCdi9XWJenoPKjGbzljBhDKcryzEQ=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.13.2/go.mod h1:eAT5aj/WJ2UDIA0IVNFc2byQLeD89SDEi4cjzH/MKoQ=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.9/go.mod h1:KDCCm4ONIdHtUloDcFvK2+vshZvx4Zmj7UMDfusuz5s=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.19 h1:E3PXZSI3F2bzyj6XxUXdTIfvp425HHhwKsFvmzBwHgs=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.19/go.mod h1:VihW95zQpeKQWVPGkwT+2+WJNQV8UXFfMTWdU6VErL8=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.21/go.mod h1:iIYPrQ2rYfZiB/iADYlhj9HHZ9TTi6PqKQPAqygohbE=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.37 h1:e1VtTBo+cLNjres0wTlMkmwCGGRjDEkkrz3frxxcaCs=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.37/go.mod h1:kdAV1UMnCkyG6tZJUC4mHbPoRjPA3dIK0L8mnsHERiM=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.41 h1:ssgdsNm11dvFtO7F/AeiW4dAO3eGsDeg5fwpag/JP/I=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.41/go.mod h1:CS+AbDFAaPU9TQOo7U6mVV23YvqCOElnqmh0XQjgJ1g=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.15/go.mod h1:pWrr2OoHlT7M/Pd2y4HV3gJyPb3qj5qMmnPkKSNPYK4=
|
||||
@ -267,8 +253,6 @@ github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.19 h1:piDBAaWkaxkkV
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.19/go.mod h1:BmQWRVkLTmyNzYPFAZgon53qKLWBNSvonugD1MrSWUs=
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.18.1/go.mod h1:4PZMUkc9rXHWGVB5J9vKaZy3D7Nai79ORworQ3ASMiM=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.27.2/go.mod h1:u+566cosFI+d+motIz3USXEh6sN8Nq4GrNXSg2RXVMo=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.29.1 h1:/EMdFPW/Ppieh0WUtQf1+qCGNLdsq5UWUyevBQ6vMVc=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.29.1/go.mod h1:/NHbqPRiwxSPVOB2Xr+StDEH+GWV/64WwnUjv4KYzV0=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.29.3 h1:F6wgg8aHGNyhaAy2ONnWBThiPdLa386qNA0j33FIuSM=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.29.3/go.mod h1:/NHbqPRiwxSPVOB2Xr+StDEH+GWV/64WwnUjv4KYzV0=
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.15.14/go.mod h1:xakbH8KMsQQKqzX87uyyzTHshc/0/Df8bsTneTS5pFU=
|
||||
@ -281,8 +265,6 @@ github.com/aws/aws-sdk-go-v2/service/sso v1.11.25/go.mod h1:IARHuzTXmj1C0KS35vbo
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.8 h1:jcw6kKZrtNfBPJkaHrscDOZoe5gvi9wjudnxvozYFJo=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.8/go.mod h1:er2JHN+kBY6FcMfcBBKNGCT3CarImmdFzishsqBmSRI=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.16.10/go.mod h1:cftkHYN6tCDNfkSasAmclSfl4l7cySoay8vz7p/ce0E=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.17.1 h1:KRAix/KHvjGODaHAMXnxRk9t0D+4IJVUuS/uwXxngXk=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.17.1/go.mod h1:bXcN3koeVYiJcdDU89n3kCYILob7Y34AeLopUbZgLT4=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.17.4 h1:YNncBj5dVYd05i4ZQ+YicOotSXo0ufc9P8kTioi13EM=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.17.4/go.mod h1:bXcN3koeVYiJcdDU89n3kCYILob7Y34AeLopUbZgLT4=
|
||||
github.com/aws/smithy-go v1.12.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
|
||||
@ -498,6 +480,9 @@ github.com/digitalocean/godo v1.81.0/go.mod h1:BPCqvwbjbGqxuUnIKB4EvS/AX7IDnNmt5
|
||||
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
|
||||
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
||||
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
||||
github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo=
|
||||
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||
github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko=
|
||||
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
||||
@ -521,6 +506,14 @@ github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZ
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||
github.com/domodwyer/mailyak/v3 v3.3.4 h1:AG/pvcz2/ocFqZkPEG7lPAa0MhCq1warfUEKJt6Fagk=
|
||||
github.com/domodwyer/mailyak/v3 v3.3.4/go.mod h1:lOm/u9CyCVWHeaAmHIdF4RiKVxKUT/H5XX10lIKAL6c=
|
||||
github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
|
||||
github.com/dop251/goja v0.0.0-20220815083517-0c74f9139fd6/go.mod h1:yRkwfj0CBpOGre+TwBsqPV0IH0Pk73e4PXJOeNDboGs=
|
||||
github.com/dop251/goja v0.0.0-20221118162653-d4bf6fde1b86 h1:E2wycakfddWJ26v+ZyEY91Lb/HEZyaiZhbMX+KQcdmc=
|
||||
github.com/dop251/goja v0.0.0-20221118162653-d4bf6fde1b86/go.mod h1:yRkwfj0CBpOGre+TwBsqPV0IH0Pk73e4PXJOeNDboGs=
|
||||
github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y=
|
||||
github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM=
|
||||
github.com/dop251/goja_nodejs v0.0.0-20221009164102-3aa5028e57f6 h1:p3QZwRRfCN7Qr3GNBTMKBkLFjEm3DHR4MaJABvsiqgk=
|
||||
github.com/dop251/goja_nodejs v0.0.0-20221009164102-3aa5028e57f6/go.mod h1:+CJy9V5cGycP5qwp6RM5jLg+TFEMyGtD7A9xUbU/BOQ=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
@ -640,6 +633,8 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+
|
||||
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
||||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||
github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8=
|
||||
github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU=
|
||||
github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||
@ -816,8 +811,6 @@ github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0
|
||||
github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM=
|
||||
github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM=
|
||||
github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c=
|
||||
github.com/googleapis/gax-go/v2 v2.6.0 h1:SXk3ABtQYDT/OH8jAyvEOQ58mgawq5C4o/4/89qN2ZU=
|
||||
github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY=
|
||||
github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ=
|
||||
github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8=
|
||||
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
|
||||
@ -1379,7 +1372,6 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
@ -1464,7 +1456,6 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
|
||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
@ -1567,8 +1558,6 @@ golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
|
||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A=
|
||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@ -1613,8 +1602,6 @@ golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
|
||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
||||
golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA=
|
||||
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -1694,7 +1681,6 @@ golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug
|
||||
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220802222814-0bcc04d9c69b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0=
|
||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||
golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
@ -1723,8 +1709,6 @@ golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7Lm
|
||||
golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
|
||||
golang.org/x/oauth2 v0.0.0-20220628200809-02e64fa58f26/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
|
||||
golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
|
||||
golang.org/x/oauth2 v0.1.0 h1:isLCZuhj4v+tYv7eskaN4v/TM+A1begWWgyVJDdl1+Y=
|
||||
golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A=
|
||||
golang.org/x/oauth2 v0.2.0 h1:GtQkldQ9m7yvzCL1V+LrYow3Khe0eJH0w7RbX/VbaIU=
|
||||
golang.org/x/oauth2 v0.2.0/go.mod h1:Cwn6afJ8jrQwYMxQDTpISoXmXW9I6qF6vDeuuoX3Ibs=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@ -1741,6 +1725,7 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@ -1883,7 +1868,6 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@ -1893,7 +1877,6 @@ golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9sn
|
||||
golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY=
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
|
||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
@ -1920,8 +1903,6 @@ golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxb
|
||||
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA=
|
||||
golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.2.0 h1:52I/1L54xyEQAYdtcSuxtiT84KGYTBGXwayxmIpNJhE=
|
||||
golang.org/x/time v0.2.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@ -2007,8 +1988,6 @@ golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
||||
golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
|
||||
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||
golang.org/x/tools v0.3.0 h1:SrNbZl6ECOS1qFzgTdQfWXZM9XBkiA6tkFrH9YSTPHM=
|
||||
golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@ -2070,10 +2049,6 @@ google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6F
|
||||
google.golang.org/api v0.86.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw=
|
||||
google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw=
|
||||
google.golang.org/api v0.91.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw=
|
||||
google.golang.org/api v0.101.0 h1:lJPPeEBIRxGpGLwnBTam1NPEM8Z2BmmXEd3z812pjwM=
|
||||
google.golang.org/api v0.101.0/go.mod h1:CjxAAWWt3A3VrUE2IGDY2bgK5qhoG/OkyWVlYcP05MY=
|
||||
google.golang.org/api v0.102.0 h1:JxJl2qQ85fRMPNvlZY/enexbxpCjLwGhZUtgfGeQ51I=
|
||||
google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo=
|
||||
google.golang.org/api v0.103.0 h1:9yuVqlu2JCvcLg9p8S3fcFLZij8EPSyvODIY1rkMizQ=
|
||||
google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
@ -2184,8 +2159,6 @@ google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljW
|
||||
google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||
google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||
google.golang.org/genproto v0.0.0-20220802133213-ce4fa296bf78/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc=
|
||||
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c h1:QgY/XxIAIeccR+Ca/rDdKubLIU9rcJ3xfy1DC/Wd2Oo=
|
||||
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo=
|
||||
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 h1:a2S6M0+660BgMNl++4JPlcAO/CjkqYItDEZwkoDQK7c=
|
||||
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
|
||||
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
@ -2229,8 +2202,6 @@ google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu
|
||||
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||
google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||
google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
|
||||
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
|
||||
google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
|
||||
google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
@ -2365,8 +2336,6 @@ lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
|
||||
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||
modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw=
|
||||
modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0=
|
||||
modernc.org/ccgo/v3 v3.16.13-0.20221017192402-261537637ce8 h1:0+dsXf0zeLx9ixj4nilg6jKe5Bg1ilzBwSFq4kJmIUc=
|
||||
modernc.org/ccgo/v3 v3.16.13-0.20221017192402-261537637ce8/go.mod h1:fUB3Vn0nVPReA+7IG7yZDfjv1TMWjhQP8gCxrFAtL5g=
|
||||
modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw=
|
||||
modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY=
|
||||
modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk=
|
||||
@ -2379,15 +2348,11 @@ modernc.org/memory v1.4.0 h1:crykUfNSnMAXaOJnnxcSzbUGMqkLWjklJKkBK2nwZwk=
|
||||
modernc.org/memory v1.4.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
|
||||
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
||||
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/sqlite v1.19.3 h1:dIoagx6yIQT3V/zOSeAyZ8OqQyEr17YTgETOXTZNJMA=
|
||||
modernc.org/sqlite v1.19.3/go.mod h1:xiyJD7FY8mTZXnQwE/gEL1STtFrrnDx03V8KhVQmcr8=
|
||||
modernc.org/sqlite v1.19.4 h1:nlPIDqumn6/mSvs7T5C8MNYEuN73sISzPdKtMdURpUI=
|
||||
modernc.org/sqlite v1.19.4/go.mod h1:x/yZNb3h5+I3zGQSlwIv4REL5eJhiRkUH5MReogAeIc=
|
||||
modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
|
||||
modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
|
||||
modernc.org/tcl v1.15.0 h1:oY+JeD11qVVSgVvodMJsu7Edf8tr5E/7tuhF5cNYz34=
|
||||
modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg=
|
||||
modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
modernc.org/z v1.7.0 h1:xkDw/KepgEjeizO2sNco+hqYkU12taxQFqPEmgm1GWE=
|
||||
|
110
plugins/jsvm/migrations.go
Normal file
110
plugins/jsvm/migrations.go
Normal file
@ -0,0 +1,110 @@
|
||||
package jsvm
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/dop251/goja_nodejs/console"
|
||||
"github.com/dop251/goja_nodejs/require"
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
)
|
||||
|
||||
// MigrationsLoaderOptions defines optional struct to customize the default plugin behavior.
|
||||
type MigrationsLoaderOptions struct {
|
||||
// Dir is the app migrations directory from where the js files will be loaded
|
||||
// (default to pb_data/migrations)
|
||||
Dir string
|
||||
}
|
||||
|
||||
// migrationsLoader is the plugin definition.
|
||||
// Usually it is instantiated via RegisterMigrationsLoader or MustRegisterMigrationsLoader.
|
||||
type migrationsLoader struct {
|
||||
app core.App
|
||||
options *MigrationsLoaderOptions
|
||||
}
|
||||
|
||||
//
|
||||
// MustRegisterMigrationsLoader registers the plugin to the provided
|
||||
// app instance and panics if it fails.
|
||||
//
|
||||
// It it calls RegisterMigrationsLoader(app, options)
|
||||
//
|
||||
// If options is nil, by default the js files from pb_data/migrations are loaded.
|
||||
// Set custom options.Dir if you want to change it to some other directory.
|
||||
func MustRegisterMigrationsLoader(app core.App, options *MigrationsLoaderOptions) {
|
||||
if err := RegisterMigrationsLoader(app, options); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterMigrationsLoader registers the plugin to the provided app instance.
|
||||
//
|
||||
// If options is nil, by default the js files from pb_data/migrations are loaded.
|
||||
// Set custom options.Dir if you want to change it to some other directory.
|
||||
func RegisterMigrationsLoader(app core.App, options *MigrationsLoaderOptions) error {
|
||||
l := &migrationsLoader{app: app}
|
||||
|
||||
if options != nil {
|
||||
l.options = options
|
||||
} else {
|
||||
l.options = &MigrationsLoaderOptions{}
|
||||
}
|
||||
|
||||
if l.options.Dir == "" {
|
||||
l.options.Dir = filepath.Join(app.DataDir(), "../pb_migrations")
|
||||
}
|
||||
|
||||
files, err := readDirFiles(l.options.Dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
registry := new(require.Registry) // this can be shared by multiple runtimes
|
||||
|
||||
for file, content := range files {
|
||||
vm := NewBaseVM(l.app)
|
||||
registry.Enable(vm)
|
||||
console.Enable(vm)
|
||||
|
||||
vm.Set("migrate", func(up, down func(db dbx.Builder) error) {
|
||||
m.AppMigrations.Register(up, down, file)
|
||||
})
|
||||
|
||||
_, err := vm.RunString(string(content))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// readDirFiles returns a map with all directory files and their content.
|
||||
//
|
||||
// If directory with dirPath is missing, it returns an empty map and no error.
|
||||
func readDirFiles(dirPath string) (map[string][]byte, error) {
|
||||
files, err := os.ReadDir(dirPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return map[string][]byte{}, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := map[string][]byte{}
|
||||
|
||||
for _, f := range files {
|
||||
if f.IsDir() {
|
||||
continue
|
||||
}
|
||||
raw, err := os.ReadFile(filepath.Join(dirPath, f.Name()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result[f.Name()] = raw
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
135
plugins/jsvm/vm.go
Normal file
135
plugins/jsvm/vm.go
Normal file
@ -0,0 +1,135 @@
|
||||
package jsvm
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/dop251/goja"
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/apis"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
"github.com/pocketbase/pocketbase/daos"
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
)
|
||||
|
||||
func NewBaseVM(app core.App) *goja.Runtime {
|
||||
vm := goja.New()
|
||||
vm.SetFieldNameMapper(goja.UncapFieldNameMapper())
|
||||
|
||||
vm.Set("$app", app)
|
||||
|
||||
vm.Set("unmarshal", func(src map[string]any, dest any) (any, error) {
|
||||
raw, err := json.Marshal(src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(raw, &dest); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dest, nil
|
||||
})
|
||||
|
||||
collectionConstructor(vm)
|
||||
recordConstructor(vm)
|
||||
adminConstructor(vm)
|
||||
daoConstructor(vm)
|
||||
dbxBinds(vm)
|
||||
|
||||
return vm
|
||||
}
|
||||
|
||||
func collectionConstructor(vm *goja.Runtime) {
|
||||
vm.Set("Collection", func(call goja.ConstructorCall) *goja.Object {
|
||||
instance := &models.Collection{}
|
||||
instanceValue := vm.ToValue(instance).(*goja.Object)
|
||||
instanceValue.SetPrototype(call.This.Prototype())
|
||||
return instanceValue
|
||||
})
|
||||
}
|
||||
|
||||
func recordConstructor(vm *goja.Runtime) {
|
||||
vm.Set("Record", func(call goja.ConstructorCall) *goja.Object {
|
||||
instance := &models.Record{}
|
||||
instanceValue := vm.ToValue(instance).(*goja.Object)
|
||||
instanceValue.SetPrototype(call.This.Prototype())
|
||||
return instanceValue
|
||||
})
|
||||
}
|
||||
|
||||
func adminConstructor(vm *goja.Runtime) {
|
||||
vm.Set("Admin", func(call goja.ConstructorCall) *goja.Object {
|
||||
instance := &models.Admin{}
|
||||
instanceValue := vm.ToValue(instance).(*goja.Object)
|
||||
instanceValue.SetPrototype(call.This.Prototype())
|
||||
return instanceValue
|
||||
})
|
||||
}
|
||||
|
||||
func daoConstructor(vm *goja.Runtime) {
|
||||
vm.Set("Dao", func(call goja.ConstructorCall) *goja.Object {
|
||||
db, ok := call.Argument(0).Export().(dbx.Builder)
|
||||
if !ok || db == nil {
|
||||
panic("missing required Dao(db) argument")
|
||||
}
|
||||
|
||||
instance := daos.New(db)
|
||||
instanceValue := vm.ToValue(instance).(*goja.Object)
|
||||
instanceValue.SetPrototype(call.This.Prototype())
|
||||
return instanceValue
|
||||
})
|
||||
}
|
||||
|
||||
func dbxBinds(vm *goja.Runtime) {
|
||||
obj := vm.NewObject()
|
||||
vm.Set("$dbx", obj)
|
||||
|
||||
obj.Set("exp", dbx.NewExp)
|
||||
obj.Set("hashExp", func(data map[string]any) dbx.HashExp {
|
||||
exp := dbx.HashExp{}
|
||||
for k, v := range data {
|
||||
exp[k] = v
|
||||
}
|
||||
return exp
|
||||
})
|
||||
obj.Set("not", dbx.Not)
|
||||
obj.Set("and", dbx.And)
|
||||
obj.Set("or", dbx.Or)
|
||||
obj.Set("in", dbx.In)
|
||||
obj.Set("notIn", dbx.NotIn)
|
||||
obj.Set("like", dbx.Like)
|
||||
obj.Set("orLike", dbx.OrLike)
|
||||
obj.Set("notLike", dbx.NotLike)
|
||||
obj.Set("orNotLike", dbx.OrNotLike)
|
||||
obj.Set("exists", dbx.Exists)
|
||||
obj.Set("notExists", dbx.NotExists)
|
||||
obj.Set("between", dbx.Between)
|
||||
obj.Set("notBetween", dbx.NotBetween)
|
||||
}
|
||||
|
||||
func apisBind(vm *goja.Runtime) {
|
||||
obj := vm.NewObject()
|
||||
vm.Set("$apis", obj)
|
||||
|
||||
// middlewares
|
||||
obj.Set("requireRecordAuth", apis.RequireRecordAuth)
|
||||
obj.Set("requireRecordAuth", apis.RequireRecordAuth)
|
||||
obj.Set("requireSameContextRecordAuth", apis.RequireSameContextRecordAuth)
|
||||
obj.Set("requireAdminAuth", apis.RequireAdminAuth)
|
||||
obj.Set("requireAdminAuthOnlyIfAny", apis.RequireAdminAuthOnlyIfAny)
|
||||
obj.Set("requireAdminOrRecordAuth", apis.RequireAdminOrRecordAuth)
|
||||
obj.Set("requireAdminOrOwnerAuth", apis.RequireAdminOrOwnerAuth)
|
||||
obj.Set("activityLogger", apis.ActivityLogger)
|
||||
|
||||
// api errors
|
||||
obj.Set("notFoundError", apis.NewNotFoundError)
|
||||
obj.Set("badRequestError", apis.NewBadRequestError)
|
||||
obj.Set("forbiddenError", apis.NewForbiddenError)
|
||||
obj.Set("unauthorizedError", apis.NewUnauthorizedError)
|
||||
|
||||
// record helpers
|
||||
obj.Set("getRequestData", apis.GetRequestData)
|
||||
obj.Set("requestData", apis.RequestData)
|
||||
obj.Set("enrichRecord", apis.EnrichRecord)
|
||||
obj.Set("enrichRecords", apis.EnrichRecords)
|
||||
}
|
154
plugins/migratecmd/automigrate.go
Normal file
154
plugins/migratecmd/automigrate.go
Normal file
@ -0,0 +1,154 @@
|
||||
package migratecmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
"github.com/pocketbase/pocketbase/tools/list"
|
||||
)
|
||||
|
||||
const migrationsTable = "_migrations"
|
||||
|
||||
// tidyMigrationsTable cleanups the migrations table by removing all
|
||||
// entries with deleted migration files.
|
||||
func (p *plugin) tidyMigrationsTable() error {
|
||||
names, filesErr := p.getAllMigrationNames()
|
||||
if filesErr != nil {
|
||||
return fmt.Errorf("failed to fetch migration files list: %v", filesErr)
|
||||
}
|
||||
|
||||
_, tidyErr := p.app.Dao().DB().Delete(migrationsTable, dbx.NotIn("file", list.ToInterfaceSlice(names)...)).Execute()
|
||||
if tidyErr != nil {
|
||||
return fmt.Errorf("failed to delete last automigrates from the db: %v", tidyErr)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *plugin) onCollectionChange() func(*core.ModelEvent) error {
|
||||
return func(e *core.ModelEvent) error {
|
||||
if e.Model.TableName() != "_collections" {
|
||||
return nil // not a collection
|
||||
}
|
||||
|
||||
collections := []*models.Collection{}
|
||||
if err := p.app.Dao().CollectionQuery().OrderBy("created ASC").All(&collections); err != nil {
|
||||
return fmt.Errorf("failed to fetch collections list: %v", err)
|
||||
}
|
||||
if len(collections) == 0 {
|
||||
return errors.New("missing collections to automigrate")
|
||||
}
|
||||
|
||||
names, err := p.getAllMigrationNames()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch migration files list: %v", err)
|
||||
}
|
||||
|
||||
// delete last consequitive automigrates
|
||||
lastAutomigrates := []string{}
|
||||
for i := len(names) - 1; i >= 0; i-- {
|
||||
migrationFile := names[i]
|
||||
if !strings.Contains(migrationFile, "_automigrate.") {
|
||||
break
|
||||
}
|
||||
lastAutomigrates = append(lastAutomigrates, migrationFile)
|
||||
}
|
||||
if len(lastAutomigrates) > 0 {
|
||||
// delete last automigrates from the db
|
||||
_, err := p.app.Dao().DB().Delete(migrationsTable, dbx.In("file", list.ToInterfaceSlice(lastAutomigrates)...)).Execute()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete last automigrates from the db: %v", err)
|
||||
}
|
||||
|
||||
// delete last automigrates from the filesystem
|
||||
for _, f := range lastAutomigrates {
|
||||
if err := os.Remove(filepath.Join(p.options.Dir, f)); err != nil && !os.IsNotExist(err) {
|
||||
return fmt.Errorf("failed to delete last automigrates from the filesystem: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var template string
|
||||
var templateErr error
|
||||
if p.options.TemplateLang == TemplateLangJS {
|
||||
template, templateErr = p.jsSnapshotTemplate(collections)
|
||||
} else {
|
||||
template, templateErr = p.goSnapshotTemplate(collections)
|
||||
}
|
||||
if templateErr != nil {
|
||||
return fmt.Errorf("failed to resolve template: %v", templateErr)
|
||||
}
|
||||
|
||||
// add a comment to not edit the template
|
||||
template = ("// Do not edit by hand since this file is autogenerated and may get overwritten.\n" +
|
||||
"// If you want to do further changes, create a new non '_automigrate' file instead.\n" + template)
|
||||
|
||||
appliedTime := time.Now().Unix()
|
||||
fileDest := filepath.Join(p.options.Dir, fmt.Sprintf("%d_automigrate.%s", appliedTime, p.options.TemplateLang))
|
||||
|
||||
// ensure that the local migrations dir exist
|
||||
if err := os.MkdirAll(p.options.Dir, os.ModePerm); err != nil {
|
||||
return fmt.Errorf("failed to create migration dir: %v", err)
|
||||
}
|
||||
|
||||
return os.WriteFile(fileDest, []byte(template), 0644)
|
||||
}
|
||||
}
|
||||
|
||||
// getAllMigrationNames return both applied and new local migration file names.
|
||||
func (p *plugin) getAllMigrationNames() ([]string, error) {
|
||||
names := []string{}
|
||||
|
||||
for _, migration := range m.AppMigrations.Items() {
|
||||
names = append(names, migration.File)
|
||||
}
|
||||
|
||||
localFiles, err := p.getLocalMigrationNames()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, name := range localFiles {
|
||||
if !list.ExistInSlice(name, names) {
|
||||
names = append(names, name)
|
||||
}
|
||||
}
|
||||
|
||||
sort.Slice(names, func(i int, j int) bool {
|
||||
return names[i] < names[j]
|
||||
})
|
||||
|
||||
return names, nil
|
||||
}
|
||||
|
||||
// getLocalMigrationNames returns a list with all local migration files
|
||||
//
|
||||
// Returns an empty slice if the migrations directory doesn't exist.
|
||||
func (p *plugin) getLocalMigrationNames() ([]string, error) {
|
||||
files, err := os.ReadDir(p.options.Dir)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return []string{}, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make([]string, 0, len(files))
|
||||
|
||||
for _, f := range files {
|
||||
if f.IsDir() {
|
||||
continue
|
||||
}
|
||||
result = append(result, f.Name())
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
210
plugins/migratecmd/migratecmd.go
Normal file
210
plugins/migratecmd/migratecmd.go
Normal file
@ -0,0 +1,210 @@
|
||||
package migratecmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
Dir string // the directory with user defined migrations
|
||||
AutoMigrate bool
|
||||
TemplateLang string
|
||||
}
|
||||
|
||||
type plugin struct {
|
||||
app core.App
|
||||
options *Options
|
||||
}
|
||||
|
||||
func MustRegister(app core.App, rootCmd *cobra.Command, options *Options) {
|
||||
if err := Register(app, rootCmd, options); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Register(app core.App, rootCmd *cobra.Command, options *Options) error {
|
||||
p := &plugin{app: app}
|
||||
|
||||
if options != nil {
|
||||
p.options = options
|
||||
} else {
|
||||
p.options = &Options{}
|
||||
}
|
||||
|
||||
if p.options.TemplateLang == "" {
|
||||
p.options.TemplateLang = TemplateLangGo
|
||||
}
|
||||
|
||||
if p.options.Dir == "" {
|
||||
if p.options.TemplateLang == TemplateLangJS {
|
||||
p.options.Dir = filepath.Join(p.app.DataDir(), "../pb_migrations")
|
||||
} else {
|
||||
p.options.Dir = filepath.Join(p.app.DataDir(), "../migrations")
|
||||
}
|
||||
}
|
||||
|
||||
// attach the migrate command
|
||||
if rootCmd != nil {
|
||||
rootCmd.AddCommand(p.createCommand())
|
||||
}
|
||||
|
||||
// watch for collection changes
|
||||
if p.options.AutoMigrate {
|
||||
// @todo replace with AfterBootstrap
|
||||
p.app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
|
||||
if err := p.tidyMigrationsTable(); err != nil && p.app.IsDebug() {
|
||||
log.Println("Failed to tidy the migrations table.")
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
p.app.OnModelAfterCreate().Add(p.onCollectionChange())
|
||||
p.app.OnModelAfterUpdate().Add(p.onCollectionChange())
|
||||
p.app.OnModelAfterDelete().Add(p.onCollectionChange())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *plugin) createCommand() *cobra.Command {
|
||||
const cmdDesc = `Supported arguments are:
|
||||
- up - runs all available migrations.
|
||||
- down [number] - reverts the last [number] applied migrations.
|
||||
- create name [folder] - creates new blank migration template file.
|
||||
- collections [folder] - creates new migration file with the latest local collections snapshot (similar to the automigrate but allows editing).
|
||||
`
|
||||
|
||||
command := &cobra.Command{
|
||||
Use: "migrate",
|
||||
Short: "Executes app DB migration scripts",
|
||||
ValidArgs: []string{"up", "down", "create", "collections"},
|
||||
Long: cmdDesc,
|
||||
Run: func(command *cobra.Command, args []string) {
|
||||
cmd := ""
|
||||
if len(args) > 0 {
|
||||
cmd = args[0]
|
||||
}
|
||||
|
||||
// additional commands
|
||||
// ---
|
||||
if cmd == "create" {
|
||||
if err := p.migrateCreateHandler("", args[1:]); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if cmd == "collections" {
|
||||
if err := p.migrateCollectionsHandler(args[1:]); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
// ---
|
||||
|
||||
runner, err := migrate.NewRunner(p.app.DB(), migrations.AppMigrations)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if err := runner.Run(args...); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
return command
|
||||
}
|
||||
|
||||
func (p *plugin) migrateCreateHandler(template string, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("Missing migration file name")
|
||||
}
|
||||
|
||||
name := args[0]
|
||||
|
||||
var dir string
|
||||
if len(args) == 2 {
|
||||
dir = args[1]
|
||||
}
|
||||
if dir == "" {
|
||||
dir = p.options.Dir
|
||||
}
|
||||
|
||||
resultFilePath := path.Join(
|
||||
dir,
|
||||
fmt.Sprintf("%d_%s.%s", time.Now().Unix(), inflector.Snakecase(name), p.options.TemplateLang),
|
||||
)
|
||||
|
||||
confirm := false
|
||||
prompt := &survey.Confirm{
|
||||
Message: fmt.Sprintf("Do you really want to create migration %q?", resultFilePath),
|
||||
}
|
||||
survey.AskOne(prompt, &confirm)
|
||||
if !confirm {
|
||||
fmt.Println("The command has been cancelled")
|
||||
return nil
|
||||
}
|
||||
|
||||
// get default create template
|
||||
if template == "" {
|
||||
var templateErr error
|
||||
if p.options.TemplateLang == TemplateLangJS {
|
||||
template, templateErr = p.jsCreateTemplate()
|
||||
} else {
|
||||
template, templateErr = p.goCreateTemplate()
|
||||
}
|
||||
if templateErr != nil {
|
||||
return fmt.Errorf("Failed to resolve create template: %v\n", templateErr)
|
||||
}
|
||||
}
|
||||
|
||||
// ensure that the migrations dir exist
|
||||
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// save the migration file
|
||||
if err := os.WriteFile(resultFilePath, []byte(template), 0644); err != nil {
|
||||
return fmt.Errorf("Failed to save migration file %q: %v\n", resultFilePath, err)
|
||||
}
|
||||
|
||||
fmt.Printf("Successfully created file %q\n", resultFilePath)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *plugin) migrateCollectionsHandler(args []string) error {
|
||||
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)
|
||||
}
|
||||
|
||||
var template string
|
||||
var templateErr error
|
||||
if p.options.TemplateLang == TemplateLangJS {
|
||||
template, templateErr = p.jsSnapshotTemplate(collections)
|
||||
} else {
|
||||
template, templateErr = p.goSnapshotTemplate(collections)
|
||||
}
|
||||
if templateErr != nil {
|
||||
return fmt.Errorf("Failed to resolve template: %v", templateErr)
|
||||
}
|
||||
|
||||
return p.migrateCreateHandler(template, createArgs)
|
||||
}
|
112
plugins/migratecmd/templates.go
Normal file
112
plugins/migratecmd/templates.go
Normal file
@ -0,0 +1,112 @@
|
||||
package migratecmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
)
|
||||
|
||||
const (
|
||||
TemplateLangJS = "js"
|
||||
TemplateLangGo = "go"
|
||||
)
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// JavaScript templates
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
func (p *plugin) jsCreateTemplate() (string, error) {
|
||||
const template = `migrate((db) => {
|
||||
// add up queries...
|
||||
}, (db) => {
|
||||
// add down queries...
|
||||
})
|
||||
`
|
||||
|
||||
return template, nil
|
||||
}
|
||||
|
||||
func (p *plugin) jsSnapshotTemplate(collections []*models.Collection) (string, error) {
|
||||
jsonData, err := json.MarshalIndent(collections, " ", " ")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to serialize collections list: %v", err)
|
||||
}
|
||||
|
||||
const template = `migrate((db) => {
|
||||
const snapshot = %s;
|
||||
|
||||
const collections = snapshot.map((item) => unmarshal(item, new Collection()));
|
||||
|
||||
return Dao(db).importCollections(collections, true, null);
|
||||
}, (db) => {
|
||||
return null;
|
||||
})
|
||||
`
|
||||
|
||||
return fmt.Sprintf(template, string(jsonData)), nil
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Go templates
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
func (p *plugin) goCreateTemplate() (string, error) {
|
||||
const template = `package %s
|
||||
|
||||
import (
|
||||
"github.com/pocketbase/dbx"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m.Register(func(db dbx.Builder) error {
|
||||
// add up queries...
|
||||
|
||||
return nil
|
||||
}, func(db dbx.Builder) error {
|
||||
// add down queries...
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
`
|
||||
|
||||
return fmt.Sprintf(template, filepath.Base(p.options.Dir)), nil
|
||||
}
|
||||
|
||||
func (p *plugin) goSnapshotTemplate(collections []*models.Collection) (string, error) {
|
||||
jsonData, err := json.MarshalIndent(collections, "\t", "\t\t")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to serialize collections list: %v", err)
|
||||
}
|
||||
|
||||
const template = `package %s
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/daos"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m.Register(func(db dbx.Builder) error {
|
||||
jsonData := ` + "`%s`" + `
|
||||
|
||||
collections := []*models.Collection{}
|
||||
if err := json.Unmarshal([]byte(jsonData), &collections); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return daos.New(db).ImportCollections(collections, true, nil)
|
||||
}, func(db dbx.Builder) error {
|
||||
return nil
|
||||
})
|
||||
}
|
||||
`
|
||||
return fmt.Sprintf(template, filepath.Base(p.options.Dir), string(jsonData)), nil
|
||||
}
|
84
plugins/publicdir/publicdir.go
Normal file
84
plugins/publicdir/publicdir.go
Normal file
@ -0,0 +1,84 @@
|
||||
// Example
|
||||
//
|
||||
// publicdir.MustRegister(app, &publicdir.Options{
|
||||
// FlagsCmd: app.RootCmd,
|
||||
// IndexFallback: false,
|
||||
// })
|
||||
package publicdir
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/pocketbase/pocketbase/apis"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
Dir string
|
||||
IndexFallback bool
|
||||
FlagsCmd *cobra.Command
|
||||
}
|
||||
|
||||
type plugin struct {
|
||||
app core.App
|
||||
options *Options
|
||||
}
|
||||
|
||||
func MustRegister(app core.App, options *Options) {
|
||||
if err := Register(app, options); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Register(app core.App, options *Options) error {
|
||||
p := &plugin{app: app}
|
||||
|
||||
if options != nil {
|
||||
p.options = options
|
||||
} else {
|
||||
p.options = &Options{}
|
||||
}
|
||||
|
||||
if options.Dir == "" {
|
||||
options.Dir = defaultPublicDir()
|
||||
}
|
||||
|
||||
if options.FlagsCmd != nil {
|
||||
// add "--publicDir" option flag
|
||||
options.FlagsCmd.PersistentFlags().StringVar(
|
||||
&options.Dir,
|
||||
"publicDir",
|
||||
options.Dir,
|
||||
"the directory to serve static files",
|
||||
)
|
||||
|
||||
// add "--indexFallback" option flag
|
||||
options.FlagsCmd.PersistentFlags().BoolVar(
|
||||
&options.IndexFallback,
|
||||
"indexFallback",
|
||||
options.IndexFallback,
|
||||
"fallback the request to index.html on missing static path (eg. when pretty urls are used with SPA)",
|
||||
)
|
||||
}
|
||||
|
||||
p.app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
|
||||
// serves static files from the provided public dir (if exists)
|
||||
e.Router.GET("/*", apis.StaticDirectoryHandler(os.DirFS(options.Dir), options.IndexFallback))
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func defaultPublicDir() string {
|
||||
if strings.HasPrefix(os.Args[0], os.TempDir()) {
|
||||
// most likely ran with go run
|
||||
return "./pb_public"
|
||||
}
|
||||
|
||||
return filepath.Join(os.Args[0], "../pb_public")
|
||||
}
|
@ -127,7 +127,6 @@ func NewWithConfig(config Config) *PocketBase {
|
||||
func (pb *PocketBase) Start() error {
|
||||
// register system commands
|
||||
pb.RootCmd.AddCommand(cmd.NewServeCommand(pb, !pb.hideStartBanner))
|
||||
pb.RootCmd.AddCommand(cmd.NewMigrateCommand(pb))
|
||||
pb.RootCmd.AddCommand(cmd.NewTempUpgradeCommand(pb))
|
||||
|
||||
return pb.Execute()
|
||||
|
@ -357,19 +357,19 @@ func createTestDir(t *testing.T) string {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
file1, err := os.OpenFile(filepath.Join(dir, "test/sub1.txt"), os.O_WRONLY|os.O_CREATE, 0666)
|
||||
file1, err := os.OpenFile(filepath.Join(dir, "test/sub1.txt"), os.O_WRONLY|os.O_CREATE, 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
file1.Close()
|
||||
|
||||
file2, err := os.OpenFile(filepath.Join(dir, "test/sub2.txt"), os.O_WRONLY|os.O_CREATE, 0666)
|
||||
file2, err := os.OpenFile(filepath.Join(dir, "test/sub2.txt"), os.O_WRONLY|os.O_CREATE, 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
file2.Close()
|
||||
|
||||
file3, err := os.OpenFile(filepath.Join(dir, "image.png"), os.O_WRONLY|os.O_CREATE, 0666)
|
||||
file3, err := os.OpenFile(filepath.Join(dir, "image.png"), os.O_WRONLY|os.O_CREATE, 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -377,18 +377,18 @@ func createTestDir(t *testing.T) string {
|
||||
imgRect := image.Rect(0, 0, 1, 1)
|
||||
png.Encode(file3, imgRect)
|
||||
file3.Close()
|
||||
err2 := os.WriteFile(filepath.Join(dir, "image.png.attrs"), []byte(`{"user.cache_control":"","user.content_disposition":"","user.content_encoding":"","user.content_language":"","user.content_type":"image/png","user.metadata":null}`), 0666)
|
||||
err2 := os.WriteFile(filepath.Join(dir, "image.png.attrs"), []byte(`{"user.cache_control":"","user.content_disposition":"","user.content_encoding":"","user.content_language":"","user.content_type":"image/png","user.metadata":null}`), 0644)
|
||||
if err2 != nil {
|
||||
t.Fatal(err2)
|
||||
}
|
||||
|
||||
file4, err := os.OpenFile(filepath.Join(dir, "image.svg"), os.O_WRONLY|os.O_CREATE, 0666)
|
||||
file4, err := os.OpenFile(filepath.Join(dir, "image.svg"), os.O_WRONLY|os.O_CREATE, 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
file4.Close()
|
||||
|
||||
file5, err := os.OpenFile(filepath.Join(dir, "style.css"), os.O_WRONLY|os.O_CREATE, 0666)
|
||||
file5, err := os.OpenFile(filepath.Join(dir, "style.css"), os.O_WRONLY|os.O_CREATE, 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -8,24 +8,24 @@ import (
|
||||
"github.com/pocketbase/dbx"
|
||||
)
|
||||
|
||||
type migration struct {
|
||||
file string
|
||||
up func(db dbx.Builder) error
|
||||
down func(db dbx.Builder) error
|
||||
type Migration struct {
|
||||
File string
|
||||
Up func(db dbx.Builder) error
|
||||
Down func(db dbx.Builder) error
|
||||
}
|
||||
|
||||
// MigrationsList defines a list with migration definitions
|
||||
type MigrationsList struct {
|
||||
list []*migration
|
||||
list []*Migration
|
||||
}
|
||||
|
||||
// Item returns a single migration from the list by its index.
|
||||
func (l *MigrationsList) Item(index int) *migration {
|
||||
func (l *MigrationsList) Item(index int) *Migration {
|
||||
return l.list[index]
|
||||
}
|
||||
|
||||
// Items returns the internal migrations list slice.
|
||||
func (l *MigrationsList) Items() []*migration {
|
||||
func (l *MigrationsList) Items() []*Migration {
|
||||
return l.list
|
||||
}
|
||||
|
||||
@ -47,13 +47,13 @@ func (l *MigrationsList) Register(
|
||||
file = filepath.Base(path)
|
||||
}
|
||||
|
||||
l.list = append(l.list, &migration{
|
||||
file: file,
|
||||
up: up,
|
||||
down: down,
|
||||
l.list = append(l.list, &Migration{
|
||||
File: file,
|
||||
Up: up,
|
||||
Down: down,
|
||||
})
|
||||
|
||||
sort.Slice(l.list, func(i int, j int) bool {
|
||||
return l.list[i].file < l.list[j].file
|
||||
return l.list[i].File < l.list[j].File
|
||||
})
|
||||
}
|
||||
|
@ -26,8 +26,8 @@ func TestMigrationsList(t *testing.T) {
|
||||
|
||||
for i, name := range expected {
|
||||
item := l.Item(i)
|
||||
if item.file != name {
|
||||
t.Fatalf("Expected name %s for index %d, got %s", name, i, item.file)
|
||||
if item.File != name {
|
||||
t.Fatalf("Expected name %s for index %d, got %s", name, i, item.File)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -111,19 +111,19 @@ func (r *Runner) Up() ([]string, error) {
|
||||
err := r.db.Transactional(func(tx *dbx.Tx) error {
|
||||
for _, m := range r.migrationsList.Items() {
|
||||
// skip applied
|
||||
if r.isMigrationApplied(tx, m.file) {
|
||||
if r.isMigrationApplied(tx, m.File) {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := m.up(tx); err != nil {
|
||||
return fmt.Errorf("Failed to apply migration %s: %w", m.file, err)
|
||||
if err := m.Up(tx); err != nil {
|
||||
return fmt.Errorf("Failed to apply migration %s: %w", m.File, err)
|
||||
}
|
||||
|
||||
if err := r.saveAppliedMigration(tx, m.file); err != nil {
|
||||
return fmt.Errorf("Failed to save applied migration info for %s: %w", m.file, err)
|
||||
if err := r.saveAppliedMigration(tx, m.File); err != nil {
|
||||
return fmt.Errorf("Failed to save applied migration info for %s: %w", m.File, err)
|
||||
}
|
||||
|
||||
applied = append(applied, m.file)
|
||||
applied = append(applied, m.File)
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -146,7 +146,7 @@ func (r *Runner) Down(toRevertCount int) ([]string, error) {
|
||||
m := r.migrationsList.Item(i)
|
||||
|
||||
// skip unapplied
|
||||
if !r.isMigrationApplied(tx, m.file) {
|
||||
if !r.isMigrationApplied(tx, m.File) {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -155,15 +155,15 @@ func (r *Runner) Down(toRevertCount int) ([]string, error) {
|
||||
break
|
||||
}
|
||||
|
||||
if err := m.down(tx); err != nil {
|
||||
return fmt.Errorf("Failed to revert migration %s: %w", m.file, err)
|
||||
if err := m.Down(tx); err != nil {
|
||||
return fmt.Errorf("Failed to revert migration %s: %w", m.File, err)
|
||||
}
|
||||
|
||||
if err := r.saveRevertedMigration(tx, m.file); err != nil {
|
||||
return fmt.Errorf("Failed to save reverted migration info for %s: %w", m.file, err)
|
||||
if err := r.saveRevertedMigration(tx, m.File); err != nil {
|
||||
return fmt.Errorf("Failed to save reverted migration info for %s: %w", m.File, err)
|
||||
}
|
||||
|
||||
reverted = append(reverted, m.file)
|
||||
reverted = append(reverted, m.File)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -79,7 +79,7 @@ func TestRunnerUpAndDown(t *testing.T) {
|
||||
}
|
||||
|
||||
// simulate partially run migration
|
||||
r.saveAppliedMigration(testDB, r.migrationsList.Item(0).file)
|
||||
r.saveAppliedMigration(testDB, r.migrationsList.Item(0).File)
|
||||
|
||||
// Up()
|
||||
// ---
|
||||
|
2
ui/.env
2
ui/.env
@ -7,4 +7,4 @@ PB_FILE_UPLOAD_DOCS = "https://pocketbase.io/docs/files-handling/"
|
||||
PB_JS_SDK_URL = "https://github.com/pocketbase/js-sdk"
|
||||
PB_DART_SDK_URL = "https://github.com/pocketbase/dart-sdk"
|
||||
PB_RELEASES = "https://github.com/pocketbase/pocketbase/releases"
|
||||
PB_VERSION = "v0.8.0"
|
||||
PB_VERSION = "v0.9.0-rc"
|
||||
|
Loading…
Reference in New Issue
Block a user