mirror of
https://github.com/pocketbase/pocketbase.git
synced 2026-09-30 19:41:43 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e73077e7e7 | ||
|
|
0113fecca9 | ||
|
|
fbc378067d | ||
|
|
e80d64414b | ||
|
|
7ffe9f63a5 | ||
|
|
5dbd9821e8 | ||
|
|
87c6c5b483 | ||
|
|
836fc77ddc | ||
|
|
3ef752c232 | ||
|
|
c7c590bace | ||
|
|
fac0d5b899 | ||
|
|
902e07e724 | ||
|
|
dc350f0a3e | ||
|
|
1a3efe96ac | ||
|
|
18f152a0e7 | ||
|
|
52dcb4192c | ||
|
|
08b1b49e17 |
No files matched your search
@@ -28,7 +28,7 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '>=1.23.6'
|
||||
go-version: '>=1.23.9'
|
||||
|
||||
# This step usually is not needed because the /ui/dist is pregenerated locally
|
||||
# but its here to ensure that each release embeds the latest admin ui artifacts.
|
||||
|
||||
@@ -1,3 +1,27 @@
|
||||
## v0.28.1
|
||||
|
||||
- Fixed `json_each`/`json_array_length` normalizations to properly check for array values ([#6835](https://github.com/pocketbase/pocketbase/issues/6835)).
|
||||
|
||||
|
||||
## v0.28.0
|
||||
|
||||
- Write the default response body of `*Request` hooks that are wrapped in a transaction after the related transaction completes to allow propagating the transaction error ([#6462](https://github.com/pocketbase/pocketbase/discussions/6462#discussioncomment-12207818)).
|
||||
|
||||
- Updated `app.DB()` to automatically routes raw write SQL statements to the nonconcurrent db pool ([#6689](https://github.com/pocketbase/pocketbase/discussions/6689)).
|
||||
_For the rare cases when it is needed users still have the option to explicitly target the specific pool they want using `app.ConcurrentDB()`/`app.NonconcurrentDB()`._
|
||||
|
||||
- ⚠️ Changed the default `json` field max size to 1MB.
|
||||
_Users still have the option to adjust the default limit from the collection field options but keep in mind that storing large strings/blobs in the database is known to cause performance issues and should be avoided when possible._
|
||||
|
||||
- ⚠️ Soft-deprecated and replaced `filesystem.System.GetFile(fileKey)` with `filesystem.System.GetReader(fileKey)` to avoid the confusion with `filesystem.File`.
|
||||
_The old method will still continue to work for at least until v0.29.0 but you'll get a console warning to replace it with `GetReader`._
|
||||
|
||||
- Added new `filesystem.System.GetReuploadableFile(fileKey, preserveName)` method to return an existing blob as a `*filesystem.File` value ([#6792](https://github.com/pocketbase/pocketbase/discussions/6792)).
|
||||
_This method could be useful in case you want to clone an existing Record file and assign it to a new Record (e.g. in a Record duplicate action)._
|
||||
|
||||
- Other minor improvements (updated the GitHub release min Go version to 1.23.9, updated npm and Go deps, etc.)
|
||||
|
||||
|
||||
## v0.27.2
|
||||
|
||||
- Added workers pool when cascade deleting record files to minimize _"thread exhaustion"_ errors ([#6780](https://github.com/pocketbase/pocketbase/discussions/6780)).
|
||||
|
||||
+5
-5
@@ -49,7 +49,7 @@ var ValidBatchActions = map[*regexp.Regexp]BatchActionHandlerFunc{
|
||||
params["id"] = id // required for the path value
|
||||
ir.Method = "PATCH"
|
||||
ir.URL = "/api/collections/" + params["collection"] + "/records/" + id + params["query"]
|
||||
return recordUpdate(next)
|
||||
return recordUpdate(false, next)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,16 +57,16 @@ var ValidBatchActions = map[*regexp.Regexp]BatchActionHandlerFunc{
|
||||
// ---
|
||||
ir.Method = "POST"
|
||||
ir.URL = "/api/collections/" + params["collection"] + "/records" + params["query"]
|
||||
return recordCreate(next)
|
||||
return recordCreate(false, next)
|
||||
},
|
||||
regexp.MustCompile(`^POST /api/collections/(?P<collection>[^\/\?]+)/records(\?.*)?$`): func(app core.App, ir *core.InternalRequest, params map[string]string, next func(any) error) HandleFunc {
|
||||
return recordCreate(next)
|
||||
return recordCreate(false, next)
|
||||
},
|
||||
regexp.MustCompile(`^PATCH /api/collections/(?P<collection>[^\/\?]+)/records/(?P<id>[^\/\?]+)(\?.*)?$`): func(app core.App, ir *core.InternalRequest, params map[string]string, next func(any) error) HandleFunc {
|
||||
return recordUpdate(next)
|
||||
return recordUpdate(false, next)
|
||||
},
|
||||
regexp.MustCompile(`^DELETE /api/collections/(?P<collection>[^\/\?]+)/records/(?P<id>[^\/\?]+)(\?.*)?$`): func(app core.App, ir *core.InternalRequest, params map[string]string, next func(any) error) HandleFunc {
|
||||
return recordDelete(next)
|
||||
return recordDelete(false, next)
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
+15
-5
@@ -45,7 +45,9 @@ func collectionsList(e *core.RequestEvent) error {
|
||||
event.Result = result
|
||||
|
||||
return event.App.OnCollectionsListRequest().Trigger(event, func(e *core.CollectionsListRequestEvent) error {
|
||||
return e.JSON(http.StatusOK, e.Result)
|
||||
return execAfterSuccessTx(true, e.App, func() error {
|
||||
return e.JSON(http.StatusOK, e.Result)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -60,7 +62,9 @@ func collectionView(e *core.RequestEvent) error {
|
||||
event.Collection = collection
|
||||
|
||||
return e.App.OnCollectionViewRequest().Trigger(event, func(e *core.CollectionRequestEvent) error {
|
||||
return e.JSON(http.StatusOK, e.Collection)
|
||||
return execAfterSuccessTx(true, e.App, func() error {
|
||||
return e.JSON(http.StatusOK, e.Collection)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -98,7 +102,9 @@ func collectionCreate(e *core.RequestEvent) error {
|
||||
return e.BadRequestError("Failed to create collection. Raw error: \n"+err.Error(), nil)
|
||||
}
|
||||
|
||||
return e.JSON(http.StatusOK, e.Collection)
|
||||
return execAfterSuccessTx(true, e.App, func() error {
|
||||
return e.JSON(http.StatusOK, e.Collection)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -128,7 +134,9 @@ func collectionUpdate(e *core.RequestEvent) error {
|
||||
return e.BadRequestError("Failed to update collection. Raw error: \n"+err.Error(), nil)
|
||||
}
|
||||
|
||||
return e.JSON(http.StatusOK, e.Collection)
|
||||
return execAfterSuccessTx(true, e.App, func() error {
|
||||
return e.JSON(http.StatusOK, e.Collection)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -159,7 +167,9 @@ func collectionDelete(e *core.RequestEvent) error {
|
||||
return e.BadRequestError(msg, err)
|
||||
}
|
||||
|
||||
return e.NoContent(http.StatusNoContent)
|
||||
return execAfterSuccessTx(true, e.App, func() error {
|
||||
return e.NoContent(http.StatusNoContent)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,9 @@ func collectionsImport(e *core.RequestEvent) error {
|
||||
return event.App.OnCollectionsImportRequest().Trigger(event, func(e *core.CollectionsImportRequestEvent) error {
|
||||
importErr := e.App.ImportCollections(e.CollectionsData, form.DeleteMissing)
|
||||
if importErr == nil {
|
||||
return e.NoContent(http.StatusNoContent)
|
||||
return execAfterSuccessTx(true, e.App, func() error {
|
||||
return e.NoContent(http.StatusNoContent)
|
||||
})
|
||||
}
|
||||
|
||||
// validation failure
|
||||
|
||||
@@ -316,6 +316,51 @@ func TestCollectionsImport(t *testing.T) {
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "OnCollectionsImportRequest tx body write check",
|
||||
Method: http.MethodPut,
|
||||
URL: "/api/collections/import",
|
||||
Body: strings.NewReader(`{
|
||||
"deleteMissing": true,
|
||||
"collections":[
|
||||
{"name": "test123"},
|
||||
{
|
||||
"id":"wsmn24bux7wo113",
|
||||
"name":"demo1",
|
||||
"fields":[
|
||||
{
|
||||
"id":"_2hlxbmp",
|
||||
"name":"title",
|
||||
"type":"text",
|
||||
"required":true
|
||||
}
|
||||
],
|
||||
"indexes": []
|
||||
}
|
||||
]
|
||||
}`),
|
||||
Headers: map[string]string{
|
||||
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
||||
},
|
||||
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||
app.OnCollectionsImportRequest().BindFunc(func(e *core.CollectionsImportRequestEvent) error {
|
||||
original := e.App
|
||||
return e.App.RunInTransaction(func(txApp core.App) error {
|
||||
e.App = txApp
|
||||
defer func() { e.App = original }()
|
||||
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.BadRequestError("TX_ERROR", nil)
|
||||
})
|
||||
})
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedEvents: map[string]int{"OnCollectionsImportRequest": 1},
|
||||
ExpectedContent: []string{"TX_ERROR"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, scenario := range scenarios {
|
||||
|
||||
+94
-22
@@ -1,7 +1,6 @@
|
||||
package apis_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -130,6 +129,32 @@ func TestCollectionsList(t *testing.T) {
|
||||
"OnCollectionsListRequest": 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "OnCollectionsListRequest tx body write check",
|
||||
Method: http.MethodGet,
|
||||
URL: "/api/collections",
|
||||
Headers: map[string]string{
|
||||
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
||||
},
|
||||
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||
app.OnCollectionsListRequest().BindFunc(func(e *core.CollectionsListRequestEvent) error {
|
||||
original := e.App
|
||||
return e.App.RunInTransaction(func(txApp core.App) error {
|
||||
e.App = txApp
|
||||
defer func() { e.App = original }()
|
||||
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.BadRequestError("TX_ERROR", nil)
|
||||
})
|
||||
})
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedEvents: map[string]int{"OnCollectionsListRequest": 1},
|
||||
ExpectedContent: []string{"TX_ERROR"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, scenario := range scenarios {
|
||||
@@ -205,6 +230,32 @@ func TestCollectionView(t *testing.T) {
|
||||
"OnCollectionViewRequest": 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "OnCollectionViewRequest tx body write check",
|
||||
Method: http.MethodGet,
|
||||
URL: "/api/collections/wsmn24bux7wo113",
|
||||
Headers: map[string]string{
|
||||
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
||||
},
|
||||
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||
app.OnCollectionViewRequest().BindFunc(func(e *core.CollectionRequestEvent) error {
|
||||
original := e.App
|
||||
return e.App.RunInTransaction(func(txApp core.App) error {
|
||||
e.App = txApp
|
||||
defer func() { e.App = original }()
|
||||
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.BadRequestError("TX_ERROR", nil)
|
||||
})
|
||||
})
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedEvents: map[string]int{"OnCollectionViewRequest": 1},
|
||||
ExpectedContent: []string{"TX_ERROR"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, scenario := range scenarios {
|
||||
@@ -361,7 +412,7 @@ func TestCollectionDelete(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "OnCollectionAfterDeleteSuccessRequest error response",
|
||||
Name: "OnCollectionDeleteRequest tx body write check",
|
||||
Method: http.MethodDelete,
|
||||
URL: "/api/collections/view2",
|
||||
Headers: map[string]string{
|
||||
@@ -369,15 +420,22 @@ func TestCollectionDelete(t *testing.T) {
|
||||
},
|
||||
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||
app.OnCollectionDeleteRequest().BindFunc(func(e *core.CollectionRequestEvent) error {
|
||||
return errors.New("error")
|
||||
original := e.App
|
||||
return e.App.RunInTransaction(func(txApp core.App) error {
|
||||
e.App = txApp
|
||||
defer func() { e.App = original }()
|
||||
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.BadRequestError("TX_ERROR", nil)
|
||||
})
|
||||
})
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedContent: []string{`"data":{}`},
|
||||
ExpectedEvents: map[string]int{
|
||||
"*": 0,
|
||||
"OnCollectionDeleteRequest": 1,
|
||||
},
|
||||
ExpectedEvents: map[string]int{"OnCollectionDeleteRequest": 1},
|
||||
ExpectedContent: []string{"TX_ERROR"},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -656,7 +714,7 @@ func TestCollectionCreate(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "OnCollectionCreateRequest error response",
|
||||
Name: "OnCollectionCreateRequest tx body write check",
|
||||
Method: http.MethodPost,
|
||||
URL: "/api/collections",
|
||||
Body: strings.NewReader(`{"name":"new","type":"base"}`),
|
||||
@@ -665,15 +723,22 @@ func TestCollectionCreate(t *testing.T) {
|
||||
},
|
||||
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||
app.OnCollectionCreateRequest().BindFunc(func(e *core.CollectionRequestEvent) error {
|
||||
return errors.New("error")
|
||||
original := e.App
|
||||
return e.App.RunInTransaction(func(txApp core.App) error {
|
||||
e.App = txApp
|
||||
defer func() { e.App = original }()
|
||||
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.BadRequestError("TX_ERROR", nil)
|
||||
})
|
||||
})
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedContent: []string{`"data":{}`},
|
||||
ExpectedEvents: map[string]int{
|
||||
"*": 0,
|
||||
"OnCollectionCreateRequest": 1,
|
||||
},
|
||||
ExpectedEvents: map[string]int{"OnCollectionCreateRequest": 1},
|
||||
ExpectedContent: []string{"TX_ERROR"},
|
||||
},
|
||||
|
||||
// view
|
||||
@@ -978,7 +1043,7 @@ func TestCollectionUpdate(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "OnCollectionAfterUpdateSuccessRequest error response",
|
||||
Name: "OnCollectionUpdateRequest tx body write check",
|
||||
Method: http.MethodPatch,
|
||||
URL: "/api/collections/demo1",
|
||||
Body: strings.NewReader(`{}`),
|
||||
@@ -987,15 +1052,22 @@ func TestCollectionUpdate(t *testing.T) {
|
||||
},
|
||||
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||
app.OnCollectionUpdateRequest().BindFunc(func(e *core.CollectionRequestEvent) error {
|
||||
return errors.New("error")
|
||||
original := e.App
|
||||
return e.App.RunInTransaction(func(txApp core.App) error {
|
||||
e.App = txApp
|
||||
defer func() { e.App = original }()
|
||||
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.BadRequestError("TX_ERROR", nil)
|
||||
})
|
||||
})
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedContent: []string{`"data":{}`},
|
||||
ExpectedEvents: map[string]int{
|
||||
"*": 0,
|
||||
"OnCollectionUpdateRequest": 1,
|
||||
},
|
||||
ExpectedEvents: map[string]int{"OnCollectionUpdateRequest": 1},
|
||||
ExpectedContent: []string{"TX_ERROR"},
|
||||
},
|
||||
{
|
||||
Name: "authorized as superuser + invalid data (eg. existing name)",
|
||||
|
||||
+6
-3
@@ -75,8 +75,8 @@ func (api *fileApi) fileToken(e *core.RequestEvent) error {
|
||||
event.Record = e.Auth
|
||||
|
||||
return e.App.OnFileTokenRequest().Trigger(event, func(e *core.FileTokenRequestEvent) error {
|
||||
return e.JSON(http.StatusOK, map[string]string{
|
||||
"token": e.Token,
|
||||
return execAfterSuccessTx(true, e.App, func() error {
|
||||
return e.JSON(http.StatusOK, map[string]string{"token": e.Token})
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -192,7 +192,10 @@ func (api *fileApi) download(e *core.RequestEvent) error {
|
||||
e.Response.Header().Del("X-Frame-Options")
|
||||
|
||||
return e.App.OnFileDownloadRequest().Trigger(event, func(e *core.FileDownloadRequestEvent) error {
|
||||
if err := fsys.Serve(e.Response, e.Request, e.ServedPath, e.ServedName); err != nil {
|
||||
err = execAfterSuccessTx(true, e.App, func() error {
|
||||
return fsys.Serve(e.Response, e.Request, e.ServedPath, e.ServedName)
|
||||
})
|
||||
if err != nil {
|
||||
return e.NotFoundError("", err)
|
||||
}
|
||||
|
||||
|
||||
+17
-3
@@ -365,11 +365,25 @@ func logRequest(event *core.RequestEvent, err error) {
|
||||
|
||||
// parse the request error
|
||||
if err != nil {
|
||||
if apiErr, ok := err.(*router.ApiError); ok {
|
||||
status = apiErr.Status
|
||||
apiErr, isPlainApiError := err.(*router.ApiError)
|
||||
if isPlainApiError || errors.As(err, &apiErr) {
|
||||
// the status header wasn't written yet
|
||||
if status == 0 {
|
||||
status = apiErr.Status
|
||||
}
|
||||
|
||||
var errMsg string
|
||||
if isPlainApiError {
|
||||
errMsg = apiErr.Message
|
||||
} else {
|
||||
// wrapped ApiError -> add the full serialized version
|
||||
// of the original error since it could contain more information
|
||||
errMsg = err.Error()
|
||||
}
|
||||
|
||||
attrs = append(
|
||||
attrs,
|
||||
slog.String("error", apiErr.Message),
|
||||
slog.String("error", errMsg),
|
||||
slog.Any("details", apiErr.RawData()),
|
||||
)
|
||||
} else {
|
||||
|
||||
+4
-2
@@ -213,7 +213,9 @@ func realtimeSetSubscriptions(e *core.RequestEvent) error {
|
||||
slog.Any("subscriptions", e.Subscriptions),
|
||||
)
|
||||
|
||||
return e.NoContent(http.StatusNoContent)
|
||||
return execAfterSuccessTx(true, e.App, func() error {
|
||||
return e.NoContent(http.StatusNoContent)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -756,7 +758,7 @@ func realtimeCanAccessRecord(
|
||||
|
||||
var exists int
|
||||
|
||||
q := app.DB().Select("(1)").
|
||||
q := app.ConcurrentDB().Select("(1)").
|
||||
From(record.Collection().Name).
|
||||
AndWhere(dbx.HashExp{record.Collection().Name + ".id": record.Id})
|
||||
|
||||
|
||||
@@ -45,7 +45,9 @@ func recordConfirmEmailChange(e *core.RequestEvent) error {
|
||||
return firstApiError(err, e.BadRequestError("Failed to confirm email change.", err))
|
||||
}
|
||||
|
||||
return e.NoContent(http.StatusNoContent)
|
||||
return execAfterSuccessTx(true, e.App, func() error {
|
||||
return e.NoContent(http.StatusNoContent)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package apis_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -136,7 +135,7 @@ func TestRecordConfirmEmailChange(t *testing.T) {
|
||||
ExpectedEvents: map[string]int{"*": 0},
|
||||
},
|
||||
{
|
||||
Name: "OnRecordAfterConfirmEmailChangeRequest error response",
|
||||
Name: "OnRecordConfirmEmailChangeRequest tx body write check",
|
||||
Method: http.MethodPost,
|
||||
URL: "/api/collections/users/confirm-email-change",
|
||||
Body: strings.NewReader(`{
|
||||
@@ -145,15 +144,22 @@ func TestRecordConfirmEmailChange(t *testing.T) {
|
||||
}`),
|
||||
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||
app.OnRecordConfirmEmailChangeRequest().BindFunc(func(e *core.RecordConfirmEmailChangeRequestEvent) error {
|
||||
return errors.New("error")
|
||||
original := e.App
|
||||
return e.App.RunInTransaction(func(txApp core.App) error {
|
||||
e.App = txApp
|
||||
defer func() { e.App = original }()
|
||||
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.BadRequestError("TX_ERROR", nil)
|
||||
})
|
||||
})
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedContent: []string{`"data":{}`},
|
||||
ExpectedEvents: map[string]int{
|
||||
"*": 0,
|
||||
"OnRecordConfirmEmailChangeRequest": 1,
|
||||
},
|
||||
ExpectedEvents: map[string]int{"OnRecordConfirmEmailChangeRequest": 1},
|
||||
ExpectedContent: []string{"TX_ERROR"},
|
||||
},
|
||||
|
||||
// rate limit checks
|
||||
|
||||
@@ -43,7 +43,9 @@ func recordRequestEmailChange(e *core.RequestEvent) error {
|
||||
return firstApiError(err, e.BadRequestError("Failed to request email change.", err))
|
||||
}
|
||||
|
||||
return e.NoContent(http.StatusNoContent)
|
||||
return execAfterSuccessTx(true, e.App, func() error {
|
||||
return e.NoContent(http.StatusNoContent)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -118,6 +118,33 @@ func TestRecordRequestEmailChange(t *testing.T) {
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "OnRecordRequestEmailChangeRequest tx body write check",
|
||||
Method: http.MethodPost,
|
||||
URL: "/api/collections/users/request-email-change",
|
||||
Body: strings.NewReader(`{"newEmail":"change@example.com"}`),
|
||||
Headers: map[string]string{
|
||||
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IjRxMXhsY2xtZmxva3UzMyIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoiX3BiX3VzZXJzX2F1dGhfIiwiZXhwIjoyNTI0NjA0NDYxLCJyZWZyZXNoYWJsZSI6dHJ1ZX0.ZT3F0Z3iM-xbGgSG3LEKiEzHrPHr8t8IuHLZGGNuxLo",
|
||||
},
|
||||
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||
app.OnRecordRequestEmailChangeRequest().BindFunc(func(e *core.RecordRequestEmailChangeRequestEvent) error {
|
||||
original := e.App
|
||||
return e.App.RunInTransaction(func(txApp core.App) error {
|
||||
e.App = txApp
|
||||
defer func() { e.App = original }()
|
||||
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.BadRequestError("TX_ERROR", nil)
|
||||
})
|
||||
})
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedEvents: map[string]int{"OnRecordRequestEmailChangeRequest": 1},
|
||||
ExpectedContent: []string{"TX_ERROR"},
|
||||
},
|
||||
|
||||
// rate limit checks
|
||||
// -----------------------------------------------------------
|
||||
|
||||
@@ -26,10 +26,10 @@ func recordAuthImpersonate(e *core.RequestEvent) error {
|
||||
|
||||
form := &impersonateForm{}
|
||||
if err = e.BindBody(form); err != nil {
|
||||
return firstApiError(err, e.BadRequestError("An error occurred while loading the submitted data.", err))
|
||||
return e.BadRequestError("An error occurred while loading the submitted data.", err)
|
||||
}
|
||||
if err = form.validate(); err != nil {
|
||||
return firstApiError(err, e.BadRequestError("An error occurred while validating the submitted data.", err))
|
||||
return e.BadRequestError("An error occurred while validating the submitted data.", err)
|
||||
}
|
||||
|
||||
token, err := record.NewStaticAuthToken(time.Duration(form.Duration) * time.Second)
|
||||
|
||||
@@ -108,8 +108,8 @@ func recordRequestOTP(e *core.RequestEvent) error {
|
||||
})
|
||||
}
|
||||
|
||||
return e.JSON(http.StatusOK, map[string]string{
|
||||
"otpId": otp.Id,
|
||||
return execAfterSuccessTx(true, e.App, func() error {
|
||||
return e.JSON(http.StatusOK, map[string]string{"otpId": otp.Id})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -247,6 +247,31 @@ func TestRecordRequestOTP(t *testing.T) {
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "OnRecordRequestOTPRequest tx body write check",
|
||||
Method: http.MethodPost,
|
||||
URL: "/api/collections/users/request-otp",
|
||||
Body: strings.NewReader(`{"email":"test@example.com"}`),
|
||||
Delay: 100 * time.Millisecond,
|
||||
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||
app.OnRecordRequestOTPRequest().BindFunc(func(e *core.RecordCreateOTPRequestEvent) error {
|
||||
original := e.App
|
||||
return e.App.RunInTransaction(func(txApp core.App) error {
|
||||
e.App = txApp
|
||||
defer func() { e.App = original }()
|
||||
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.BadRequestError("TX_ERROR", nil)
|
||||
})
|
||||
})
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedEvents: map[string]int{"OnRecordRequestOTPRequest": 1},
|
||||
ExpectedContent: []string{"TX_ERROR"},
|
||||
},
|
||||
|
||||
// rate limit checks
|
||||
// -----------------------------------------------------------
|
||||
|
||||
@@ -54,7 +54,9 @@ func recordConfirmPasswordReset(e *core.RequestEvent) error {
|
||||
|
||||
e.App.Store().Remove(getPasswordResetResendKey(authRecord))
|
||||
|
||||
return e.NoContent(http.StatusNoContent)
|
||||
return execAfterSuccessTx(true, e.App, func() error {
|
||||
return e.NoContent(http.StatusNoContent)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package apis_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -282,7 +281,7 @@ func TestRecordConfirmPasswordReset(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "OnRecordAfterConfirmPasswordResetRequest error response",
|
||||
Name: "OnRecordConfirmPasswordResetRequest tx body write check",
|
||||
Method: http.MethodPost,
|
||||
URL: "/api/collections/users/confirm-password-reset",
|
||||
Body: strings.NewReader(`{
|
||||
@@ -292,15 +291,22 @@ func TestRecordConfirmPasswordReset(t *testing.T) {
|
||||
}`),
|
||||
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||
app.OnRecordConfirmPasswordResetRequest().BindFunc(func(e *core.RecordConfirmPasswordResetRequestEvent) error {
|
||||
return errors.New("error")
|
||||
original := e.App
|
||||
return e.App.RunInTransaction(func(txApp core.App) error {
|
||||
e.App = txApp
|
||||
defer func() { e.App = original }()
|
||||
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.BadRequestError("TX_ERROR", nil)
|
||||
})
|
||||
})
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedContent: []string{`"data":{}`},
|
||||
ExpectedEvents: map[string]int{
|
||||
"*": 0,
|
||||
"OnRecordConfirmPasswordResetRequest": 1,
|
||||
},
|
||||
ExpectedEvents: map[string]int{"OnRecordConfirmPasswordResetRequest": 1},
|
||||
ExpectedContent: []string{"TX_ERROR"},
|
||||
},
|
||||
|
||||
// rate limit checks
|
||||
|
||||
@@ -65,7 +65,9 @@ func recordRequestPasswordReset(e *core.RequestEvent) error {
|
||||
})
|
||||
})
|
||||
|
||||
return e.NoContent(http.StatusNoContent)
|
||||
return execAfterSuccessTx(true, e.App, func() error {
|
||||
return e.NoContent(http.StatusNoContent)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -101,6 +101,30 @@ func TestRecordRequestPasswordReset(t *testing.T) {
|
||||
app.Store().Set(resendKey, struct{}{})
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "OnRecordRequestPasswordResetRequest tx body write check",
|
||||
Method: http.MethodPost,
|
||||
URL: "/api/collections/users/request-password-reset",
|
||||
Body: strings.NewReader(`{"email":"test@example.com"}`),
|
||||
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||
app.OnRecordRequestPasswordResetRequest().BindFunc(func(e *core.RecordRequestPasswordResetRequestEvent) error {
|
||||
original := e.App
|
||||
return e.App.RunInTransaction(func(txApp core.App) error {
|
||||
e.App = txApp
|
||||
defer func() { e.App = original }()
|
||||
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.BadRequestError("TX_ERROR", nil)
|
||||
})
|
||||
})
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedEvents: map[string]int{"OnRecordRequestPasswordResetRequest": 1},
|
||||
ExpectedContent: []string{"TX_ERROR"},
|
||||
},
|
||||
|
||||
// rate limit checks
|
||||
// -----------------------------------------------------------
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package apis_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
@@ -130,23 +129,30 @@ func TestRecordAuthRefresh(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "OnRecordAfterAuthRefreshRequest error response",
|
||||
Name: "OnRecordAuthRefreshRequest tx body write check",
|
||||
Method: http.MethodPost,
|
||||
URL: "/api/collections/users/auth-refresh?expand=rel,missing",
|
||||
URL: "/api/collections/users/auth-refresh",
|
||||
Headers: map[string]string{
|
||||
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IjRxMXhsY2xtZmxva3UzMyIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoiX3BiX3VzZXJzX2F1dGhfIiwiZXhwIjoyNTI0NjA0NDYxLCJyZWZyZXNoYWJsZSI6dHJ1ZX0.ZT3F0Z3iM-xbGgSG3LEKiEzHrPHr8t8IuHLZGGNuxLo",
|
||||
},
|
||||
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||
app.OnRecordAuthRefreshRequest().BindFunc(func(e *core.RecordAuthRefreshRequestEvent) error {
|
||||
return errors.New("error")
|
||||
original := e.App
|
||||
return e.App.RunInTransaction(func(txApp core.App) error {
|
||||
e.App = txApp
|
||||
defer func() { e.App = original }()
|
||||
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.BadRequestError("TX_ERROR", nil)
|
||||
})
|
||||
})
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedContent: []string{`"data":{}`},
|
||||
ExpectedEvents: map[string]int{
|
||||
"*": 0,
|
||||
"OnRecordAuthRefreshRequest": 1,
|
||||
},
|
||||
ExpectedEvents: map[string]int{"OnRecordAuthRefreshRequest": 1},
|
||||
ExpectedContent: []string{"TX_ERROR"},
|
||||
},
|
||||
|
||||
// rate limit checks
|
||||
|
||||
@@ -42,19 +42,19 @@ func recordConfirmVerification(e *core.RequestEvent) error {
|
||||
event.Record = record
|
||||
|
||||
return e.App.OnRecordConfirmVerificationRequest().Trigger(event, func(e *core.RecordConfirmVerificationRequestEvent) error {
|
||||
if wasVerified {
|
||||
return e.NoContent(http.StatusNoContent)
|
||||
}
|
||||
if !wasVerified {
|
||||
e.Record.SetVerified(true)
|
||||
|
||||
e.Record.SetVerified(true)
|
||||
|
||||
if err := e.App.Save(e.Record); err != nil {
|
||||
return firstApiError(err, e.BadRequestError("An error occurred while saving the verified state.", err))
|
||||
if err := e.App.Save(e.Record); err != nil {
|
||||
return firstApiError(err, e.BadRequestError("An error occurred while saving the verified state.", err))
|
||||
}
|
||||
}
|
||||
|
||||
e.App.Store().Remove(getVerificationResendKey(e.Record))
|
||||
|
||||
return e.NoContent(http.StatusNoContent)
|
||||
return execAfterSuccessTx(true, e.App, func() error {
|
||||
return e.NoContent(http.StatusNoContent)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package apis_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -144,7 +143,7 @@ func TestRecordConfirmVerification(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "OnRecordAfterConfirmVerificationRequest error response",
|
||||
Name: "OnRecordConfirmVerificationRequest tx body write check",
|
||||
Method: http.MethodPost,
|
||||
URL: "/api/collections/users/confirm-verification",
|
||||
Body: strings.NewReader(`{
|
||||
@@ -152,15 +151,22 @@ func TestRecordConfirmVerification(t *testing.T) {
|
||||
}`),
|
||||
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||
app.OnRecordConfirmVerificationRequest().BindFunc(func(e *core.RecordConfirmVerificationRequestEvent) error {
|
||||
return errors.New("error")
|
||||
original := e.App
|
||||
return e.App.RunInTransaction(func(txApp core.App) error {
|
||||
e.App = txApp
|
||||
defer func() { e.App = original }()
|
||||
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.BadRequestError("TX_ERROR", nil)
|
||||
})
|
||||
})
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedContent: []string{`"data":{}`},
|
||||
ExpectedEvents: map[string]int{
|
||||
"*": 0,
|
||||
"OnRecordConfirmVerificationRequest": 1,
|
||||
},
|
||||
ExpectedEvents: map[string]int{"OnRecordConfirmVerificationRequest": 1},
|
||||
ExpectedContent: []string{"TX_ERROR"},
|
||||
},
|
||||
|
||||
// rate limit checks
|
||||
|
||||
@@ -68,7 +68,9 @@ func recordRequestVerification(e *core.RequestEvent) error {
|
||||
})
|
||||
})
|
||||
|
||||
return e.NoContent(http.StatusNoContent)
|
||||
return execAfterSuccessTx(true, e.App, func() error {
|
||||
return e.NoContent(http.StatusNoContent)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -118,6 +118,30 @@ func TestRecordRequestVerification(t *testing.T) {
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "OnRecordRequestVerificationRequest tx body write check",
|
||||
Method: http.MethodPost,
|
||||
URL: "/api/collections/users/request-verification",
|
||||
Body: strings.NewReader(`{"email":"test@example.com"}`),
|
||||
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||
app.OnRecordRequestVerificationRequest().BindFunc(func(e *core.RecordRequestVerificationRequestEvent) error {
|
||||
original := e.App
|
||||
return e.App.RunInTransaction(func(txApp core.App) error {
|
||||
e.App = txApp
|
||||
defer func() { e.App = original }()
|
||||
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.BadRequestError("TX_ERROR", nil)
|
||||
})
|
||||
})
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedEvents: map[string]int{"OnRecordRequestVerificationRequest": 1},
|
||||
ExpectedContent: []string{"TX_ERROR"},
|
||||
},
|
||||
|
||||
// rate limit checks
|
||||
// -----------------------------------------------------------
|
||||
|
||||
@@ -1577,6 +1577,69 @@ func TestRecordAuthWithOAuth2(t *testing.T) {
|
||||
"OnRecordValidate": 4,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "OnRecordAuthWithOAuth2Request tx body write check",
|
||||
Method: http.MethodPost,
|
||||
URL: "/api/collections/users/auth-with-oauth2",
|
||||
Body: strings.NewReader(`{
|
||||
"provider": "test",
|
||||
"code":"123",
|
||||
"redirectURL": "https://example.com"
|
||||
}`),
|
||||
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||
user, err := app.FindAuthRecordByEmail("users", "test@example.com")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// register the test provider
|
||||
auth.Providers["test"] = func() auth.Provider {
|
||||
return &oauth2MockProvider{
|
||||
AuthUser: &auth.AuthUser{Id: "test_id"},
|
||||
Token: &oauth2.Token{AccessToken: "abc"},
|
||||
}
|
||||
}
|
||||
|
||||
// add the test provider in the collection
|
||||
user.Collection().MFA.Enabled = false
|
||||
user.Collection().OAuth2.Enabled = true
|
||||
user.Collection().OAuth2.Providers = []core.OAuth2ProviderConfig{{
|
||||
Name: "test",
|
||||
ClientId: "123",
|
||||
ClientSecret: "456",
|
||||
}}
|
||||
if err := app.Save(user.Collection()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// stub linked provider
|
||||
ea := core.NewExternalAuth(app)
|
||||
ea.SetCollectionRef(user.Collection().Id)
|
||||
ea.SetRecordRef(user.Id)
|
||||
ea.SetProvider("test")
|
||||
ea.SetProviderId("test_id")
|
||||
if err := app.Save(ea); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
app.OnRecordAuthWithOAuth2Request().BindFunc(func(e *core.RecordAuthWithOAuth2RequestEvent) error {
|
||||
original := e.App
|
||||
return e.App.RunInTransaction(func(txApp core.App) error {
|
||||
e.App = txApp
|
||||
defer func() { e.App = original }()
|
||||
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.BadRequestError("TX_ERROR", nil)
|
||||
})
|
||||
})
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedEvents: map[string]int{"OnRecordAuthWithOAuth2Request": 1},
|
||||
ExpectedContent: []string{"TX_ERROR"},
|
||||
},
|
||||
|
||||
// rate limit checks
|
||||
// -----------------------------------------------------------
|
||||
|
||||
@@ -419,6 +419,53 @@ func TestRecordAuthWithOTP(t *testing.T) {
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "OnRecordAuthWithOTPRequest tx body write check",
|
||||
Method: http.MethodPost,
|
||||
URL: "/api/collections/users/auth-with-otp",
|
||||
Body: strings.NewReader(`{
|
||||
"otpId":"` + strings.Repeat("a", 15) + `",
|
||||
"password":"123456"
|
||||
}`),
|
||||
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||
user, err := app.FindAuthRecordByEmail("users", "test@example.com")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// disable MFA
|
||||
user.Collection().MFA.Enabled = false
|
||||
if err = app.Save(user.Collection()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
otp := core.NewOTP(app)
|
||||
otp.Id = strings.Repeat("a", 15)
|
||||
otp.SetCollectionRef(user.Collection().Id)
|
||||
otp.SetRecordRef(user.Id)
|
||||
otp.SetPassword("123456")
|
||||
if err := app.Save(otp); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
app.OnRecordAuthWithOTPRequest().BindFunc(func(e *core.RecordAuthWithOTPRequestEvent) error {
|
||||
original := e.App
|
||||
return e.App.RunInTransaction(func(txApp core.App) error {
|
||||
e.App = txApp
|
||||
defer func() { e.App = original }()
|
||||
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.BadRequestError("TX_ERROR", nil)
|
||||
})
|
||||
})
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedEvents: map[string]int{"OnRecordAuthWithOTPRequest": 1},
|
||||
ExpectedContent: []string{"TX_ERROR"},
|
||||
},
|
||||
|
||||
// rate limit checks
|
||||
// -----------------------------------------------------------
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package apis_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -82,7 +81,7 @@ func TestRecordAuthWithPassword(t *testing.T) {
|
||||
ExpectedEvents: map[string]int{"*": 0},
|
||||
},
|
||||
{
|
||||
Name: "OnRecordAuthWithPasswordRequest error response",
|
||||
Name: "OnRecordAuthWithPasswordRequest tx body write check",
|
||||
Method: http.MethodPost,
|
||||
URL: "/api/collections/clients/auth-with-password",
|
||||
Body: strings.NewReader(`{
|
||||
@@ -91,15 +90,22 @@ func TestRecordAuthWithPassword(t *testing.T) {
|
||||
}`),
|
||||
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||
app.OnRecordAuthWithPasswordRequest().BindFunc(func(e *core.RecordAuthWithPasswordRequestEvent) error {
|
||||
return errors.New("error")
|
||||
original := e.App
|
||||
return e.App.RunInTransaction(func(txApp core.App) error {
|
||||
e.App = txApp
|
||||
defer func() { e.App = original }()
|
||||
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.BadRequestError("TX_ERROR", nil)
|
||||
})
|
||||
})
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedContent: []string{`"data":{}`},
|
||||
ExpectedEvents: map[string]int{
|
||||
"*": 0,
|
||||
"OnRecordAuthWithPasswordRequest": 1,
|
||||
},
|
||||
ExpectedEvents: map[string]int{"OnRecordAuthWithPasswordRequest": 1},
|
||||
ExpectedContent: []string{"TX_ERROR"},
|
||||
},
|
||||
{
|
||||
Name: "valid identity field and invalid password",
|
||||
|
||||
+24
-14
@@ -28,9 +28,9 @@ func bindRecordCrudApi(app core.App, rg *router.RouterGroup[*core.RequestEvent])
|
||||
subGroup := rg.Group("/collections/{collection}/records").Unbind(DefaultRateLimitMiddlewareId)
|
||||
subGroup.GET("", recordsList)
|
||||
subGroup.GET("/{id}", recordView)
|
||||
subGroup.POST("", recordCreate(nil)).Bind(dynamicCollectionBodyLimit(""))
|
||||
subGroup.PATCH("/{id}", recordUpdate(nil)).Bind(dynamicCollectionBodyLimit(""))
|
||||
subGroup.DELETE("/{id}", recordDelete(nil))
|
||||
subGroup.POST("", recordCreate(true, nil)).Bind(dynamicCollectionBodyLimit(""))
|
||||
subGroup.PATCH("/{id}", recordUpdate(true, nil)).Bind(dynamicCollectionBodyLimit(""))
|
||||
subGroup.DELETE("/{id}", recordDelete(true, nil))
|
||||
}
|
||||
|
||||
func recordsList(e *core.RequestEvent) error {
|
||||
@@ -121,7 +121,9 @@ func recordsList(e *core.RequestEvent) error {
|
||||
randomizedThrottle(150)
|
||||
}
|
||||
|
||||
return e.JSON(http.StatusOK, e.Result)
|
||||
return execAfterSuccessTx(true, e.App, func() error {
|
||||
return e.JSON(http.StatusOK, e.Result)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -192,11 +194,13 @@ func recordView(e *core.RequestEvent) error {
|
||||
return firstApiError(err, e.InternalServerError("Failed to enrich record", err))
|
||||
}
|
||||
|
||||
return e.JSON(http.StatusOK, e.Record)
|
||||
return execAfterSuccessTx(true, e.App, func() error {
|
||||
return e.JSON(http.StatusOK, e.Record)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func recordCreate(optFinalizer func(data any) error) func(e *core.RequestEvent) error {
|
||||
func recordCreate(responseWriteAfterTx bool, optFinalizer func(data any) error) func(e *core.RequestEvent) error {
|
||||
return func(e *core.RequestEvent) error {
|
||||
collection, err := e.App.FindCachedCollectionByNameOrId(e.Request.PathValue("collection"))
|
||||
if err != nil || collection == nil {
|
||||
@@ -296,7 +300,7 @@ func recordCreate(optFinalizer func(data any) error) func(e *core.RequestEvent)
|
||||
|
||||
// check non-empty create rule
|
||||
if *dummyCollection.CreateRule != "" {
|
||||
ruleQuery := e.App.DB().Select("(1)").PreFragment(withFrom).From(dummyCollection.Name).AndBind(dummyParams)
|
||||
ruleQuery := e.App.ConcurrentDB().Select("(1)").PreFragment(withFrom).From(dummyCollection.Name).AndBind(dummyParams)
|
||||
|
||||
resolver := core.NewRecordFieldResolver(e.App, &dummyCollection, requestInfo, true)
|
||||
|
||||
@@ -316,7 +320,7 @@ func recordCreate(optFinalizer func(data any) error) func(e *core.RequestEvent)
|
||||
}
|
||||
|
||||
// check for manage rule access
|
||||
manageRuleQuery := e.App.DB().Select("(1)").PreFragment(withFrom).From(dummyCollection.Name).AndBind(dummyParams)
|
||||
manageRuleQuery := e.App.ConcurrentDB().Select("(1)").PreFragment(withFrom).From(dummyCollection.Name).AndBind(dummyParams)
|
||||
if !form.HasManageAccess() &&
|
||||
hasAuthManageAccess(e.App, requestInfo, &dummyCollection, manageRuleQuery) {
|
||||
form.GrantManagerAccess()
|
||||
@@ -344,7 +348,9 @@ func recordCreate(optFinalizer func(data any) error) func(e *core.RequestEvent)
|
||||
return firstApiError(err, e.InternalServerError("Failed to enrich record", err))
|
||||
}
|
||||
|
||||
err = e.JSON(http.StatusOK, e.Record)
|
||||
err = execAfterSuccessTx(responseWriteAfterTx, e.App, func() error {
|
||||
return e.JSON(http.StatusOK, e.Record)
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -374,7 +380,7 @@ func recordCreate(optFinalizer func(data any) error) func(e *core.RequestEvent)
|
||||
}
|
||||
}
|
||||
|
||||
func recordUpdate(optFinalizer func(data any) error) func(e *core.RequestEvent) error {
|
||||
func recordUpdate(responseWriteAfterTx bool, optFinalizer func(data any) error) func(e *core.RequestEvent) error {
|
||||
return func(e *core.RequestEvent) error {
|
||||
collection, err := e.App.FindCachedCollectionByNameOrId(e.Request.PathValue("collection"))
|
||||
if err != nil || collection == nil {
|
||||
@@ -446,7 +452,7 @@ func recordUpdate(optFinalizer func(data any) error) func(e *core.RequestEvent)
|
||||
}
|
||||
form.Load(data)
|
||||
|
||||
manageRuleQuery := e.App.DB().Select("(1)").From(collection.Name).AndWhere(dbx.HashExp{
|
||||
manageRuleQuery := e.App.ConcurrentDB().Select("(1)").From(collection.Name).AndWhere(dbx.HashExp{
|
||||
collection.Name + ".id": record.Id,
|
||||
})
|
||||
if !form.HasManageAccess() &&
|
||||
@@ -475,7 +481,9 @@ func recordUpdate(optFinalizer func(data any) error) func(e *core.RequestEvent)
|
||||
return firstApiError(err, e.InternalServerError("Failed to enrich record", err))
|
||||
}
|
||||
|
||||
err = e.JSON(http.StatusOK, e.Record)
|
||||
err = execAfterSuccessTx(responseWriteAfterTx, e.App, func() error {
|
||||
return e.JSON(http.StatusOK, e.Record)
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -505,7 +513,7 @@ func recordUpdate(optFinalizer func(data any) error) func(e *core.RequestEvent)
|
||||
}
|
||||
}
|
||||
|
||||
func recordDelete(optFinalizer func(data any) error) func(e *core.RequestEvent) error {
|
||||
func recordDelete(responseWriteAfterTx bool, optFinalizer func(data any) error) func(e *core.RequestEvent) error {
|
||||
return func(e *core.RequestEvent) error {
|
||||
collection, err := e.App.FindCachedCollectionByNameOrId(e.Request.PathValue("collection"))
|
||||
if err != nil || collection == nil {
|
||||
@@ -565,7 +573,9 @@ func recordDelete(optFinalizer func(data any) error) func(e *core.RequestEvent)
|
||||
return firstApiError(err, e.BadRequestError("Failed to delete record. Make sure that the record is not part of a required relation reference.", err))
|
||||
}
|
||||
|
||||
err = e.NoContent(http.StatusNoContent)
|
||||
err = execAfterSuccessTx(responseWriteAfterTx, e.App, func() error {
|
||||
return e.NoContent(http.StatusNoContent)
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+100
-22
@@ -2,7 +2,6 @@ package apis_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
@@ -418,6 +417,32 @@ func TestRecordCrudList(t *testing.T) {
|
||||
"OnRecordsListRequest": 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "OnRecordsListRequest tx body write check",
|
||||
Method: http.MethodGet,
|
||||
URL: "/api/collections/demo4/records",
|
||||
Headers: map[string]string{
|
||||
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
||||
},
|
||||
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||
app.OnRecordsListRequest().BindFunc(func(e *core.RecordsListRequestEvent) error {
|
||||
original := e.App
|
||||
return e.App.RunInTransaction(func(txApp core.App) error {
|
||||
e.App = txApp
|
||||
defer func() { e.App = original }()
|
||||
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.BadRequestError("TX_ERROR", nil)
|
||||
})
|
||||
})
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedEvents: map[string]int{"OnRecordsListRequest": 1},
|
||||
ExpectedContent: []string{"TX_ERROR"},
|
||||
},
|
||||
|
||||
// auth collection
|
||||
// -----------------------------------------------------------
|
||||
@@ -862,6 +887,32 @@ func TestRecordCrudView(t *testing.T) {
|
||||
"OnRecordEnrich": 7,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "OnRecordViewRequest tx body write check",
|
||||
Method: http.MethodGet,
|
||||
URL: "/api/collections/demo1/records/al1h9ijdeojtsjy",
|
||||
Headers: map[string]string{
|
||||
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
||||
},
|
||||
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||
app.OnRecordViewRequest().BindFunc(func(e *core.RecordRequestEvent) error {
|
||||
original := e.App
|
||||
return e.App.RunInTransaction(func(txApp core.App) error {
|
||||
e.App = txApp
|
||||
defer func() { e.App = original }()
|
||||
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.BadRequestError("TX_ERROR", nil)
|
||||
})
|
||||
})
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedEvents: map[string]int{"OnRecordViewRequest": 1},
|
||||
ExpectedContent: []string{"TX_ERROR"},
|
||||
},
|
||||
|
||||
// auth collection
|
||||
// -----------------------------------------------------------
|
||||
@@ -1209,7 +1260,7 @@ func TestRecordCrudDelete(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "OnRecordAfterDeleteSuccessRequest error response",
|
||||
Name: "OnRecordDeleteRequest tx body write check",
|
||||
Method: http.MethodDelete,
|
||||
URL: "/api/collections/clients/records/o1y0dd0spd786md",
|
||||
Headers: map[string]string{
|
||||
@@ -1217,15 +1268,22 @@ func TestRecordCrudDelete(t *testing.T) {
|
||||
},
|
||||
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||
app.OnRecordDeleteRequest().BindFunc(func(e *core.RecordRequestEvent) error {
|
||||
return errors.New("error")
|
||||
original := e.App
|
||||
return e.App.RunInTransaction(func(txApp core.App) error {
|
||||
e.App = txApp
|
||||
defer func() { e.App = original }()
|
||||
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.BadRequestError("TX_ERROR", nil)
|
||||
})
|
||||
})
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedContent: []string{`"data":{}`},
|
||||
ExpectedEvents: map[string]int{
|
||||
"*": 0,
|
||||
"OnRecordDeleteRequest": 1,
|
||||
},
|
||||
ExpectedEvents: map[string]int{"OnRecordDeleteRequest": 1},
|
||||
ExpectedContent: []string{"TX_ERROR"},
|
||||
},
|
||||
{
|
||||
Name: "authenticated record that match the collection delete rule",
|
||||
@@ -1792,21 +1850,31 @@ func TestRecordCrudCreate(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "OnRecordAfterCreateSuccessRequest error response",
|
||||
Name: "OnRecordCreateRequest tx body write check",
|
||||
Method: http.MethodPost,
|
||||
URL: "/api/collections/demo2/records",
|
||||
Body: strings.NewReader(`{"title":"new"}`),
|
||||
Headers: map[string]string{
|
||||
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
||||
},
|
||||
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||
app.OnRecordCreateRequest().BindFunc(func(e *core.RecordRequestEvent) error {
|
||||
return errors.New("error")
|
||||
original := e.App
|
||||
return e.App.RunInTransaction(func(txApp core.App) error {
|
||||
e.App = txApp
|
||||
defer func() { e.App = original }()
|
||||
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.BadRequestError("TX_ERROR", nil)
|
||||
})
|
||||
})
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedContent: []string{`"data":{}`},
|
||||
ExpectedEvents: map[string]int{
|
||||
"*": 0,
|
||||
"OnRecordCreateRequest": 1,
|
||||
},
|
||||
ExpectedEvents: map[string]int{"OnRecordCreateRequest": 1},
|
||||
ExpectedContent: []string{"TX_ERROR"},
|
||||
},
|
||||
|
||||
// ID checks
|
||||
@@ -2799,21 +2867,31 @@ func TestRecordCrudUpdate(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "OnRecordAfterUpdateSuccessRequest error response",
|
||||
Name: "OnRecordUpdateRequest tx body write check",
|
||||
Method: http.MethodPatch,
|
||||
URL: "/api/collections/demo2/records/0yxhwia2amd8gec",
|
||||
Body: strings.NewReader(`{"title":"new"}`),
|
||||
Headers: map[string]string{
|
||||
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
||||
},
|
||||
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||
app.OnRecordUpdateRequest().BindFunc(func(e *core.RecordRequestEvent) error {
|
||||
return errors.New("error")
|
||||
original := e.App
|
||||
return e.App.RunInTransaction(func(txApp core.App) error {
|
||||
e.App = txApp
|
||||
defer func() { e.App = original }()
|
||||
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.BadRequestError("TX_ERROR", nil)
|
||||
})
|
||||
})
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedContent: []string{`"data":{}`},
|
||||
ExpectedEvents: map[string]int{
|
||||
"*": 0,
|
||||
"OnRecordUpdateRequest": 1,
|
||||
},
|
||||
ExpectedEvents: map[string]int{"OnRecordUpdateRequest": 1},
|
||||
ExpectedContent: []string{"TX_ERROR"},
|
||||
},
|
||||
{
|
||||
Name: "try to change the id of an existing record",
|
||||
|
||||
+26
-3
@@ -129,7 +129,9 @@ func recordAuthResponse(e *core.RequestEvent, authRecord *core.Record, token str
|
||||
result.Meta = e.Meta
|
||||
}
|
||||
|
||||
return e.JSON(http.StatusOK, result)
|
||||
return execAfterSuccessTx(true, e.App, func() error {
|
||||
return e.JSON(http.StatusOK, result)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -455,8 +457,8 @@ func autoResolveRecordsFlags(app core.App, records []*core.Record, requestInfo *
|
||||
managedIds := []string{}
|
||||
|
||||
query := app.RecordQuery(collection).
|
||||
Select(app.DB().QuoteSimpleColumnName(collection.Name) + ".id").
|
||||
AndWhere(dbx.In(app.DB().QuoteSimpleColumnName(collection.Name)+".id", recordIds...))
|
||||
Select(app.ConcurrentDB().QuoteSimpleColumnName(collection.Name) + ".id").
|
||||
AndWhere(dbx.In(app.ConcurrentDB().QuoteSimpleColumnName(collection.Name)+".id", recordIds...))
|
||||
|
||||
resolver := core.NewRecordFieldResolver(app, collection, requestInfo, true)
|
||||
expr, err := search.FilterData(*collection.ManageRule).BuildExpr(resolver)
|
||||
@@ -535,6 +537,27 @@ func firstApiError(errs ...error) *router.ApiError {
|
||||
return router.NewInternalServerError("", errors.Join(errs...))
|
||||
}
|
||||
|
||||
// execAfterSuccessTx ensures that fn is executed only after a succesul transaction.
|
||||
//
|
||||
// If the current app instance is not a transactional or checkTx is false,
|
||||
// then fn is directly executed.
|
||||
//
|
||||
// It could be usually used to allow propagating an error or writing
|
||||
// custom response from within the wrapped transaction block.
|
||||
func execAfterSuccessTx(checkTx bool, app core.App, fn func() error) error {
|
||||
if txInfo := app.TxInfo(); txInfo != nil && checkTx {
|
||||
txInfo.OnComplete(func(txErr error) error {
|
||||
if txErr == nil {
|
||||
return fn()
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
return fn()
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
const maxAuthOrigins = 5
|
||||
|
||||
+6
-2
@@ -30,7 +30,9 @@ func settingsList(e *core.RequestEvent) error {
|
||||
event.Settings = clone
|
||||
|
||||
return e.App.OnSettingsListRequest().Trigger(event, func(e *core.SettingsListRequestEvent) error {
|
||||
return e.JSON(http.StatusOK, e.Settings)
|
||||
return execAfterSuccessTx(true, e.App, func() error {
|
||||
return e.JSON(http.StatusOK, e.Settings)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -65,7 +67,9 @@ func settingsSet(e *core.RequestEvent) error {
|
||||
return e.InternalServerError("Failed to clone app settings.", err)
|
||||
}
|
||||
|
||||
return e.JSON(http.StatusOK, appSettings)
|
||||
return execAfterSuccessTx(true, e.App, func() error {
|
||||
return e.JSON(http.StatusOK, appSettings)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
"github.com/pocketbase/pocketbase/tests"
|
||||
)
|
||||
|
||||
@@ -58,6 +59,32 @@ func TestSettingsList(t *testing.T) {
|
||||
"OnSettingsListRequest": 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "OnSettingsListRequest tx body write check",
|
||||
Method: http.MethodGet,
|
||||
URL: "/api/settings",
|
||||
Headers: map[string]string{
|
||||
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
||||
},
|
||||
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||
app.OnSettingsListRequest().BindFunc(func(e *core.SettingsListRequestEvent) error {
|
||||
original := e.App
|
||||
return e.App.RunInTransaction(func(txApp core.App) error {
|
||||
e.App = txApp
|
||||
defer func() { e.App = original }()
|
||||
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.BadRequestError("TX_ERROR", nil)
|
||||
})
|
||||
})
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedEvents: map[string]int{"OnSettingsListRequest": 1},
|
||||
ExpectedContent: []string{"TX_ERROR"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, scenario := range scenarios {
|
||||
@@ -176,6 +203,33 @@ func TestSettingsSet(t *testing.T) {
|
||||
"OnSettingsReload": 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "OnSettingsUpdateRequest tx body write check",
|
||||
Method: http.MethodPatch,
|
||||
URL: "/api/settings",
|
||||
Body: strings.NewReader(validData),
|
||||
Headers: map[string]string{
|
||||
"Authorization": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5d2JoZWNuaDQ2cmhtMCIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoicGJjXzMxNDI2MzU4MjMiLCJleHAiOjI1MjQ2MDQ0NjEsInJlZnJlc2hhYmxlIjp0cnVlfQ.UXgO3j-0BumcugrFjbd7j0M4MQvbrLggLlcu_YNGjoY",
|
||||
},
|
||||
BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) {
|
||||
app.OnSettingsUpdateRequest().BindFunc(func(e *core.SettingsUpdateRequestEvent) error {
|
||||
original := e.App
|
||||
return e.App.RunInTransaction(func(txApp core.App) error {
|
||||
e.App = txApp
|
||||
defer func() { e.App = original }()
|
||||
|
||||
if err := e.Next(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.BadRequestError("TX_ERROR", nil)
|
||||
})
|
||||
})
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedEvents: map[string]int{"OnSettingsUpdateRequest": 1},
|
||||
ExpectedContent: []string{"TX_ERROR"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, scenario := range scenarios {
|
||||
|
||||
+59
-19
@@ -45,6 +45,12 @@ type App interface {
|
||||
// IsTransactional checks if the current app instance is part of a transaction.
|
||||
IsTransactional() bool
|
||||
|
||||
// TxInfo returns the transaction associated with the current app instance (if any).
|
||||
//
|
||||
// Could be used if you want to execute indirectly a function after
|
||||
// the related app transaction completes using `app.TxInfo().OnAfterFunc(callback)`.
|
||||
TxInfo() *TxAppInfo
|
||||
|
||||
// Bootstrap initializes the application
|
||||
// (aka. create data dir, open db connections, load settings, etc.).
|
||||
//
|
||||
@@ -140,46 +146,82 @@ type App interface {
|
||||
// DB methods
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
// DB returns the default app data db instance (pb_data/data.db).
|
||||
// DB returns the default app data.db builder instance.
|
||||
//
|
||||
// To minimize SQLITE_BUSY errors, it automatically routes the
|
||||
// SELECT queries to the underlying concurrent db pool and everything else
|
||||
// to the nonconcurrent one.
|
||||
//
|
||||
// For more finer control over the used connections pools you can
|
||||
// call directly ConcurrentDB() or NonconcurrentDB().
|
||||
DB() dbx.Builder
|
||||
|
||||
// NonconcurrentDB returns the nonconcurrent app data db instance (pb_data/data.db).
|
||||
// ConcurrentDB returns the concurrent app data.db builder instance.
|
||||
//
|
||||
// This method is used mainly internally for executing db read
|
||||
// operations in a concurrent/non-blocking manner.
|
||||
//
|
||||
// Most users should use simply DB() as it will automatically
|
||||
// route the query execution to ConcurrentDB() or NonconcurrentDB().
|
||||
//
|
||||
// In a transaction the ConcurrentDB() and NonconcurrentDB() refer to the same *dbx.TX instance.
|
||||
ConcurrentDB() dbx.Builder
|
||||
|
||||
// NonconcurrentDB returns the nonconcurrent app data.db builder instance.
|
||||
//
|
||||
// The returned db instance is limited only to a single open connection,
|
||||
// meaning that it can process only 1 db operation at a time (other operations will be queued up).
|
||||
// meaning that it can process only 1 db operation at a time (other queries queue up).
|
||||
//
|
||||
// This method is used mainly internally and in the tests to execute write
|
||||
// (save/delete) db operations as it helps with minimizing the SQLITE_BUSY errors.
|
||||
//
|
||||
// For the majority of cases you would want to use the regular DB() method
|
||||
// since it allows concurrent db read operations.
|
||||
// Most users should use simply DB() as it will automatically
|
||||
// route the query execution to ConcurrentDB() or NonconcurrentDB().
|
||||
//
|
||||
// In a transaction the ConcurrentDB() and NonconcurrentDB() refer to the same *dbx.TX instance.
|
||||
NonconcurrentDB() dbx.Builder
|
||||
|
||||
// AuxDB returns the default app auxiliary db instance (pb_data/auxiliary.db).
|
||||
// AuxDB returns the app auxiliary.db builder instance.
|
||||
//
|
||||
// To minimize SQLITE_BUSY errors, it automatically routes the
|
||||
// SELECT queries to the underlying concurrent db pool and everything else
|
||||
// to the nonconcurrent one.
|
||||
//
|
||||
// For more finer control over the used connections pools you can
|
||||
// call directly AuxConcurrentDB() or AuxNonconcurrentDB().
|
||||
AuxDB() dbx.Builder
|
||||
|
||||
// AuxNonconcurrentDB returns the nonconcurrent app auxiliary db instance (pb_data/auxiliary.db)..
|
||||
// AuxConcurrentDB returns the concurrent app auxiliary.db builder instance.
|
||||
//
|
||||
// This method is used mainly internally for executing db read
|
||||
// operations in a concurrent/non-blocking manner.
|
||||
//
|
||||
// Most users should use simply AuxDB() as it will automatically
|
||||
// route the query execution to AuxConcurrentDB() or AuxNonconcurrentDB().
|
||||
//
|
||||
// In a transaction the AuxConcurrentDB() and AuxNonconcurrentDB() refer to the same *dbx.TX instance.
|
||||
AuxConcurrentDB() dbx.Builder
|
||||
|
||||
// AuxNonconcurrentDB returns the nonconcurrent app auxiliary.db builder instance.
|
||||
//
|
||||
// The returned db instance is limited only to a single open connection,
|
||||
// meaning that it can process only 1 db operation at a time (other operations will be queued up).
|
||||
// meaning that it can process only 1 db operation at a time (other queries queue up).
|
||||
//
|
||||
// This method is used mainly internally and in the tests to execute write
|
||||
// (save/delete) db operations as it helps with minimizing the SQLITE_BUSY errors.
|
||||
//
|
||||
// For the majority of cases you would want to use the regular DB() method
|
||||
// since it allows concurrent db read operations.
|
||||
// Most users should use simply AuxDB() as it will automatically
|
||||
// route the query execution to AuxConcurrentDB() or AuxNonconcurrentDB().
|
||||
//
|
||||
// In a transaction the AuxNonconcurrentDB() and AuxNonconcurrentDB() refer to the same *dbx.TX instance.
|
||||
// In a transaction the AuxConcurrentDB() and AuxNonconcurrentDB() refer to the same *dbx.TX instance.
|
||||
AuxNonconcurrentDB() dbx.Builder
|
||||
|
||||
// HasTable checks if a table (or view) with the provided name exists (case insensitive).
|
||||
// in the current app.DB() instance.
|
||||
// in the data.db.
|
||||
HasTable(tableName string) bool
|
||||
|
||||
// AuxHasTable checks if a table (or view) with the provided name exists (case insensitive)
|
||||
// in the current app.AuxDB() instance.
|
||||
// in the auxiliary.db.
|
||||
AuxHasTable(tableName string) bool
|
||||
|
||||
// TableColumns returns all column names of a single table by its name.
|
||||
@@ -225,21 +267,19 @@ type App interface {
|
||||
// FindRecordByViewFile returns the original Record of the provided view collection file.
|
||||
FindRecordByViewFile(viewCollectionModelOrIdentifier any, fileFieldName string, filename string) (*Record, error)
|
||||
|
||||
// Vacuum executes VACUUM on the current app.DB() instance
|
||||
// in order to reclaim unused data db disk space.
|
||||
// Vacuum executes VACUUM on the data.db in order to reclaim unused data db disk space.
|
||||
Vacuum() error
|
||||
|
||||
// AuxVacuum executes VACUUM on the current app.AuxDB() instance
|
||||
// in order to reclaim unused auxiliary db disk space.
|
||||
// AuxVacuum executes VACUUM on the auxiliary.db in order to reclaim unused auxiliary db disk space.
|
||||
AuxVacuum() error
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
// ModelQuery creates a new preconfigured select app.DB() query with preset
|
||||
// ModelQuery creates a new preconfigured select data.db query with preset
|
||||
// SELECT, FROM and other common fields based on the provided model.
|
||||
ModelQuery(model Model) *dbx.SelectQuery
|
||||
|
||||
// AuxModelQuery creates a new preconfigured select app.AuxDB() query with preset
|
||||
// AuxModelQuery creates a new preconfigured select auxiliary.db query with preset
|
||||
// SELECT, FROM and other common fields based on the provided model.
|
||||
AuxModelQuery(model Model) *dbx.SelectQuery
|
||||
|
||||
|
||||
+82
-18
@@ -71,7 +71,7 @@ var _ App = (*BaseApp)(nil)
|
||||
// BaseApp implements core.App and defines the base PocketBase app structure.
|
||||
type BaseApp struct {
|
||||
config *BaseAppConfig
|
||||
txInfo *txAppInfo
|
||||
txInfo *TxAppInfo
|
||||
store *store.Store[string, any]
|
||||
cron *cron.Cron
|
||||
settings *Settings
|
||||
@@ -362,9 +362,17 @@ func (app *BaseApp) Logger() *slog.Logger {
|
||||
return app.logger
|
||||
}
|
||||
|
||||
// TxInfo returns the transaction associated with the current app instance (if any).
|
||||
//
|
||||
// Could be used if you want to execute indirectly a function after
|
||||
// the related app transaction completes using `app.TxInfo().OnAfterFunc(callback)`.
|
||||
func (app *BaseApp) TxInfo() *TxAppInfo {
|
||||
return app.txInfo
|
||||
}
|
||||
|
||||
// IsTransactional checks if the current app instance is part of a transaction.
|
||||
func (app *BaseApp) IsTransactional() bool {
|
||||
return app.txInfo != nil
|
||||
return app.TxInfo() != nil
|
||||
}
|
||||
|
||||
// IsBootstrapped checks if the application was initialized
|
||||
@@ -468,44 +476,100 @@ func (app *BaseApp) ResetBootstrapState() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DB returns the default app data db instance (pb_data/data.db).
|
||||
// DB returns the default app data.db builder instance.
|
||||
//
|
||||
// To minimize SQLITE_BUSY errors, it automatically routes the
|
||||
// SELECT queries to the underlying concurrent db pool and everything
|
||||
// else to the nonconcurrent one.
|
||||
//
|
||||
// For more finer control over the used connections pools you can
|
||||
// call directly ConcurrentDB() or NonconcurrentDB().
|
||||
func (app *BaseApp) DB() dbx.Builder {
|
||||
// transactional or both are nil
|
||||
if app.concurrentDB == app.nonconcurrentDB {
|
||||
return app.concurrentDB
|
||||
}
|
||||
|
||||
return &dualDBBuilder{
|
||||
concurrentDB: app.concurrentDB,
|
||||
nonconcurrentDB: app.nonconcurrentDB,
|
||||
}
|
||||
}
|
||||
|
||||
// ConcurrentDB returns the concurrent app data.db builder instance.
|
||||
//
|
||||
// This method is used mainly internally for executing db read
|
||||
// operations in a concurrent/non-blocking manner.
|
||||
//
|
||||
// Most users should use simply DB() as it will automatically
|
||||
// route the query execution to ConcurrentDB() or NonconcurrentDB().
|
||||
//
|
||||
// In a transaction the ConcurrentDB() and NonconcurrentDB() refer to the same *dbx.TX instance.
|
||||
func (app *BaseApp) ConcurrentDB() dbx.Builder {
|
||||
return app.concurrentDB
|
||||
}
|
||||
|
||||
// NonconcurrentDB returns the nonconcurrent app data db instance (pb_data/data.db).
|
||||
// NonconcurrentDB returns the nonconcurrent app data.db builder instance.
|
||||
//
|
||||
// The returned db instance is limited only to a single open connection,
|
||||
// meaning that it can process only 1 db operation at a time (other operations will be queued up).
|
||||
// meaning that it can process only 1 db operation at a time (other queries queue up).
|
||||
//
|
||||
// This method is used mainly internally and in the tests to execute write
|
||||
// (save/delete) db operations as it helps with minimizing the SQLITE_BUSY errors.
|
||||
//
|
||||
// For the majority of cases you would want to use the regular DB() method
|
||||
// since it allows concurrent db read operations.
|
||||
// Most users should use simply DB() as it will automatically
|
||||
// route the query execution to ConcurrentDB() or NonconcurrentDB().
|
||||
//
|
||||
// In a transaction the ConcurrentDB() and NonconcurrentDB() refer to the same *dbx.TX instance.
|
||||
func (app *BaseApp) NonconcurrentDB() dbx.Builder {
|
||||
return app.nonconcurrentDB
|
||||
}
|
||||
|
||||
// AuxDB returns the default app auxiliary db instance (pb_data/auxiliary.db).
|
||||
// AuxDB returns the app auxiliary.db builder instance.
|
||||
//
|
||||
// To minimize SQLITE_BUSY errors, it automatically routes the
|
||||
// SELECT queries to the underlying concurrent db pool and everything
|
||||
// else to the nonconcurrent one.
|
||||
//
|
||||
// For more finer control over the used connections pools you can
|
||||
// call directly AuxConcurrentDB() or AuxNonconcurrentDB().
|
||||
func (app *BaseApp) AuxDB() dbx.Builder {
|
||||
// transactional or both are nil
|
||||
if app.auxConcurrentDB == app.auxNonconcurrentDB {
|
||||
return app.auxConcurrentDB
|
||||
}
|
||||
|
||||
return &dualDBBuilder{
|
||||
concurrentDB: app.auxConcurrentDB,
|
||||
nonconcurrentDB: app.auxNonconcurrentDB,
|
||||
}
|
||||
}
|
||||
|
||||
// AuxConcurrentDB returns the concurrent app auxiliary.db builder instance.
|
||||
//
|
||||
// This method is used mainly internally for executing db read
|
||||
// operations in a concurrent/non-blocking manner.
|
||||
//
|
||||
// Most users should use simply AuxDB() as it will automatically
|
||||
// route the query execution to AuxConcurrentDB() or AuxNonconcurrentDB().
|
||||
//
|
||||
// In a transaction the AuxConcurrentDB() and AuxNonconcurrentDB() refer to the same *dbx.TX instance.
|
||||
func (app *BaseApp) AuxConcurrentDB() dbx.Builder {
|
||||
return app.auxConcurrentDB
|
||||
}
|
||||
|
||||
// AuxNonconcurrentDB returns the nonconcurrent app auxiliary db instance (pb_data/auxiliary.db).
|
||||
// AuxNonconcurrentDB returns the nonconcurrent app auxiliary.db builder instance.
|
||||
//
|
||||
// The returned db instance is limited only to a single open connection,
|
||||
// meaning that it can process only 1 db operation at a time (other operations will be queued up).
|
||||
// meaning that it can process only 1 db operation at a time (other queries queue up).
|
||||
//
|
||||
// This method is used mainly internally and in the tests to execute write
|
||||
// (save/delete) db operations as it helps with minimizing the SQLITE_BUSY errors.
|
||||
//
|
||||
// For the majority of cases you would want to use the regular DB() method
|
||||
// since it allows concurrent db read operations.
|
||||
// Most users should use simply AuxDB() as it will automatically
|
||||
// route the query execution to AuxConcurrentDB() or AuxNonconcurrentDB().
|
||||
//
|
||||
// In a transaction the AuxNonconcurrentDB() and AuxNonconcurrentDB() refer to the same *dbx.TX instance.
|
||||
// In a transaction the AuxConcurrentDB() and AuxNonconcurrentDB() refer to the same *dbx.TX instance.
|
||||
func (app *BaseApp) AuxNonconcurrentDB() dbx.Builder {
|
||||
return app.auxNonconcurrentDB
|
||||
}
|
||||
@@ -1147,10 +1211,10 @@ var sqlLogReplacements = []struct {
|
||||
}{
|
||||
{regexp.MustCompile(`\[\[([^\[\]\{\}\.]+)\.([^\[\]\{\}\.]+)\]\]`), "`$1`.`$2`"},
|
||||
{regexp.MustCompile(`\{\{([^\[\]\{\}\.]+)\.([^\[\]\{\}\.]+)\}\}`), "`$1`.`$2`"},
|
||||
{regexp.MustCompile(`([^'"])\{\{`), "$1`"},
|
||||
{regexp.MustCompile(`\}\}([^'"])`), "`$1"},
|
||||
{regexp.MustCompile(`([^'"])\[\[`), "$1`"},
|
||||
{regexp.MustCompile(`\]\]([^'"])`), "`$1"},
|
||||
{regexp.MustCompile(`([^'"])?\{\{`), "$1`"},
|
||||
{regexp.MustCompile(`\}\}([^'"])?`), "`$1"},
|
||||
{regexp.MustCompile(`([^'"])?\[\[`), "$1`"},
|
||||
{regexp.MustCompile(`\]\]([^'"])?`), "`$1"},
|
||||
{regexp.MustCompile(`<nil>`), "NULL"},
|
||||
}
|
||||
|
||||
@@ -1301,7 +1365,7 @@ func (app *BaseApp) registerBaseHooks() {
|
||||
app.Logger().Warn("Failed to run periodic PRAGMA wal_checkpoint for the auxiliary DB", slog.String("error", execErr.Error()))
|
||||
}
|
||||
|
||||
_, execErr = app.DB().NewQuery("PRAGMA optimize").Execute()
|
||||
_, execErr = app.ConcurrentDB().NewQuery("PRAGMA optimize").Execute()
|
||||
if execErr != nil {
|
||||
app.Logger().Warn("Failed to run periodic PRAGMA optimize", slog.String("error", execErr.Error()))
|
||||
}
|
||||
|
||||
+1
-1
@@ -190,7 +190,7 @@ func (app *BaseApp) RestoreBackup(ctx context.Context, name string) error {
|
||||
|
||||
// extract the zip
|
||||
if e.App.Settings().Backups.S3.Enabled {
|
||||
br, err := fsys.GetFile(name)
|
||||
br, err := fsys.GetReader(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+185
-11
@@ -5,6 +5,7 @@ import (
|
||||
"database/sql"
|
||||
"log/slog"
|
||||
"os"
|
||||
"slices"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -99,9 +100,11 @@ func TestBaseAppBootstrap(t *testing.T) {
|
||||
}
|
||||
|
||||
nilChecksBeforeReset := []nilCheck{
|
||||
{"[before] concurrentDB", app.DB(), false},
|
||||
{"[before] db", app.DB(), false},
|
||||
{"[before] concurrentDB", app.ConcurrentDB(), false},
|
||||
{"[before] nonconcurrentDB", app.NonconcurrentDB(), false},
|
||||
{"[before] auxConcurrentDB", app.AuxDB(), false},
|
||||
{"[before] auxDB", app.AuxDB(), false},
|
||||
{"[before] auxConcurrentDB", app.AuxConcurrentDB(), false},
|
||||
{"[before] auxNonconcurrentDB", app.AuxNonconcurrentDB(), false},
|
||||
{"[before] settings", app.Settings(), false},
|
||||
{"[before] logger", app.Logger(), false},
|
||||
@@ -116,9 +119,11 @@ func TestBaseAppBootstrap(t *testing.T) {
|
||||
}
|
||||
|
||||
nilChecksAfterReset := []nilCheck{
|
||||
{"[after] concurrentDB", app.DB(), true},
|
||||
{"[after] db", app.DB(), true},
|
||||
{"[after] concurrentDB", app.ConcurrentDB(), true},
|
||||
{"[after] nonconcurrentDB", app.NonconcurrentDB(), true},
|
||||
{"[after] auxConcurrentDB", app.AuxDB(), true},
|
||||
{"[after] auxDB", app.AuxDB(), true},
|
||||
{"[after] auxConcurrentDB", app.AuxConcurrentDB(), true},
|
||||
{"[after] auxNonconcurrentDB", app.AuxNonconcurrentDB(), true},
|
||||
{"[after] settings", app.Settings(), false},
|
||||
{"[after] logger", app.Logger(), false},
|
||||
@@ -128,7 +133,7 @@ func TestBaseAppBootstrap(t *testing.T) {
|
||||
runNilChecks(nilChecksAfterReset)
|
||||
}
|
||||
|
||||
func TestNewBaseAppIsTransactional(t *testing.T) {
|
||||
func TestNewBaseAppTx(t *testing.T) {
|
||||
const testDataDir = "./pb_base_app_test_data_dir/"
|
||||
defer os.RemoveAll(testDataDir)
|
||||
|
||||
@@ -141,17 +146,34 @@ func TestNewBaseAppIsTransactional(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if app.IsTransactional() {
|
||||
t.Fatalf("Didn't expect the app to be transactional")
|
||||
mustNotHaveTx := func(app core.App) {
|
||||
if app.IsTransactional() {
|
||||
t.Fatalf("Didn't expect the app to be transactional")
|
||||
}
|
||||
|
||||
if app.TxInfo() != nil {
|
||||
t.Fatalf("Didn't expect the app.txInfo to be loaded")
|
||||
}
|
||||
}
|
||||
|
||||
app.RunInTransaction(func(txApp core.App) error {
|
||||
if !txApp.IsTransactional() {
|
||||
mustHaveTx := func(app core.App) {
|
||||
if !app.IsTransactional() {
|
||||
t.Fatalf("Expected the app to be transactional")
|
||||
}
|
||||
|
||||
if app.TxInfo() == nil {
|
||||
t.Fatalf("Expected the app.txInfo to be loaded")
|
||||
}
|
||||
}
|
||||
|
||||
mustNotHaveTx(app)
|
||||
|
||||
app.RunInTransaction(func(txApp core.App) error {
|
||||
mustHaveTx(txApp)
|
||||
return nil
|
||||
})
|
||||
|
||||
mustNotHaveTx(app)
|
||||
}
|
||||
|
||||
func TestBaseAppNewMailClient(t *testing.T) {
|
||||
@@ -354,8 +376,8 @@ func TestBaseAppRefreshSettingsLoggerMinLevelEnabled(t *testing.T) {
|
||||
}
|
||||
|
||||
// silence query logs
|
||||
app.DB().(*dbx.DB).ExecLogFunc = func(ctx context.Context, t time.Duration, sql string, result sql.Result, err error) {}
|
||||
app.DB().(*dbx.DB).QueryLogFunc = func(ctx context.Context, t time.Duration, sql string, rows *sql.Rows, err error) {}
|
||||
app.ConcurrentDB().(*dbx.DB).ExecLogFunc = func(ctx context.Context, t time.Duration, sql string, result sql.Result, err error) {}
|
||||
app.ConcurrentDB().(*dbx.DB).QueryLogFunc = func(ctx context.Context, t time.Duration, sql string, rows *sql.Rows, err error) {}
|
||||
app.NonconcurrentDB().(*dbx.DB).ExecLogFunc = func(ctx context.Context, t time.Duration, sql string, result sql.Result, err error) {}
|
||||
app.NonconcurrentDB().(*dbx.DB).QueryLogFunc = func(ctx context.Context, t time.Duration, sql string, rows *sql.Rows, err error) {}
|
||||
|
||||
@@ -378,3 +400,155 @@ func TestBaseAppRefreshSettingsLoggerMinLevelEnabled(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBaseAppDBDualBuilder(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
app, _ := tests.NewTestApp()
|
||||
defer app.Cleanup()
|
||||
|
||||
concurrentQueries := []string{}
|
||||
nonconcurrentQueries := []string{}
|
||||
app.ConcurrentDB().(*dbx.DB).QueryLogFunc = func(ctx context.Context, t time.Duration, sql string, rows *sql.Rows, err error) {
|
||||
concurrentQueries = append(concurrentQueries, sql)
|
||||
}
|
||||
app.ConcurrentDB().(*dbx.DB).ExecLogFunc = func(ctx context.Context, t time.Duration, sql string, result sql.Result, err error) {
|
||||
concurrentQueries = append(concurrentQueries, sql)
|
||||
}
|
||||
app.NonconcurrentDB().(*dbx.DB).QueryLogFunc = func(ctx context.Context, t time.Duration, sql string, rows *sql.Rows, err error) {
|
||||
nonconcurrentQueries = append(nonconcurrentQueries, sql)
|
||||
}
|
||||
app.NonconcurrentDB().(*dbx.DB).ExecLogFunc = func(ctx context.Context, t time.Duration, sql string, result sql.Result, err error) {
|
||||
nonconcurrentQueries = append(nonconcurrentQueries, sql)
|
||||
}
|
||||
|
||||
type testQuery struct {
|
||||
query string
|
||||
isConcurrent bool
|
||||
}
|
||||
|
||||
regularTests := []testQuery{
|
||||
{" \n sEleCt 1", true},
|
||||
{"With abc(x) AS (select 2) SELECT x FROM abc", true},
|
||||
{"create table t1(x int)", false},
|
||||
{"insert into t1(x) values(1)", false},
|
||||
{"update t1 set x = 2", false},
|
||||
{"delete from t1", false},
|
||||
}
|
||||
|
||||
txTests := []testQuery{
|
||||
{"select 3", false},
|
||||
{" \n WITH abc(x) AS (select 4) SELECT x FROM abc", false},
|
||||
{"create table t2(x int)", false},
|
||||
{"insert into t2(x) values(1)", false},
|
||||
{"update t2 set x = 2", false},
|
||||
{"delete from t2", false},
|
||||
}
|
||||
|
||||
for _, item := range regularTests {
|
||||
_, err := app.DB().NewQuery(item.query).Execute()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to execute query %q error: %v", item.query, err)
|
||||
}
|
||||
}
|
||||
|
||||
app.RunInTransaction(func(txApp core.App) error {
|
||||
for _, item := range txTests {
|
||||
_, err := txApp.DB().NewQuery(item.query).Execute()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to execute query %q error: %v", item.query, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
allTests := append(regularTests, txTests...)
|
||||
for _, item := range allTests {
|
||||
if item.isConcurrent {
|
||||
if !slices.Contains(concurrentQueries, item.query) {
|
||||
t.Fatalf("Expected concurrent query\n%q\ngot\nconcurrent:%v\nnonconcurrent:%v", item.query, concurrentQueries, nonconcurrentQueries)
|
||||
}
|
||||
} else {
|
||||
if !slices.Contains(nonconcurrentQueries, item.query) {
|
||||
t.Fatalf("Expected nonconcurrent query\n%q\ngot\nconcurrent:%v\nnonconcurrent:%v", item.query, concurrentQueries, nonconcurrentQueries)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBaseAppAuxDBDualBuilder(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
app, _ := tests.NewTestApp()
|
||||
defer app.Cleanup()
|
||||
|
||||
concurrentQueries := []string{}
|
||||
nonconcurrentQueries := []string{}
|
||||
app.AuxConcurrentDB().(*dbx.DB).QueryLogFunc = func(ctx context.Context, t time.Duration, sql string, rows *sql.Rows, err error) {
|
||||
concurrentQueries = append(concurrentQueries, sql)
|
||||
}
|
||||
app.AuxConcurrentDB().(*dbx.DB).ExecLogFunc = func(ctx context.Context, t time.Duration, sql string, result sql.Result, err error) {
|
||||
concurrentQueries = append(concurrentQueries, sql)
|
||||
}
|
||||
app.AuxNonconcurrentDB().(*dbx.DB).QueryLogFunc = func(ctx context.Context, t time.Duration, sql string, rows *sql.Rows, err error) {
|
||||
nonconcurrentQueries = append(nonconcurrentQueries, sql)
|
||||
}
|
||||
app.AuxNonconcurrentDB().(*dbx.DB).ExecLogFunc = func(ctx context.Context, t time.Duration, sql string, result sql.Result, err error) {
|
||||
nonconcurrentQueries = append(nonconcurrentQueries, sql)
|
||||
}
|
||||
|
||||
type testQuery struct {
|
||||
query string
|
||||
isConcurrent bool
|
||||
}
|
||||
|
||||
regularTests := []testQuery{
|
||||
{" \n sEleCt 1", true},
|
||||
{"With abc(x) AS (select 2) SELECT x FROM abc", true},
|
||||
{"create table t1(x int)", false},
|
||||
{"insert into t1(x) values(1)", false},
|
||||
{"update t1 set x = 2", false},
|
||||
{"delete from t1", false},
|
||||
}
|
||||
|
||||
txTests := []testQuery{
|
||||
{"select 3", false},
|
||||
{" \n WITH abc(x) AS (select 4) SELECT x FROM abc", false},
|
||||
{"create table t2(x int)", false},
|
||||
{"insert into t2(x) values(1)", false},
|
||||
{"update t2 set x = 2", false},
|
||||
{"delete from t2", false},
|
||||
}
|
||||
|
||||
for _, item := range regularTests {
|
||||
_, err := app.AuxDB().NewQuery(item.query).Execute()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to execute query %q error: %v", item.query, err)
|
||||
}
|
||||
}
|
||||
|
||||
app.AuxRunInTransaction(func(txApp core.App) error {
|
||||
for _, item := range txTests {
|
||||
_, err := txApp.AuxDB().NewQuery(item.query).Execute()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to execute query %q error: %v", item.query, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
allTests := append(regularTests, txTests...)
|
||||
for _, item := range allTests {
|
||||
if item.isConcurrent {
|
||||
if !slices.Contains(concurrentQueries, item.query) {
|
||||
t.Fatalf("Expected concurrent query\n%q\ngot\nconcurrent:%v\nnonconcurrent:%v", item.query, concurrentQueries, nonconcurrentQueries)
|
||||
}
|
||||
} else {
|
||||
if !slices.Contains(nonconcurrentQueries, item.query) {
|
||||
t.Fatalf("Expected nonconcurrent query\n%q\ngot\nconcurrent:%v\nnonconcurrent:%v", item.query, concurrentQueries, nonconcurrentQueries)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1623,7 +1623,7 @@ func TestCollectionSaveViewWrapping(t *testing.T) {
|
||||
|
||||
var sql string
|
||||
|
||||
rowErr := app.DB().NewQuery("SELECT sql FROM sqlite_master WHERE type='view' AND name={:name}").
|
||||
rowErr := app.ConcurrentDB().NewQuery("SELECT sql FROM sqlite_master WHERE type='view' AND name={:name}").
|
||||
Bind(dbx.Params{"name": viewName}).
|
||||
Row(&sql)
|
||||
if rowErr != nil {
|
||||
|
||||
@@ -38,7 +38,7 @@ func (app *BaseApp) FindAllCollections(collectionTypes ...string) ([]*Collection
|
||||
q.AndWhere(dbx.In("type", list.ToInterfaceSlice(types)...))
|
||||
}
|
||||
|
||||
err := q.OrderBy("created ASC").All(&collections)
|
||||
err := q.OrderBy("rowid ASC").All(&collections)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ func TestFindCachedCollectionByNameOrId(t *testing.T) {
|
||||
defer app.Cleanup()
|
||||
|
||||
totalQueries := 0
|
||||
app.DB().(*dbx.DB).QueryLogFunc = func(ctx context.Context, t time.Duration, sql string, rows *sql.Rows, err error) {
|
||||
app.ConcurrentDB().(*dbx.DB).QueryLogFunc = func(ctx context.Context, t time.Duration, sql string, rows *sql.Rows, err error) {
|
||||
totalQueries++
|
||||
}
|
||||
|
||||
@@ -272,7 +272,7 @@ func TestFindCachedCollectionReferences(t *testing.T) {
|
||||
}
|
||||
|
||||
totalQueries := 0
|
||||
app.DB().(*dbx.DB).QueryLogFunc = func(ctx context.Context, t time.Duration, sql string, rows *sql.Rows, err error) {
|
||||
app.ConcurrentDB().(*dbx.DB).QueryLogFunc = func(ctx context.Context, t time.Duration, sql string, rows *sql.Rows, err error) {
|
||||
totalQueries++
|
||||
}
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@ func (app *BaseApp) SyncRecordTableSchema(newCollection *Collection, oldCollecti
|
||||
|
||||
// run optimize per the SQLite recommendations
|
||||
// (https://www.sqlite.org/pragma.html#pragma_optimize)
|
||||
_, optimizeErr := app.DB().NewQuery("PRAGMA optimize").Execute()
|
||||
_, optimizeErr := app.ConcurrentDB().NewQuery("PRAGMA optimize").Execute()
|
||||
if optimizeErr != nil {
|
||||
app.Logger().Warn("Failed to run PRAGMA optimize after record table sync", slog.String("error", optimizeErr.Error()))
|
||||
}
|
||||
@@ -310,7 +310,8 @@ func dropCollectionIndexes(app App, collection *Collection) error {
|
||||
continue
|
||||
}
|
||||
|
||||
if _, err := app.DB().NewQuery(fmt.Sprintf("DROP INDEX IF EXISTS [[%s]]", parsed.IndexName)).Execute(); err != nil {
|
||||
_, err := txApp.DB().NewQuery(fmt.Sprintf("DROP INDEX IF EXISTS [[%s]]", parsed.IndexName)).Execute()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ func (validator *collectionValidator) run() error {
|
||||
validator.original.IsNew(),
|
||||
validation.Length(1, 100),
|
||||
validation.Match(DefaultIdRegex),
|
||||
validation.By(validators.UniqueId(validator.app.DB(), validator.new.TableName())),
|
||||
validation.By(validators.UniqueId(validator.app.ConcurrentDB(), validator.new.TableName())),
|
||||
).Else(
|
||||
validation.By(validators.Equal(validator.original.Id)),
|
||||
),
|
||||
@@ -558,7 +558,7 @@ func (cv *collectionValidator) checkIndexes(value any) error {
|
||||
|
||||
// ensure that the index name is not used in another collection
|
||||
var usedTblName string
|
||||
_ = cv.app.DB().Select("tbl_name").
|
||||
_ = cv.app.ConcurrentDB().Select("tbl_name").
|
||||
From("sqlite_master").
|
||||
AndWhere(dbx.HashExp{"type": "index"}).
|
||||
AndWhere(dbx.NewExp("LOWER([[tbl_name]])!=LOWER({:oldName})", dbx.Params{"oldName": cv.original.Name})).
|
||||
|
||||
+8
-8
@@ -62,16 +62,16 @@ func crc32Checksum(str string) string {
|
||||
return strconv.FormatInt(int64(crc32.ChecksumIEEE([]byte(str))), 10)
|
||||
}
|
||||
|
||||
// ModelQuery creates a new preconfigured select app.DB() query with preset
|
||||
// ModelQuery creates a new preconfigured select data.db query with preset
|
||||
// SELECT, FROM and other common fields based on the provided model.
|
||||
func (app *BaseApp) ModelQuery(m Model) *dbx.SelectQuery {
|
||||
return app.modelQuery(app.DB(), m)
|
||||
return app.modelQuery(app.ConcurrentDB(), m)
|
||||
}
|
||||
|
||||
// AuxModelQuery creates a new preconfigured select app.AuxDB() query with preset
|
||||
// AuxModelQuery creates a new preconfigured select auxiliary.db query with preset
|
||||
// SELECT, FROM and other common fields based on the provided model.
|
||||
func (app *BaseApp) AuxModelQuery(m Model) *dbx.SelectQuery {
|
||||
return app.modelQuery(app.AuxDB(), m)
|
||||
return app.modelQuery(app.AuxConcurrentDB(), m)
|
||||
}
|
||||
|
||||
func (app *BaseApp) modelQuery(db dbx.Builder, m Model) *dbx.SelectQuery {
|
||||
@@ -151,7 +151,7 @@ func (app *BaseApp) delete(ctx context.Context, model Model, isForAuxDB bool) er
|
||||
|
||||
if app.txInfo != nil {
|
||||
// execute later after the transaction has completed
|
||||
app.txInfo.onAfterFunc(func(txErr error) error {
|
||||
app.txInfo.OnComplete(func(txErr error) error {
|
||||
if app.txInfo != nil && app.txInfo.parent != nil {
|
||||
event.App = app.txInfo.parent
|
||||
}
|
||||
@@ -342,7 +342,7 @@ func (app *BaseApp) create(ctx context.Context, model Model, withValidations boo
|
||||
|
||||
if app.txInfo != nil {
|
||||
// execute later after the transaction has completed
|
||||
app.txInfo.onAfterFunc(func(txErr error) error {
|
||||
app.txInfo.OnComplete(func(txErr error) error {
|
||||
if app.txInfo != nil && app.txInfo.parent != nil {
|
||||
event.App = app.txInfo.parent
|
||||
}
|
||||
@@ -426,7 +426,7 @@ func (app *BaseApp) update(ctx context.Context, model Model, withValidations boo
|
||||
|
||||
if app.txInfo != nil {
|
||||
// execute later after the transaction has completed
|
||||
app.txInfo.onAfterFunc(func(txErr error) error {
|
||||
app.txInfo.OnComplete(func(txErr error) error {
|
||||
if app.txInfo != nil && app.txInfo.parent != nil {
|
||||
event.App = app.txInfo.parent
|
||||
}
|
||||
@@ -484,7 +484,7 @@ func validateRecordId(app App, collectionNameOrId string) validation.RuleFunc {
|
||||
|
||||
var exists int
|
||||
|
||||
rowErr := app.DB().Select("(1)").
|
||||
rowErr := app.ConcurrentDB().Select("(1)").
|
||||
From(collection.Name).
|
||||
AndWhere(dbx.HashExp{"id": id}).
|
||||
Limit(1).
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
)
|
||||
|
||||
var _ dbx.Builder = (*dualDBBuilder)(nil)
|
||||
|
||||
// note: expects both builder to use the same driver
|
||||
type dualDBBuilder struct {
|
||||
concurrentDB dbx.Builder
|
||||
nonconcurrentDB dbx.Builder
|
||||
}
|
||||
|
||||
// Select implements the [dbx.Builder.Select] interface method.
|
||||
func (b *dualDBBuilder) Select(cols ...string) *dbx.SelectQuery {
|
||||
return b.concurrentDB.Select(cols...)
|
||||
}
|
||||
|
||||
// Model implements the [dbx.Builder.Model] interface method.
|
||||
func (b *dualDBBuilder) Model(data interface{}) *dbx.ModelQuery {
|
||||
return b.nonconcurrentDB.Model(data)
|
||||
}
|
||||
|
||||
// GeneratePlaceholder implements the [dbx.Builder.GeneratePlaceholder] interface method.
|
||||
func (b *dualDBBuilder) GeneratePlaceholder(i int) string {
|
||||
return b.concurrentDB.GeneratePlaceholder(i)
|
||||
}
|
||||
|
||||
// Quote implements the [dbx.Builder.Quote] interface method.
|
||||
func (b *dualDBBuilder) Quote(str string) string {
|
||||
return b.concurrentDB.Quote(str)
|
||||
}
|
||||
|
||||
// QuoteSimpleTableName implements the [dbx.Builder.QuoteSimpleTableName] interface method.
|
||||
func (b *dualDBBuilder) QuoteSimpleTableName(table string) string {
|
||||
return b.concurrentDB.QuoteSimpleTableName(table)
|
||||
}
|
||||
|
||||
// QuoteSimpleColumnName implements the [dbx.Builder.QuoteSimpleColumnName] interface method.
|
||||
func (b *dualDBBuilder) QuoteSimpleColumnName(col string) string {
|
||||
return b.concurrentDB.QuoteSimpleColumnName(col)
|
||||
}
|
||||
|
||||
// QueryBuilder implements the [dbx.Builder.QueryBuilder] interface method.
|
||||
func (b *dualDBBuilder) QueryBuilder() dbx.QueryBuilder {
|
||||
return b.concurrentDB.QueryBuilder()
|
||||
}
|
||||
|
||||
// Insert implements the [dbx.Builder.Insert] interface method.
|
||||
func (b *dualDBBuilder) Insert(table string, cols dbx.Params) *dbx.Query {
|
||||
return b.nonconcurrentDB.Insert(table, cols)
|
||||
}
|
||||
|
||||
// Upsert implements the [dbx.Builder.Upsert] interface method.
|
||||
func (b *dualDBBuilder) Upsert(table string, cols dbx.Params, constraints ...string) *dbx.Query {
|
||||
return b.nonconcurrentDB.Upsert(table, cols, constraints...)
|
||||
}
|
||||
|
||||
// Update implements the [dbx.Builder.Update] interface method.
|
||||
func (b *dualDBBuilder) Update(table string, cols dbx.Params, where dbx.Expression) *dbx.Query {
|
||||
return b.nonconcurrentDB.Update(table, cols, where)
|
||||
}
|
||||
|
||||
// Delete implements the [dbx.Builder.Delete] interface method.
|
||||
func (b *dualDBBuilder) Delete(table string, where dbx.Expression) *dbx.Query {
|
||||
return b.nonconcurrentDB.Delete(table, where)
|
||||
}
|
||||
|
||||
// CreateTable implements the [dbx.Builder.CreateTable] interface method.
|
||||
func (b *dualDBBuilder) CreateTable(table string, cols map[string]string, options ...string) *dbx.Query {
|
||||
return b.nonconcurrentDB.CreateTable(table, cols, options...)
|
||||
}
|
||||
|
||||
// RenameTable implements the [dbx.Builder.RenameTable] interface method.
|
||||
func (b *dualDBBuilder) RenameTable(oldName, newName string) *dbx.Query {
|
||||
return b.nonconcurrentDB.RenameTable(oldName, newName)
|
||||
}
|
||||
|
||||
// DropTable implements the [dbx.Builder.DropTable] interface method.
|
||||
func (b *dualDBBuilder) DropTable(table string) *dbx.Query {
|
||||
return b.nonconcurrentDB.DropTable(table)
|
||||
}
|
||||
|
||||
// TruncateTable implements the [dbx.Builder.TruncateTable] interface method.
|
||||
func (b *dualDBBuilder) TruncateTable(table string) *dbx.Query {
|
||||
return b.nonconcurrentDB.TruncateTable(table)
|
||||
}
|
||||
|
||||
// AddColumn implements the [dbx.Builder.AddColumn] interface method.
|
||||
func (b *dualDBBuilder) AddColumn(table, col, typ string) *dbx.Query {
|
||||
return b.nonconcurrentDB.AddColumn(table, col, typ)
|
||||
}
|
||||
|
||||
// DropColumn implements the [dbx.Builder.DropColumn] interface method.
|
||||
func (b *dualDBBuilder) DropColumn(table, col string) *dbx.Query {
|
||||
return b.nonconcurrentDB.DropColumn(table, col)
|
||||
}
|
||||
|
||||
// RenameColumn implements the [dbx.Builder.RenameColumn] interface method.
|
||||
func (b *dualDBBuilder) RenameColumn(table, oldName, newName string) *dbx.Query {
|
||||
return b.nonconcurrentDB.RenameColumn(table, oldName, newName)
|
||||
}
|
||||
|
||||
// AlterColumn implements the [dbx.Builder.AlterColumn] interface method.
|
||||
func (b *dualDBBuilder) AlterColumn(table, col, typ string) *dbx.Query {
|
||||
return b.nonconcurrentDB.AlterColumn(table, col, typ)
|
||||
}
|
||||
|
||||
// AddPrimaryKey implements the [dbx.Builder.AddPrimaryKey] interface method.
|
||||
func (b *dualDBBuilder) AddPrimaryKey(table, name string, cols ...string) *dbx.Query {
|
||||
return b.nonconcurrentDB.AddPrimaryKey(table, name, cols...)
|
||||
}
|
||||
|
||||
// DropPrimaryKey implements the [dbx.Builder.DropPrimaryKey] interface method.
|
||||
func (b *dualDBBuilder) DropPrimaryKey(table, name string) *dbx.Query {
|
||||
return b.nonconcurrentDB.DropPrimaryKey(table, name)
|
||||
}
|
||||
|
||||
// AddForeignKey implements the [dbx.Builder.AddForeignKey] interface method.
|
||||
func (b *dualDBBuilder) AddForeignKey(table, name string, cols, refCols []string, refTable string, options ...string) *dbx.Query {
|
||||
return b.nonconcurrentDB.AddForeignKey(table, name, cols, refCols, refTable, options...)
|
||||
}
|
||||
|
||||
// DropForeignKey implements the [dbx.Builder.DropForeignKey] interface method.
|
||||
func (b *dualDBBuilder) DropForeignKey(table, name string) *dbx.Query {
|
||||
return b.nonconcurrentDB.DropForeignKey(table, name)
|
||||
}
|
||||
|
||||
// CreateIndex implements the [dbx.Builder.CreateIndex] interface method.
|
||||
func (b *dualDBBuilder) CreateIndex(table, name string, cols ...string) *dbx.Query {
|
||||
return b.nonconcurrentDB.CreateIndex(table, name, cols...)
|
||||
}
|
||||
|
||||
// CreateUniqueIndex implements the [dbx.Builder.CreateUniqueIndex] interface method.
|
||||
func (b *dualDBBuilder) CreateUniqueIndex(table, name string, cols ...string) *dbx.Query {
|
||||
return b.nonconcurrentDB.CreateUniqueIndex(table, name, cols...)
|
||||
}
|
||||
|
||||
// DropIndex implements the [dbx.Builder.DropIndex] interface method.
|
||||
func (b *dualDBBuilder) DropIndex(table, name string) *dbx.Query {
|
||||
return b.nonconcurrentDB.DropIndex(table, name)
|
||||
}
|
||||
|
||||
// NewQuery implements the [dbx.Builder.NewQuery] interface method by
|
||||
// routing the SELECT queries to the concurrent builder instance.
|
||||
func (b *dualDBBuilder) NewQuery(str string) *dbx.Query {
|
||||
// note: technically INSERT/UPDATE/DELETE could also have CTE but since
|
||||
// it is rare for now this scase is ignored to avoid unnecessary complicating the checks
|
||||
trimmed := trimLeftSpaces(str)
|
||||
if hasPrefixFold(trimmed, "SELECT") || hasPrefixFold(trimmed, "WITH") {
|
||||
return b.concurrentDB.NewQuery(str)
|
||||
}
|
||||
|
||||
return b.nonconcurrentDB.NewQuery(str)
|
||||
}
|
||||
|
||||
var asciiSpace = [256]uint8{'\t': 1, '\n': 1, '\v': 1, '\f': 1, '\r': 1, ' ': 1}
|
||||
|
||||
// note: similar to strings.Space() but without the right trim because it is not needed in our case
|
||||
func trimLeftSpaces(str string) string {
|
||||
start := 0
|
||||
for ; start < len(str); start++ {
|
||||
c := str[start]
|
||||
if c >= utf8.RuneSelf {
|
||||
return strings.TrimLeftFunc(str[start:], unicode.IsSpace)
|
||||
}
|
||||
if asciiSpace[c] == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return str[start:]
|
||||
}
|
||||
|
||||
// note: the prefix is expected to be ASCII
|
||||
func hasPrefixFold(str, prefix string) bool {
|
||||
if len(str) < len(prefix) {
|
||||
return false
|
||||
}
|
||||
|
||||
return strings.EqualFold(str[:len(prefix)], prefix)
|
||||
}
|
||||
+12
-14
@@ -11,7 +11,7 @@ import (
|
||||
func (app *BaseApp) TableColumns(tableName string) ([]string, error) {
|
||||
columns := []string{}
|
||||
|
||||
err := app.DB().NewQuery("SELECT name FROM PRAGMA_TABLE_INFO({:tableName})").
|
||||
err := app.ConcurrentDB().NewQuery("SELECT name FROM PRAGMA_TABLE_INFO({:tableName})").
|
||||
Bind(dbx.Params{"tableName": tableName}).
|
||||
Column(&columns)
|
||||
|
||||
@@ -34,7 +34,7 @@ type TableInfoRow struct {
|
||||
func (app *BaseApp) TableInfo(tableName string) ([]*TableInfoRow, error) {
|
||||
info := []*TableInfoRow{}
|
||||
|
||||
err := app.DB().NewQuery("SELECT * FROM PRAGMA_TABLE_INFO({:tableName})").
|
||||
err := app.ConcurrentDB().NewQuery("SELECT * FROM PRAGMA_TABLE_INFO({:tableName})").
|
||||
Bind(dbx.Params{"tableName": tableName}).
|
||||
All(&info)
|
||||
if err != nil {
|
||||
@@ -59,7 +59,7 @@ func (app *BaseApp) TableIndexes(tableName string) (map[string]string, error) {
|
||||
Sql string
|
||||
}{}
|
||||
|
||||
err := app.DB().Select("name", "sql").
|
||||
err := app.ConcurrentDB().Select("name", "sql").
|
||||
From("sqlite_master").
|
||||
AndWhere(dbx.NewExp("sql is not null")).
|
||||
AndWhere(dbx.HashExp{
|
||||
@@ -87,7 +87,7 @@ func (app *BaseApp) TableIndexes(tableName string) (map[string]string, error) {
|
||||
// NB! Be aware that this method is vulnerable to SQL injection and the
|
||||
// "tableName" argument must come only from trusted input!
|
||||
func (app *BaseApp) DeleteTable(tableName string) error {
|
||||
_, err := app.DB().NewQuery(fmt.Sprintf(
|
||||
_, err := app.NonconcurrentDB().NewQuery(fmt.Sprintf(
|
||||
"DROP TABLE IF EXISTS {{%s}}",
|
||||
tableName,
|
||||
)).Execute()
|
||||
@@ -96,15 +96,15 @@ func (app *BaseApp) DeleteTable(tableName string) error {
|
||||
}
|
||||
|
||||
// HasTable checks if a table (or view) with the provided name exists (case insensitive).
|
||||
// in the current app.DB() instance.
|
||||
// in the data.db.
|
||||
func (app *BaseApp) HasTable(tableName string) bool {
|
||||
return app.hasTable(app.DB(), tableName)
|
||||
return app.hasTable(app.ConcurrentDB(), tableName)
|
||||
}
|
||||
|
||||
// AuxHasTable checks if a table (or view) with the provided name exists (case insensitive)
|
||||
// in the current app.AuxDB() instance.
|
||||
// in the auixiliary.db.
|
||||
func (app *BaseApp) AuxHasTable(tableName string) bool {
|
||||
return app.hasTable(app.AuxDB(), tableName)
|
||||
return app.hasTable(app.AuxConcurrentDB(), tableName)
|
||||
}
|
||||
|
||||
func (app *BaseApp) hasTable(db dbx.Builder, tableName string) bool {
|
||||
@@ -120,16 +120,14 @@ func (app *BaseApp) hasTable(db dbx.Builder, tableName string) bool {
|
||||
return err == nil && exists > 0
|
||||
}
|
||||
|
||||
// Vacuum executes VACUUM on the current app.DB() instance
|
||||
// in order to reclaim unused data db disk space.
|
||||
// Vacuum executes VACUUM on the data.db in order to reclaim unused data db disk space.
|
||||
func (app *BaseApp) Vacuum() error {
|
||||
return app.vacuum(app.DB())
|
||||
return app.vacuum(app.NonconcurrentDB())
|
||||
}
|
||||
|
||||
// AuxVacuum executes VACUUM on the current app.AuxDB() instance
|
||||
// in order to reclaim unused auxiliary db disk space.
|
||||
// AuxVacuum executes VACUUM on the auxiliary.db in order to reclaim unused auxiliary db disk space.
|
||||
func (app *BaseApp) AuxVacuum() error {
|
||||
return app.vacuum(app.AuxDB())
|
||||
return app.vacuum(app.AuxNonconcurrentDB())
|
||||
}
|
||||
|
||||
func (app *BaseApp) vacuum(db dbx.Builder) error {
|
||||
|
||||
@@ -202,10 +202,10 @@ func TestVacuum(t *testing.T) {
|
||||
defer app.Cleanup()
|
||||
|
||||
calledQueries := []string{}
|
||||
app.DB().(*dbx.DB).QueryLogFunc = func(ctx context.Context, t time.Duration, sql string, rows *sql.Rows, err error) {
|
||||
app.NonconcurrentDB().(*dbx.DB).QueryLogFunc = func(ctx context.Context, t time.Duration, sql string, rows *sql.Rows, err error) {
|
||||
calledQueries = append(calledQueries, sql)
|
||||
}
|
||||
app.DB().(*dbx.DB).ExecLogFunc = func(ctx context.Context, t time.Duration, sql string, result sql.Result, err error) {
|
||||
app.NonconcurrentDB().(*dbx.DB).ExecLogFunc = func(ctx context.Context, t time.Duration, sql string, result sql.Result, err error) {
|
||||
calledQueries = append(calledQueries, sql)
|
||||
}
|
||||
|
||||
@@ -229,10 +229,10 @@ func TestAuxVacuum(t *testing.T) {
|
||||
defer app.Cleanup()
|
||||
|
||||
calledQueries := []string{}
|
||||
app.AuxDB().(*dbx.DB).QueryLogFunc = func(ctx context.Context, t time.Duration, sql string, rows *sql.Rows, err error) {
|
||||
app.AuxNonconcurrentDB().(*dbx.DB).QueryLogFunc = func(ctx context.Context, t time.Duration, sql string, rows *sql.Rows, err error) {
|
||||
calledQueries = append(calledQueries, sql)
|
||||
}
|
||||
app.AuxDB().(*dbx.DB).ExecLogFunc = func(ctx context.Context, t time.Duration, sql string, result sql.Result, err error) {
|
||||
app.AuxNonconcurrentDB().(*dbx.DB).ExecLogFunc = func(ctx context.Context, t time.Duration, sql string, result sql.Result, err error) {
|
||||
calledQueries = append(calledQueries, sql)
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -38,12 +38,12 @@ func TestModelQuery(t *testing.T) {
|
||||
modelsQuery := app.ModelQuery(&core.Collection{})
|
||||
logsModelQuery := app.AuxModelQuery(&core.Collection{})
|
||||
|
||||
if app.DB() == modelsQuery.Info().Builder {
|
||||
t.Fatalf("ModelQuery() is not using app.DB()")
|
||||
if app.ConcurrentDB() == modelsQuery.Info().Builder {
|
||||
t.Fatalf("ModelQuery() is not using app.ConcurrentDB()")
|
||||
}
|
||||
|
||||
if app.AuxDB() == logsModelQuery.Info().Builder {
|
||||
t.Fatalf("AuxModelQuery() is not using app.AuxDB()")
|
||||
if app.AuxConcurrentDB() == logsModelQuery.Info().Builder {
|
||||
t.Fatalf("AuxModelQuery() is not using app.AuxConcurrentDB()")
|
||||
}
|
||||
|
||||
expectedSQL := "SELECT {{_collections}}.* FROM `_collections`"
|
||||
|
||||
+12
-5
@@ -60,7 +60,7 @@ func (app *BaseApp) createTxApp(tx *dbx.Tx, isForAuxDB bool) *BaseApp {
|
||||
clone.nonconcurrentDB = tx
|
||||
}
|
||||
|
||||
clone.txInfo = &txAppInfo{
|
||||
clone.txInfo = &TxAppInfo{
|
||||
parent: app,
|
||||
isForAuxDB: isForAuxDB,
|
||||
}
|
||||
@@ -68,22 +68,29 @@ func (app *BaseApp) createTxApp(tx *dbx.Tx, isForAuxDB bool) *BaseApp {
|
||||
return &clone
|
||||
}
|
||||
|
||||
type txAppInfo struct {
|
||||
// TxAppInfo represents an active transaction context associated to an existing app instance.
|
||||
type TxAppInfo struct {
|
||||
parent *BaseApp
|
||||
afterFuncs []func(txErr error) error
|
||||
mu sync.Mutex
|
||||
isForAuxDB bool
|
||||
}
|
||||
|
||||
func (a *txAppInfo) onAfterFunc(fn func(txErr error) error) {
|
||||
// OnComplete registers the provided callback that will be invoked
|
||||
// once the related transaction ends (either completes successfully or rollbacked with an error).
|
||||
//
|
||||
// The callback receives the transaction error (if any) as its argument.
|
||||
// Any additional errors returned by the OnComplete callbacks will be
|
||||
// joined together with txErr when returning the final transaction result.
|
||||
func (a *TxAppInfo) OnComplete(fn func(txErr error) error) {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
|
||||
a.afterFuncs = append(a.afterFuncs, fn)
|
||||
}
|
||||
|
||||
// note: can be called only once because txAppInfo is cleared
|
||||
func (a *txAppInfo) runAfterFuncs(txErr error) error {
|
||||
// note: can be called only once because TxAppInfo is cleared
|
||||
func (a *TxAppInfo) runAfterFuncs(txErr error) error {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
|
||||
|
||||
@@ -155,7 +155,7 @@ func TestFindFirstExternalAuthByExpr(t *testing.T) {
|
||||
}
|
||||
|
||||
for i, s := range scenarios {
|
||||
t.Run(fmt.Sprintf("%d_%v", i, s.expr.Build(app.DB().(*dbx.DB), dbx.Params{})), func(t *testing.T) {
|
||||
t.Run(fmt.Sprintf("%d_%v", i, s.expr.Build(app.ConcurrentDB().(*dbx.DB), dbx.Params{})), func(t *testing.T) {
|
||||
result, err := app.FindFirstExternalAuthByExpr(s.expr)
|
||||
|
||||
hasErr := err != nil
|
||||
|
||||
+1
-3
@@ -10,7 +10,6 @@ import (
|
||||
"strings"
|
||||
|
||||
validation "github.com/go-ozzo/ozzo-validation/v4"
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/core/validators"
|
||||
"github.com/pocketbase/pocketbase/tools/filesystem"
|
||||
"github.com/pocketbase/pocketbase/tools/list"
|
||||
@@ -357,8 +356,7 @@ func (f *FileField) Intercept(
|
||||
return nil
|
||||
case InterceptorActionAfterCreateError, InterceptorActionAfterUpdateError:
|
||||
// when in transaction we assume that the error was handled by afterRecordExecuteFailure
|
||||
_, insideTransaction := app.DB().(*dbx.Tx)
|
||||
if insideTransaction {
|
||||
if app.IsTransactional() {
|
||||
return actionFunc()
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -20,7 +20,7 @@ func init() {
|
||||
|
||||
const FieldTypeJSON = "json"
|
||||
|
||||
const DefaultJSONFieldMaxSize int64 = 5 << 20
|
||||
const DefaultJSONFieldMaxSize int64 = 1 << 20
|
||||
|
||||
var (
|
||||
_ Field = (*JSONField)(nil)
|
||||
@@ -53,7 +53,7 @@ type JSONField struct {
|
||||
|
||||
// MaxSize specifies the maximum size of the allowed field value (in bytes and up to 2^53-1).
|
||||
//
|
||||
// If zero, a default limit of 5MB is applied.
|
||||
// If zero, a default limit of 1MB is applied.
|
||||
MaxSize int64 `form:"maxSize" json:"maxSize"`
|
||||
|
||||
// Required will require the field value to be non-empty JSON value
|
||||
|
||||
@@ -146,7 +146,7 @@ func TestJSONFieldValidateValue(t *testing.T) {
|
||||
&core.JSONField{Name: "test"},
|
||||
func() *core.Record {
|
||||
record := core.NewRecord(collection)
|
||||
record.SetRaw("test", types.JSONRaw(`"`+strings.Repeat("a", (5<<20))+`"`))
|
||||
record.SetRaw("test", types.JSONRaw(`"`+strings.Repeat("a", (1<<20))+`"`))
|
||||
return record
|
||||
},
|
||||
true,
|
||||
|
||||
@@ -219,7 +219,7 @@ func (f *RelationField) ValidateValue(ctx context.Context, app App, record *Reco
|
||||
}
|
||||
|
||||
var total int
|
||||
_ = app.DB().
|
||||
_ = app.ConcurrentDB().
|
||||
Select("count(*)").
|
||||
From(relCollection.Name).
|
||||
AndWhere(dbx.In("id", list.ToInterfaceSlice(ids)...)).
|
||||
|
||||
+1
-1
@@ -194,7 +194,7 @@ func (f *TextField) ValidateValue(ctx context.Context, app App, record *Record)
|
||||
// (@todo eventually may get replaced in the future with a system unique constraint to avoid races or wrapping the request in a transaction)
|
||||
if f.Pattern != defaultLowercaseRecordIdPattern {
|
||||
var exists int
|
||||
err := app.DB().
|
||||
err := app.ConcurrentDB().
|
||||
Select("(1)").
|
||||
From(record.TableName()).
|
||||
Where(dbx.NewExp("id = {:id} COLLATE NOCASE", dbx.Params{"id": newVal})).
|
||||
|
||||
@@ -55,10 +55,10 @@ func TestBaseAppLoggerLevelDevPrint(t *testing.T) {
|
||||
}
|
||||
|
||||
// silence query logs
|
||||
app.DB().(*dbx.DB).ExecLogFunc = func(ctx context.Context, t time.Duration, sql string, result sql.Result, err error) {}
|
||||
app.DB().(*dbx.DB).QueryLogFunc = func(ctx context.Context, t time.Duration, sql string, rows *sql.Rows, err error) {}
|
||||
app.NonconcurrentDB().(*dbx.DB).ExecLogFunc = func(ctx context.Context, t time.Duration, sql string, result sql.Result, err error) {}
|
||||
app.NonconcurrentDB().(*dbx.DB).QueryLogFunc = func(ctx context.Context, t time.Duration, sql string, rows *sql.Rows, err error) {}
|
||||
app.concurrentDB.(*dbx.DB).ExecLogFunc = func(ctx context.Context, t time.Duration, sql string, result sql.Result, err error) {}
|
||||
app.concurrentDB.(*dbx.DB).QueryLogFunc = func(ctx context.Context, t time.Duration, sql string, rows *sql.Rows, err error) {}
|
||||
app.nonconcurrentDB.(*dbx.DB).ExecLogFunc = func(ctx context.Context, t time.Duration, sql string, result sql.Result, err error) {}
|
||||
app.nonconcurrentDB.(*dbx.DB).QueryLogFunc = func(ctx context.Context, t time.Duration, sql string, rows *sql.Rows, err error) {}
|
||||
|
||||
app.Settings().Logs.MinLevel = testLogLevel
|
||||
if err := app.Save(app.Settings()); err != nil {
|
||||
|
||||
@@ -173,7 +173,7 @@ func TestRecordFieldResolverUpdateQuery(t *testing.T) {
|
||||
"demo4",
|
||||
"self_rel_many.id ?> true", // should have join
|
||||
false,
|
||||
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN json_each(CASE WHEN json_valid([[demo4.self_rel_many]]) THEN [[demo4.self_rel_many]] ELSE json_array([[demo4.self_rel_many]]) END) `demo4_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many` ON [[demo4_self_rel_many.id]] = [[demo4_self_rel_many_je.value]] WHERE [[demo4_self_rel_many.id]] > 1",
|
||||
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN json_each(CASE WHEN iif(json_valid([[demo4.self_rel_many]]), json_type([[demo4.self_rel_many]])='array', FALSE) THEN [[demo4.self_rel_many]] ELSE json_array([[demo4.self_rel_many]]) END) `demo4_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many` ON [[demo4_self_rel_many.id]] = [[demo4_self_rel_many_je.value]] WHERE [[demo4_self_rel_many.id]] > 1",
|
||||
},
|
||||
{
|
||||
"nested single rel (self rel)",
|
||||
@@ -201,63 +201,63 @@ func TestRecordFieldResolverUpdateQuery(t *testing.T) {
|
||||
"demo4",
|
||||
"self_rel_many.self_rel_one ?> true",
|
||||
false,
|
||||
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN json_each(CASE WHEN json_valid([[demo4.self_rel_many]]) THEN [[demo4.self_rel_many]] ELSE json_array([[demo4.self_rel_many]]) END) `demo4_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many` ON [[demo4_self_rel_many.id]] = [[demo4_self_rel_many_je.value]] WHERE [[demo4_self_rel_many.self_rel_one]] > 1",
|
||||
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN json_each(CASE WHEN iif(json_valid([[demo4.self_rel_many]]), json_type([[demo4.self_rel_many]])='array', FALSE) THEN [[demo4.self_rel_many]] ELSE json_array([[demo4.self_rel_many]]) END) `demo4_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many` ON [[demo4_self_rel_many.id]] = [[demo4_self_rel_many_je.value]] WHERE [[demo4_self_rel_many.self_rel_one]] > 1",
|
||||
},
|
||||
{
|
||||
"nested incomplete relations (multi-match operator)",
|
||||
"demo4",
|
||||
"self_rel_many.self_rel_one > true",
|
||||
false,
|
||||
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN json_each(CASE WHEN json_valid([[demo4.self_rel_many]]) THEN [[demo4.self_rel_many]] ELSE json_array([[demo4.self_rel_many]]) END) `demo4_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many` ON [[demo4_self_rel_many.id]] = [[demo4_self_rel_many_je.value]] WHERE ((([[demo4_self_rel_many.self_rel_one]] > 1) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo4_self_rel_many.self_rel_one]] as [[multiMatchValue]] FROM `demo4` `__mm_demo4` LEFT JOIN json_each(CASE WHEN json_valid([[__mm_demo4.self_rel_many]]) THEN [[__mm_demo4.self_rel_many]] ELSE json_array([[__mm_demo4.self_rel_many]]) END) `__mm_demo4_self_rel_many_je` LEFT JOIN `demo4` `__mm_demo4_self_rel_many` ON [[__mm_demo4_self_rel_many.id]] = [[__mm_demo4_self_rel_many_je.value]] WHERE `__mm_demo4`.`id` = `demo4`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] > 1)))))",
|
||||
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN json_each(CASE WHEN iif(json_valid([[demo4.self_rel_many]]), json_type([[demo4.self_rel_many]])='array', FALSE) THEN [[demo4.self_rel_many]] ELSE json_array([[demo4.self_rel_many]]) END) `demo4_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many` ON [[demo4_self_rel_many.id]] = [[demo4_self_rel_many_je.value]] WHERE ((([[demo4_self_rel_many.self_rel_one]] > 1) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo4_self_rel_many.self_rel_one]] as [[multiMatchValue]] FROM `demo4` `__mm_demo4` LEFT JOIN json_each(CASE WHEN iif(json_valid([[__mm_demo4.self_rel_many]]), json_type([[__mm_demo4.self_rel_many]])='array', FALSE) THEN [[__mm_demo4.self_rel_many]] ELSE json_array([[__mm_demo4.self_rel_many]]) END) `__mm_demo4_self_rel_many_je` LEFT JOIN `demo4` `__mm_demo4_self_rel_many` ON [[__mm_demo4_self_rel_many.id]] = [[__mm_demo4_self_rel_many_je.value]] WHERE `__mm_demo4`.`id` = `demo4`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] > 1)))))",
|
||||
},
|
||||
{
|
||||
"nested complete relations (opt/any operator)",
|
||||
"demo4",
|
||||
"self_rel_many.self_rel_one.title ?> true",
|
||||
false,
|
||||
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN json_each(CASE WHEN json_valid([[demo4.self_rel_many]]) THEN [[demo4.self_rel_many]] ELSE json_array([[demo4.self_rel_many]]) END) `demo4_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many` ON [[demo4_self_rel_many.id]] = [[demo4_self_rel_many_je.value]] LEFT JOIN `demo4` `demo4_self_rel_many_self_rel_one` ON [[demo4_self_rel_many_self_rel_one.id]] = [[demo4_self_rel_many.self_rel_one]] WHERE [[demo4_self_rel_many_self_rel_one.title]] > 1",
|
||||
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN json_each(CASE WHEN iif(json_valid([[demo4.self_rel_many]]), json_type([[demo4.self_rel_many]])='array', FALSE) THEN [[demo4.self_rel_many]] ELSE json_array([[demo4.self_rel_many]]) END) `demo4_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many` ON [[demo4_self_rel_many.id]] = [[demo4_self_rel_many_je.value]] LEFT JOIN `demo4` `demo4_self_rel_many_self_rel_one` ON [[demo4_self_rel_many_self_rel_one.id]] = [[demo4_self_rel_many.self_rel_one]] WHERE [[demo4_self_rel_many_self_rel_one.title]] > 1",
|
||||
},
|
||||
{
|
||||
"nested complete relations (multi-match operator)",
|
||||
"demo4",
|
||||
"self_rel_many.self_rel_one.title > true",
|
||||
false,
|
||||
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN json_each(CASE WHEN json_valid([[demo4.self_rel_many]]) THEN [[demo4.self_rel_many]] ELSE json_array([[demo4.self_rel_many]]) END) `demo4_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many` ON [[demo4_self_rel_many.id]] = [[demo4_self_rel_many_je.value]] LEFT JOIN `demo4` `demo4_self_rel_many_self_rel_one` ON [[demo4_self_rel_many_self_rel_one.id]] = [[demo4_self_rel_many.self_rel_one]] WHERE ((([[demo4_self_rel_many_self_rel_one.title]] > 1) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo4_self_rel_many_self_rel_one.title]] as [[multiMatchValue]] FROM `demo4` `__mm_demo4` LEFT JOIN json_each(CASE WHEN json_valid([[__mm_demo4.self_rel_many]]) THEN [[__mm_demo4.self_rel_many]] ELSE json_array([[__mm_demo4.self_rel_many]]) END) `__mm_demo4_self_rel_many_je` LEFT JOIN `demo4` `__mm_demo4_self_rel_many` ON [[__mm_demo4_self_rel_many.id]] = [[__mm_demo4_self_rel_many_je.value]] LEFT JOIN `demo4` `__mm_demo4_self_rel_many_self_rel_one` ON [[__mm_demo4_self_rel_many_self_rel_one.id]] = [[__mm_demo4_self_rel_many.self_rel_one]] WHERE `__mm_demo4`.`id` = `demo4`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] > 1)))))",
|
||||
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN json_each(CASE WHEN iif(json_valid([[demo4.self_rel_many]]), json_type([[demo4.self_rel_many]])='array', FALSE) THEN [[demo4.self_rel_many]] ELSE json_array([[demo4.self_rel_many]]) END) `demo4_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many` ON [[demo4_self_rel_many.id]] = [[demo4_self_rel_many_je.value]] LEFT JOIN `demo4` `demo4_self_rel_many_self_rel_one` ON [[demo4_self_rel_many_self_rel_one.id]] = [[demo4_self_rel_many.self_rel_one]] WHERE ((([[demo4_self_rel_many_self_rel_one.title]] > 1) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo4_self_rel_many_self_rel_one.title]] as [[multiMatchValue]] FROM `demo4` `__mm_demo4` LEFT JOIN json_each(CASE WHEN iif(json_valid([[__mm_demo4.self_rel_many]]), json_type([[__mm_demo4.self_rel_many]])='array', FALSE) THEN [[__mm_demo4.self_rel_many]] ELSE json_array([[__mm_demo4.self_rel_many]]) END) `__mm_demo4_self_rel_many_je` LEFT JOIN `demo4` `__mm_demo4_self_rel_many` ON [[__mm_demo4_self_rel_many.id]] = [[__mm_demo4_self_rel_many_je.value]] LEFT JOIN `demo4` `__mm_demo4_self_rel_many_self_rel_one` ON [[__mm_demo4_self_rel_many_self_rel_one.id]] = [[__mm_demo4_self_rel_many.self_rel_one]] WHERE `__mm_demo4`.`id` = `demo4`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] > 1)))))",
|
||||
},
|
||||
{
|
||||
"repeated nested relations (opt/any operator)",
|
||||
"demo4",
|
||||
"self_rel_many.self_rel_one.self_rel_many.self_rel_one.title ?> true",
|
||||
false,
|
||||
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN json_each(CASE WHEN json_valid([[demo4.self_rel_many]]) THEN [[demo4.self_rel_many]] ELSE json_array([[demo4.self_rel_many]]) END) `demo4_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many` ON [[demo4_self_rel_many.id]] = [[demo4_self_rel_many_je.value]] LEFT JOIN `demo4` `demo4_self_rel_many_self_rel_one` ON [[demo4_self_rel_many_self_rel_one.id]] = [[demo4_self_rel_many.self_rel_one]] LEFT JOIN json_each(CASE WHEN json_valid([[demo4_self_rel_many_self_rel_one.self_rel_many]]) THEN [[demo4_self_rel_many_self_rel_one.self_rel_many]] ELSE json_array([[demo4_self_rel_many_self_rel_one.self_rel_many]]) END) `demo4_self_rel_many_self_rel_one_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many_self_rel_one_self_rel_many` ON [[demo4_self_rel_many_self_rel_one_self_rel_many.id]] = [[demo4_self_rel_many_self_rel_one_self_rel_many_je.value]] LEFT JOIN `demo4` `demo4_self_rel_many_self_rel_one_self_rel_many_self_rel_one` ON [[demo4_self_rel_many_self_rel_one_self_rel_many_self_rel_one.id]] = [[demo4_self_rel_many_self_rel_one_self_rel_many.self_rel_one]] WHERE [[demo4_self_rel_many_self_rel_one_self_rel_many_self_rel_one.title]] > 1",
|
||||
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN json_each(CASE WHEN iif(json_valid([[demo4.self_rel_many]]), json_type([[demo4.self_rel_many]])='array', FALSE) THEN [[demo4.self_rel_many]] ELSE json_array([[demo4.self_rel_many]]) END) `demo4_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many` ON [[demo4_self_rel_many.id]] = [[demo4_self_rel_many_je.value]] LEFT JOIN `demo4` `demo4_self_rel_many_self_rel_one` ON [[demo4_self_rel_many_self_rel_one.id]] = [[demo4_self_rel_many.self_rel_one]] LEFT JOIN json_each(CASE WHEN iif(json_valid([[demo4_self_rel_many_self_rel_one.self_rel_many]]), json_type([[demo4_self_rel_many_self_rel_one.self_rel_many]])='array', FALSE) THEN [[demo4_self_rel_many_self_rel_one.self_rel_many]] ELSE json_array([[demo4_self_rel_many_self_rel_one.self_rel_many]]) END) `demo4_self_rel_many_self_rel_one_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many_self_rel_one_self_rel_many` ON [[demo4_self_rel_many_self_rel_one_self_rel_many.id]] = [[demo4_self_rel_many_self_rel_one_self_rel_many_je.value]] LEFT JOIN `demo4` `demo4_self_rel_many_self_rel_one_self_rel_many_self_rel_one` ON [[demo4_self_rel_many_self_rel_one_self_rel_many_self_rel_one.id]] = [[demo4_self_rel_many_self_rel_one_self_rel_many.self_rel_one]] WHERE [[demo4_self_rel_many_self_rel_one_self_rel_many_self_rel_one.title]] > 1",
|
||||
},
|
||||
{
|
||||
"repeated nested relations (multi-match operator)",
|
||||
"demo4",
|
||||
"self_rel_many.self_rel_one.self_rel_many.self_rel_one.title > true",
|
||||
false,
|
||||
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN json_each(CASE WHEN json_valid([[demo4.self_rel_many]]) THEN [[demo4.self_rel_many]] ELSE json_array([[demo4.self_rel_many]]) END) `demo4_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many` ON [[demo4_self_rel_many.id]] = [[demo4_self_rel_many_je.value]] LEFT JOIN `demo4` `demo4_self_rel_many_self_rel_one` ON [[demo4_self_rel_many_self_rel_one.id]] = [[demo4_self_rel_many.self_rel_one]] LEFT JOIN json_each(CASE WHEN json_valid([[demo4_self_rel_many_self_rel_one.self_rel_many]]) THEN [[demo4_self_rel_many_self_rel_one.self_rel_many]] ELSE json_array([[demo4_self_rel_many_self_rel_one.self_rel_many]]) END) `demo4_self_rel_many_self_rel_one_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many_self_rel_one_self_rel_many` ON [[demo4_self_rel_many_self_rel_one_self_rel_many.id]] = [[demo4_self_rel_many_self_rel_one_self_rel_many_je.value]] LEFT JOIN `demo4` `demo4_self_rel_many_self_rel_one_self_rel_many_self_rel_one` ON [[demo4_self_rel_many_self_rel_one_self_rel_many_self_rel_one.id]] = [[demo4_self_rel_many_self_rel_one_self_rel_many.self_rel_one]] WHERE ((([[demo4_self_rel_many_self_rel_one_self_rel_many_self_rel_one.title]] > 1) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo4_self_rel_many_self_rel_one_self_rel_many_self_rel_one.title]] as [[multiMatchValue]] FROM `demo4` `__mm_demo4` LEFT JOIN json_each(CASE WHEN json_valid([[__mm_demo4.self_rel_many]]) THEN [[__mm_demo4.self_rel_many]] ELSE json_array([[__mm_demo4.self_rel_many]]) END) `__mm_demo4_self_rel_many_je` LEFT JOIN `demo4` `__mm_demo4_self_rel_many` ON [[__mm_demo4_self_rel_many.id]] = [[__mm_demo4_self_rel_many_je.value]] LEFT JOIN `demo4` `__mm_demo4_self_rel_many_self_rel_one` ON [[__mm_demo4_self_rel_many_self_rel_one.id]] = [[__mm_demo4_self_rel_many.self_rel_one]] LEFT JOIN json_each(CASE WHEN json_valid([[__mm_demo4_self_rel_many_self_rel_one.self_rel_many]]) THEN [[__mm_demo4_self_rel_many_self_rel_one.self_rel_many]] ELSE json_array([[__mm_demo4_self_rel_many_self_rel_one.self_rel_many]]) END) `__mm_demo4_self_rel_many_self_rel_one_self_rel_many_je` LEFT JOIN `demo4` `__mm_demo4_self_rel_many_self_rel_one_self_rel_many` ON [[__mm_demo4_self_rel_many_self_rel_one_self_rel_many.id]] = [[__mm_demo4_self_rel_many_self_rel_one_self_rel_many_je.value]] LEFT JOIN `demo4` `__mm_demo4_self_rel_many_self_rel_one_self_rel_many_self_rel_one` ON [[__mm_demo4_self_rel_many_self_rel_one_self_rel_many_self_rel_one.id]] = [[__mm_demo4_self_rel_many_self_rel_one_self_rel_many.self_rel_one]] WHERE `__mm_demo4`.`id` = `demo4`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] > 1)))))",
|
||||
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN json_each(CASE WHEN iif(json_valid([[demo4.self_rel_many]]), json_type([[demo4.self_rel_many]])='array', FALSE) THEN [[demo4.self_rel_many]] ELSE json_array([[demo4.self_rel_many]]) END) `demo4_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many` ON [[demo4_self_rel_many.id]] = [[demo4_self_rel_many_je.value]] LEFT JOIN `demo4` `demo4_self_rel_many_self_rel_one` ON [[demo4_self_rel_many_self_rel_one.id]] = [[demo4_self_rel_many.self_rel_one]] LEFT JOIN json_each(CASE WHEN iif(json_valid([[demo4_self_rel_many_self_rel_one.self_rel_many]]), json_type([[demo4_self_rel_many_self_rel_one.self_rel_many]])='array', FALSE) THEN [[demo4_self_rel_many_self_rel_one.self_rel_many]] ELSE json_array([[demo4_self_rel_many_self_rel_one.self_rel_many]]) END) `demo4_self_rel_many_self_rel_one_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many_self_rel_one_self_rel_many` ON [[demo4_self_rel_many_self_rel_one_self_rel_many.id]] = [[demo4_self_rel_many_self_rel_one_self_rel_many_je.value]] LEFT JOIN `demo4` `demo4_self_rel_many_self_rel_one_self_rel_many_self_rel_one` ON [[demo4_self_rel_many_self_rel_one_self_rel_many_self_rel_one.id]] = [[demo4_self_rel_many_self_rel_one_self_rel_many.self_rel_one]] WHERE ((([[demo4_self_rel_many_self_rel_one_self_rel_many_self_rel_one.title]] > 1) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo4_self_rel_many_self_rel_one_self_rel_many_self_rel_one.title]] as [[multiMatchValue]] FROM `demo4` `__mm_demo4` LEFT JOIN json_each(CASE WHEN iif(json_valid([[__mm_demo4.self_rel_many]]), json_type([[__mm_demo4.self_rel_many]])='array', FALSE) THEN [[__mm_demo4.self_rel_many]] ELSE json_array([[__mm_demo4.self_rel_many]]) END) `__mm_demo4_self_rel_many_je` LEFT JOIN `demo4` `__mm_demo4_self_rel_many` ON [[__mm_demo4_self_rel_many.id]] = [[__mm_demo4_self_rel_many_je.value]] LEFT JOIN `demo4` `__mm_demo4_self_rel_many_self_rel_one` ON [[__mm_demo4_self_rel_many_self_rel_one.id]] = [[__mm_demo4_self_rel_many.self_rel_one]] LEFT JOIN json_each(CASE WHEN iif(json_valid([[__mm_demo4_self_rel_many_self_rel_one.self_rel_many]]), json_type([[__mm_demo4_self_rel_many_self_rel_one.self_rel_many]])='array', FALSE) THEN [[__mm_demo4_self_rel_many_self_rel_one.self_rel_many]] ELSE json_array([[__mm_demo4_self_rel_many_self_rel_one.self_rel_many]]) END) `__mm_demo4_self_rel_many_self_rel_one_self_rel_many_je` LEFT JOIN `demo4` `__mm_demo4_self_rel_many_self_rel_one_self_rel_many` ON [[__mm_demo4_self_rel_many_self_rel_one_self_rel_many.id]] = [[__mm_demo4_self_rel_many_self_rel_one_self_rel_many_je.value]] LEFT JOIN `demo4` `__mm_demo4_self_rel_many_self_rel_one_self_rel_many_self_rel_one` ON [[__mm_demo4_self_rel_many_self_rel_one_self_rel_many_self_rel_one.id]] = [[__mm_demo4_self_rel_many_self_rel_one_self_rel_many.self_rel_one]] WHERE `__mm_demo4`.`id` = `demo4`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] > 1)))))",
|
||||
},
|
||||
{
|
||||
"multiple relations (opt/any operators)",
|
||||
"demo4",
|
||||
"self_rel_many.title ?= 'test' || self_rel_one.json_object.a ?> true",
|
||||
false,
|
||||
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN json_each(CASE WHEN json_valid([[demo4.self_rel_many]]) THEN [[demo4.self_rel_many]] ELSE json_array([[demo4.self_rel_many]]) END) `demo4_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many` ON [[demo4_self_rel_many.id]] = [[demo4_self_rel_many_je.value]] LEFT JOIN `demo4` `demo4_self_rel_one` ON [[demo4_self_rel_one.id]] = [[demo4.self_rel_one]] WHERE ([[demo4_self_rel_many.title]] = {:TEST} OR (CASE WHEN json_valid([[demo4_self_rel_one.json_object]]) THEN JSON_EXTRACT([[demo4_self_rel_one.json_object]], '$.a') ELSE JSON_EXTRACT(json_object('pb', [[demo4_self_rel_one.json_object]]), '$.pb.a') END) > 1)",
|
||||
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN json_each(CASE WHEN iif(json_valid([[demo4.self_rel_many]]), json_type([[demo4.self_rel_many]])='array', FALSE) THEN [[demo4.self_rel_many]] ELSE json_array([[demo4.self_rel_many]]) END) `demo4_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many` ON [[demo4_self_rel_many.id]] = [[demo4_self_rel_many_je.value]] LEFT JOIN `demo4` `demo4_self_rel_one` ON [[demo4_self_rel_one.id]] = [[demo4.self_rel_one]] WHERE ([[demo4_self_rel_many.title]] = {:TEST} OR (CASE WHEN json_valid([[demo4_self_rel_one.json_object]]) THEN JSON_EXTRACT([[demo4_self_rel_one.json_object]], '$.a') ELSE JSON_EXTRACT(json_object('pb', [[demo4_self_rel_one.json_object]]), '$.pb.a') END) > 1)",
|
||||
},
|
||||
{
|
||||
"multiple relations (multi-match operators)",
|
||||
"demo4",
|
||||
"self_rel_many.title = 'test' || self_rel_one.json_object.a > true",
|
||||
false,
|
||||
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN json_each(CASE WHEN json_valid([[demo4.self_rel_many]]) THEN [[demo4.self_rel_many]] ELSE json_array([[demo4.self_rel_many]]) END) `demo4_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many` ON [[demo4_self_rel_many.id]] = [[demo4_self_rel_many_je.value]] LEFT JOIN `demo4` `demo4_self_rel_one` ON [[demo4_self_rel_one.id]] = [[demo4.self_rel_one]] WHERE ((([[demo4_self_rel_many.title]] = {:TEST}) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo4_self_rel_many.title]] as [[multiMatchValue]] FROM `demo4` `__mm_demo4` LEFT JOIN json_each(CASE WHEN json_valid([[__mm_demo4.self_rel_many]]) THEN [[__mm_demo4.self_rel_many]] ELSE json_array([[__mm_demo4.self_rel_many]]) END) `__mm_demo4_self_rel_many_je` LEFT JOIN `demo4` `__mm_demo4_self_rel_many` ON [[__mm_demo4_self_rel_many.id]] = [[__mm_demo4_self_rel_many_je.value]] WHERE `__mm_demo4`.`id` = `demo4`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] = {:TEST})))) OR (CASE WHEN json_valid([[demo4_self_rel_one.json_object]]) THEN JSON_EXTRACT([[demo4_self_rel_one.json_object]], '$.a') ELSE JSON_EXTRACT(json_object('pb', [[demo4_self_rel_one.json_object]]), '$.pb.a') END) > 1)",
|
||||
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN json_each(CASE WHEN iif(json_valid([[demo4.self_rel_many]]), json_type([[demo4.self_rel_many]])='array', FALSE) THEN [[demo4.self_rel_many]] ELSE json_array([[demo4.self_rel_many]]) END) `demo4_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many` ON [[demo4_self_rel_many.id]] = [[demo4_self_rel_many_je.value]] LEFT JOIN `demo4` `demo4_self_rel_one` ON [[demo4_self_rel_one.id]] = [[demo4.self_rel_one]] WHERE ((([[demo4_self_rel_many.title]] = {:TEST}) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo4_self_rel_many.title]] as [[multiMatchValue]] FROM `demo4` `__mm_demo4` LEFT JOIN json_each(CASE WHEN iif(json_valid([[__mm_demo4.self_rel_many]]), json_type([[__mm_demo4.self_rel_many]])='array', FALSE) THEN [[__mm_demo4.self_rel_many]] ELSE json_array([[__mm_demo4.self_rel_many]]) END) `__mm_demo4_self_rel_many_je` LEFT JOIN `demo4` `__mm_demo4_self_rel_many` ON [[__mm_demo4_self_rel_many.id]] = [[__mm_demo4_self_rel_many_je.value]] WHERE `__mm_demo4`.`id` = `demo4`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] = {:TEST})))) OR (CASE WHEN json_valid([[demo4_self_rel_one.json_object]]) THEN JSON_EXTRACT([[demo4_self_rel_one.json_object]], '$.a') ELSE JSON_EXTRACT(json_object('pb', [[demo4_self_rel_one.json_object]]), '$.pb.a') END) > 1)",
|
||||
},
|
||||
{
|
||||
"back relations via single relation field (without unique index)",
|
||||
"demo3",
|
||||
"demo4_via_rel_one_cascade.id = true",
|
||||
false,
|
||||
"SELECT DISTINCT `demo3`.* FROM `demo3` LEFT JOIN `demo4` `demo3_demo4_via_rel_one_cascade` ON [[demo3.id]] IN (SELECT [[demo3_demo4_via_rel_one_cascade_je.value]] FROM json_each(CASE WHEN json_valid([[demo3_demo4_via_rel_one_cascade.rel_one_cascade]]) THEN [[demo3_demo4_via_rel_one_cascade.rel_one_cascade]] ELSE json_array([[demo3_demo4_via_rel_one_cascade.rel_one_cascade]]) END) {{demo3_demo4_via_rel_one_cascade_je}}) WHERE ((([[demo3_demo4_via_rel_one_cascade.id]] = 1) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo3_demo4_via_rel_one_cascade.id]] as [[multiMatchValue]] FROM `demo3` `__mm_demo3` LEFT JOIN `demo4` `__mm_demo3_demo4_via_rel_one_cascade` ON [[__mm_demo3.id]] IN (SELECT [[__mm_demo3_demo4_via_rel_one_cascade_je.value]] FROM json_each(CASE WHEN json_valid([[__mm_demo3_demo4_via_rel_one_cascade.rel_one_cascade]]) THEN [[__mm_demo3_demo4_via_rel_one_cascade.rel_one_cascade]] ELSE json_array([[__mm_demo3_demo4_via_rel_one_cascade.rel_one_cascade]]) END) {{__mm_demo3_demo4_via_rel_one_cascade_je}}) WHERE `__mm_demo3`.`id` = `demo3`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] = 1)))))",
|
||||
"SELECT DISTINCT `demo3`.* FROM `demo3` LEFT JOIN `demo4` `demo3_demo4_via_rel_one_cascade` ON [[demo3.id]] IN (SELECT [[demo3_demo4_via_rel_one_cascade_je.value]] FROM json_each(CASE WHEN iif(json_valid([[demo3_demo4_via_rel_one_cascade.rel_one_cascade]]), json_type([[demo3_demo4_via_rel_one_cascade.rel_one_cascade]])='array', FALSE) THEN [[demo3_demo4_via_rel_one_cascade.rel_one_cascade]] ELSE json_array([[demo3_demo4_via_rel_one_cascade.rel_one_cascade]]) END) {{demo3_demo4_via_rel_one_cascade_je}}) WHERE ((([[demo3_demo4_via_rel_one_cascade.id]] = 1) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo3_demo4_via_rel_one_cascade.id]] as [[multiMatchValue]] FROM `demo3` `__mm_demo3` LEFT JOIN `demo4` `__mm_demo3_demo4_via_rel_one_cascade` ON [[__mm_demo3.id]] IN (SELECT [[__mm_demo3_demo4_via_rel_one_cascade_je.value]] FROM json_each(CASE WHEN iif(json_valid([[__mm_demo3_demo4_via_rel_one_cascade.rel_one_cascade]]), json_type([[__mm_demo3_demo4_via_rel_one_cascade.rel_one_cascade]])='array', FALSE) THEN [[__mm_demo3_demo4_via_rel_one_cascade.rel_one_cascade]] ELSE json_array([[__mm_demo3_demo4_via_rel_one_cascade.rel_one_cascade]]) END) {{__mm_demo3_demo4_via_rel_one_cascade_je}}) WHERE `__mm_demo3`.`id` = `demo3`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] = 1)))))",
|
||||
},
|
||||
{
|
||||
"back relations via single relation field (with unique index)",
|
||||
@@ -271,28 +271,28 @@ func TestRecordFieldResolverUpdateQuery(t *testing.T) {
|
||||
"demo3",
|
||||
"demo4_via_rel_many_cascade.id ?= true",
|
||||
false,
|
||||
"SELECT DISTINCT `demo3`.* FROM `demo3` LEFT JOIN `demo4` `demo3_demo4_via_rel_many_cascade` ON [[demo3.id]] IN (SELECT [[demo3_demo4_via_rel_many_cascade_je.value]] FROM json_each(CASE WHEN json_valid([[demo3_demo4_via_rel_many_cascade.rel_many_cascade]]) THEN [[demo3_demo4_via_rel_many_cascade.rel_many_cascade]] ELSE json_array([[demo3_demo4_via_rel_many_cascade.rel_many_cascade]]) END) {{demo3_demo4_via_rel_many_cascade_je}}) WHERE [[demo3_demo4_via_rel_many_cascade.id]] = 1",
|
||||
"SELECT DISTINCT `demo3`.* FROM `demo3` LEFT JOIN `demo4` `demo3_demo4_via_rel_many_cascade` ON [[demo3.id]] IN (SELECT [[demo3_demo4_via_rel_many_cascade_je.value]] FROM json_each(CASE WHEN iif(json_valid([[demo3_demo4_via_rel_many_cascade.rel_many_cascade]]), json_type([[demo3_demo4_via_rel_many_cascade.rel_many_cascade]])='array', FALSE) THEN [[demo3_demo4_via_rel_many_cascade.rel_many_cascade]] ELSE json_array([[demo3_demo4_via_rel_many_cascade.rel_many_cascade]]) END) {{demo3_demo4_via_rel_many_cascade_je}}) WHERE [[demo3_demo4_via_rel_many_cascade.id]] = 1",
|
||||
},
|
||||
{
|
||||
"back relations via multiple relation field (multi-match operators)",
|
||||
"demo3",
|
||||
"demo4_via_rel_many_cascade.id = true",
|
||||
false,
|
||||
"SELECT DISTINCT `demo3`.* FROM `demo3` LEFT JOIN `demo4` `demo3_demo4_via_rel_many_cascade` ON [[demo3.id]] IN (SELECT [[demo3_demo4_via_rel_many_cascade_je.value]] FROM json_each(CASE WHEN json_valid([[demo3_demo4_via_rel_many_cascade.rel_many_cascade]]) THEN [[demo3_demo4_via_rel_many_cascade.rel_many_cascade]] ELSE json_array([[demo3_demo4_via_rel_many_cascade.rel_many_cascade]]) END) {{demo3_demo4_via_rel_many_cascade_je}}) WHERE ((([[demo3_demo4_via_rel_many_cascade.id]] = 1) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo3_demo4_via_rel_many_cascade.id]] as [[multiMatchValue]] FROM `demo3` `__mm_demo3` LEFT JOIN `demo4` `__mm_demo3_demo4_via_rel_many_cascade` ON [[__mm_demo3.id]] IN (SELECT [[__mm_demo3_demo4_via_rel_many_cascade_je.value]] FROM json_each(CASE WHEN json_valid([[__mm_demo3_demo4_via_rel_many_cascade.rel_many_cascade]]) THEN [[__mm_demo3_demo4_via_rel_many_cascade.rel_many_cascade]] ELSE json_array([[__mm_demo3_demo4_via_rel_many_cascade.rel_many_cascade]]) END) {{__mm_demo3_demo4_via_rel_many_cascade_je}}) WHERE `__mm_demo3`.`id` = `demo3`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] = 1)))))",
|
||||
"SELECT DISTINCT `demo3`.* FROM `demo3` LEFT JOIN `demo4` `demo3_demo4_via_rel_many_cascade` ON [[demo3.id]] IN (SELECT [[demo3_demo4_via_rel_many_cascade_je.value]] FROM json_each(CASE WHEN iif(json_valid([[demo3_demo4_via_rel_many_cascade.rel_many_cascade]]), json_type([[demo3_demo4_via_rel_many_cascade.rel_many_cascade]])='array', FALSE) THEN [[demo3_demo4_via_rel_many_cascade.rel_many_cascade]] ELSE json_array([[demo3_demo4_via_rel_many_cascade.rel_many_cascade]]) END) {{demo3_demo4_via_rel_many_cascade_je}}) WHERE ((([[demo3_demo4_via_rel_many_cascade.id]] = 1) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo3_demo4_via_rel_many_cascade.id]] as [[multiMatchValue]] FROM `demo3` `__mm_demo3` LEFT JOIN `demo4` `__mm_demo3_demo4_via_rel_many_cascade` ON [[__mm_demo3.id]] IN (SELECT [[__mm_demo3_demo4_via_rel_many_cascade_je.value]] FROM json_each(CASE WHEN iif(json_valid([[__mm_demo3_demo4_via_rel_many_cascade.rel_many_cascade]]), json_type([[__mm_demo3_demo4_via_rel_many_cascade.rel_many_cascade]])='array', FALSE) THEN [[__mm_demo3_demo4_via_rel_many_cascade.rel_many_cascade]] ELSE json_array([[__mm_demo3_demo4_via_rel_many_cascade.rel_many_cascade]]) END) {{__mm_demo3_demo4_via_rel_many_cascade_je}}) WHERE `__mm_demo3`.`id` = `demo3`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] = 1)))))",
|
||||
},
|
||||
{
|
||||
"back relations via unique multiple relation field (should be the same as multi-match)",
|
||||
"demo3",
|
||||
"demo4_via_rel_many_unique.id = true",
|
||||
false,
|
||||
"SELECT DISTINCT `demo3`.* FROM `demo3` LEFT JOIN `demo4` `demo3_demo4_via_rel_many_unique` ON [[demo3.id]] IN (SELECT [[demo3_demo4_via_rel_many_unique_je.value]] FROM json_each(CASE WHEN json_valid([[demo3_demo4_via_rel_many_unique.rel_many_unique]]) THEN [[demo3_demo4_via_rel_many_unique.rel_many_unique]] ELSE json_array([[demo3_demo4_via_rel_many_unique.rel_many_unique]]) END) {{demo3_demo4_via_rel_many_unique_je}}) WHERE ((([[demo3_demo4_via_rel_many_unique.id]] = 1) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo3_demo4_via_rel_many_unique.id]] as [[multiMatchValue]] FROM `demo3` `__mm_demo3` LEFT JOIN `demo4` `__mm_demo3_demo4_via_rel_many_unique` ON [[__mm_demo3.id]] IN (SELECT [[__mm_demo3_demo4_via_rel_many_unique_je.value]] FROM json_each(CASE WHEN json_valid([[__mm_demo3_demo4_via_rel_many_unique.rel_many_unique]]) THEN [[__mm_demo3_demo4_via_rel_many_unique.rel_many_unique]] ELSE json_array([[__mm_demo3_demo4_via_rel_many_unique.rel_many_unique]]) END) {{__mm_demo3_demo4_via_rel_many_unique_je}}) WHERE `__mm_demo3`.`id` = `demo3`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] = 1)))))",
|
||||
"SELECT DISTINCT `demo3`.* FROM `demo3` LEFT JOIN `demo4` `demo3_demo4_via_rel_many_unique` ON [[demo3.id]] IN (SELECT [[demo3_demo4_via_rel_many_unique_je.value]] FROM json_each(CASE WHEN iif(json_valid([[demo3_demo4_via_rel_many_unique.rel_many_unique]]), json_type([[demo3_demo4_via_rel_many_unique.rel_many_unique]])='array', FALSE) THEN [[demo3_demo4_via_rel_many_unique.rel_many_unique]] ELSE json_array([[demo3_demo4_via_rel_many_unique.rel_many_unique]]) END) {{demo3_demo4_via_rel_many_unique_je}}) WHERE ((([[demo3_demo4_via_rel_many_unique.id]] = 1) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo3_demo4_via_rel_many_unique.id]] as [[multiMatchValue]] FROM `demo3` `__mm_demo3` LEFT JOIN `demo4` `__mm_demo3_demo4_via_rel_many_unique` ON [[__mm_demo3.id]] IN (SELECT [[__mm_demo3_demo4_via_rel_many_unique_je.value]] FROM json_each(CASE WHEN iif(json_valid([[__mm_demo3_demo4_via_rel_many_unique.rel_many_unique]]), json_type([[__mm_demo3_demo4_via_rel_many_unique.rel_many_unique]])='array', FALSE) THEN [[__mm_demo3_demo4_via_rel_many_unique.rel_many_unique]] ELSE json_array([[__mm_demo3_demo4_via_rel_many_unique.rel_many_unique]]) END) {{__mm_demo3_demo4_via_rel_many_unique_je}}) WHERE `__mm_demo3`.`id` = `demo3`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] = 1)))))",
|
||||
},
|
||||
{
|
||||
"recursive back relations",
|
||||
"demo3",
|
||||
"demo4_via_rel_many_cascade.rel_one_cascade.demo4_via_rel_many_cascade.id ?= true",
|
||||
false,
|
||||
"SELECT DISTINCT `demo3`.* FROM `demo3` LEFT JOIN `demo4` `demo3_demo4_via_rel_many_cascade` ON [[demo3.id]] IN (SELECT [[demo3_demo4_via_rel_many_cascade_je.value]] FROM json_each(CASE WHEN json_valid([[demo3_demo4_via_rel_many_cascade.rel_many_cascade]]) THEN [[demo3_demo4_via_rel_many_cascade.rel_many_cascade]] ELSE json_array([[demo3_demo4_via_rel_many_cascade.rel_many_cascade]]) END) {{demo3_demo4_via_rel_many_cascade_je}}) LEFT JOIN `demo3` `demo3_demo4_via_rel_many_cascade_rel_one_cascade` ON [[demo3_demo4_via_rel_many_cascade_rel_one_cascade.id]] = [[demo3_demo4_via_rel_many_cascade.rel_one_cascade]] LEFT JOIN `demo4` `demo3_demo4_via_rel_many_cascade_rel_one_cascade_demo4_via_rel_many_cascade` ON [[demo3_demo4_via_rel_many_cascade_rel_one_cascade.id]] IN (SELECT [[demo3_demo4_via_rel_many_cascade_rel_one_cascade_demo4_via_rel_many_cascade_je.value]] FROM json_each(CASE WHEN json_valid([[demo3_demo4_via_rel_many_cascade_rel_one_cascade_demo4_via_rel_many_cascade.rel_many_cascade]]) THEN [[demo3_demo4_via_rel_many_cascade_rel_one_cascade_demo4_via_rel_many_cascade.rel_many_cascade]] ELSE json_array([[demo3_demo4_via_rel_many_cascade_rel_one_cascade_demo4_via_rel_many_cascade.rel_many_cascade]]) END) {{demo3_demo4_via_rel_many_cascade_rel_one_cascade_demo4_via_rel_many_cascade_je}}) WHERE [[demo3_demo4_via_rel_many_cascade_rel_one_cascade_demo4_via_rel_many_cascade.id]] = 1",
|
||||
"SELECT DISTINCT `demo3`.* FROM `demo3` LEFT JOIN `demo4` `demo3_demo4_via_rel_many_cascade` ON [[demo3.id]] IN (SELECT [[demo3_demo4_via_rel_many_cascade_je.value]] FROM json_each(CASE WHEN iif(json_valid([[demo3_demo4_via_rel_many_cascade.rel_many_cascade]]), json_type([[demo3_demo4_via_rel_many_cascade.rel_many_cascade]])='array', FALSE) THEN [[demo3_demo4_via_rel_many_cascade.rel_many_cascade]] ELSE json_array([[demo3_demo4_via_rel_many_cascade.rel_many_cascade]]) END) {{demo3_demo4_via_rel_many_cascade_je}}) LEFT JOIN `demo3` `demo3_demo4_via_rel_many_cascade_rel_one_cascade` ON [[demo3_demo4_via_rel_many_cascade_rel_one_cascade.id]] = [[demo3_demo4_via_rel_many_cascade.rel_one_cascade]] LEFT JOIN `demo4` `demo3_demo4_via_rel_many_cascade_rel_one_cascade_demo4_via_rel_many_cascade` ON [[demo3_demo4_via_rel_many_cascade_rel_one_cascade.id]] IN (SELECT [[demo3_demo4_via_rel_many_cascade_rel_one_cascade_demo4_via_rel_many_cascade_je.value]] FROM json_each(CASE WHEN iif(json_valid([[demo3_demo4_via_rel_many_cascade_rel_one_cascade_demo4_via_rel_many_cascade.rel_many_cascade]]), json_type([[demo3_demo4_via_rel_many_cascade_rel_one_cascade_demo4_via_rel_many_cascade.rel_many_cascade]])='array', FALSE) THEN [[demo3_demo4_via_rel_many_cascade_rel_one_cascade_demo4_via_rel_many_cascade.rel_many_cascade]] ELSE json_array([[demo3_demo4_via_rel_many_cascade_rel_one_cascade_demo4_via_rel_many_cascade.rel_many_cascade]]) END) {{demo3_demo4_via_rel_many_cascade_rel_one_cascade_demo4_via_rel_many_cascade_je}}) WHERE [[demo3_demo4_via_rel_many_cascade_rel_one_cascade_demo4_via_rel_many_cascade.id]] = 1",
|
||||
},
|
||||
{
|
||||
"@collection join (opt/any operators)",
|
||||
@@ -379,7 +379,7 @@ func TestRecordFieldResolverUpdateQuery(t *testing.T) {
|
||||
"rel_many.name:lower > true ||" +
|
||||
"created:lower > true",
|
||||
false,
|
||||
"SELECT DISTINCT `demo1`.* FROM `demo1` LEFT JOIN `users` `__data_users_rel_many` ON [[__data_users_rel_many.id]] IN ({:p0}, {:p1}) LEFT JOIN json_each(CASE WHEN json_valid([[demo1.rel_many]]) THEN [[demo1.rel_many]] ELSE json_array([[demo1.rel_many]]) END) `demo1_rel_many_je` LEFT JOIN `users` `demo1_rel_many` ON [[demo1_rel_many.id]] = [[demo1_rel_many_je.value]] WHERE (LOWER({:infoLowerrel_oneTEST}) > 1 OR LOWER({:infoLowerrel_manyTEST}) > 1 OR ((LOWER([[__data_users_rel_many.email]]) > 1) AND (NOT EXISTS (SELECT 1 FROM (SELECT LOWER([[__data_mm_users_rel_many.email]]) as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN `users` `__data_mm_users_rel_many` ON [[__data_mm_users_rel_many.id]] IN ({:p4}, {:p5}) WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] > 1)))) OR LOWER([[demo1.text]]) > 1 OR LOWER([[demo1.bool]]) > 1 OR LOWER([[demo1.url]]) > 1 OR LOWER([[demo1.select_one]]) > 1 OR LOWER([[demo1.select_many]]) > 1 OR LOWER([[demo1.file_one]]) > 1 OR LOWER([[demo1.file_many]]) > 1 OR LOWER([[demo1.number]]) > 1 OR LOWER([[demo1.email]]) > 1 OR LOWER([[demo1.datetime]]) > 1 OR LOWER((CASE WHEN json_valid([[demo1.json]]) THEN JSON_EXTRACT([[demo1.json]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo1.json]]), '$.pb') END)) > 1 OR LOWER([[demo1.rel_one]]) > 1 OR LOWER([[demo1.rel_many]]) > 1 OR ((LOWER([[demo1_rel_many.name]]) > 1) AND (NOT EXISTS (SELECT 1 FROM (SELECT LOWER([[__mm_demo1_rel_many.name]]) as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each(CASE WHEN json_valid([[__mm_demo1.rel_many]]) THEN [[__mm_demo1.rel_many]] ELSE json_array([[__mm_demo1.rel_many]]) END) `__mm_demo1_rel_many_je` LEFT JOIN `users` `__mm_demo1_rel_many` ON [[__mm_demo1_rel_many.id]] = [[__mm_demo1_rel_many_je.value]] WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] > 1)))) OR LOWER([[demo1.created]]) > 1)",
|
||||
"SELECT DISTINCT `demo1`.* FROM `demo1` LEFT JOIN `users` `__data_users_rel_many` ON [[__data_users_rel_many.id]] IN ({:p0}, {:p1}) LEFT JOIN json_each(CASE WHEN iif(json_valid([[demo1.rel_many]]), json_type([[demo1.rel_many]])='array', FALSE) THEN [[demo1.rel_many]] ELSE json_array([[demo1.rel_many]]) END) `demo1_rel_many_je` LEFT JOIN `users` `demo1_rel_many` ON [[demo1_rel_many.id]] = [[demo1_rel_many_je.value]] WHERE (LOWER({:infoLowerrel_oneTEST}) > 1 OR LOWER({:infoLowerrel_manyTEST}) > 1 OR ((LOWER([[__data_users_rel_many.email]]) > 1) AND (NOT EXISTS (SELECT 1 FROM (SELECT LOWER([[__data_mm_users_rel_many.email]]) as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN `users` `__data_mm_users_rel_many` ON [[__data_mm_users_rel_many.id]] IN ({:p4}, {:p5}) WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] > 1)))) OR LOWER([[demo1.text]]) > 1 OR LOWER([[demo1.bool]]) > 1 OR LOWER([[demo1.url]]) > 1 OR LOWER([[demo1.select_one]]) > 1 OR LOWER([[demo1.select_many]]) > 1 OR LOWER([[demo1.file_one]]) > 1 OR LOWER([[demo1.file_many]]) > 1 OR LOWER([[demo1.number]]) > 1 OR LOWER([[demo1.email]]) > 1 OR LOWER([[demo1.datetime]]) > 1 OR LOWER((CASE WHEN json_valid([[demo1.json]]) THEN JSON_EXTRACT([[demo1.json]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo1.json]]), '$.pb') END)) > 1 OR LOWER([[demo1.rel_one]]) > 1 OR LOWER([[demo1.rel_many]]) > 1 OR ((LOWER([[demo1_rel_many.name]]) > 1) AND (NOT EXISTS (SELECT 1 FROM (SELECT LOWER([[__mm_demo1_rel_many.name]]) as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each(CASE WHEN iif(json_valid([[__mm_demo1.rel_many]]), json_type([[__mm_demo1.rel_many]])='array', FALSE) THEN [[__mm_demo1.rel_many]] ELSE json_array([[__mm_demo1.rel_many]]) END) `__mm_demo1_rel_many_je` LEFT JOIN `users` `__mm_demo1_rel_many` ON [[__mm_demo1_rel_many.id]] = [[__mm_demo1_rel_many_je.value]] WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] > 1)))) OR LOWER([[demo1.created]]) > 1)",
|
||||
},
|
||||
{
|
||||
"isset modifier",
|
||||
@@ -440,7 +440,7 @@ func TestRecordFieldResolverUpdateQuery(t *testing.T) {
|
||||
"rel_many:each > true &&" +
|
||||
"rel_many:each ?< true",
|
||||
false,
|
||||
"SELECT DISTINCT `demo1`.* FROM `demo1` LEFT JOIN json_each(CASE WHEN json_valid([[demo1.select_one]]) THEN [[demo1.select_one]] ELSE json_array([[demo1.select_one]]) END) `demo1_select_one_je` LEFT JOIN json_each(CASE WHEN json_valid([[demo1.select_many]]) THEN [[demo1.select_many]] ELSE json_array([[demo1.select_many]]) END) `demo1_select_many_je` LEFT JOIN json_each(CASE WHEN json_valid([[demo1.file_one]]) THEN [[demo1.file_one]] ELSE json_array([[demo1.file_one]]) END) `demo1_file_one_je` LEFT JOIN json_each(CASE WHEN json_valid([[demo1.file_many]]) THEN [[demo1.file_many]] ELSE json_array([[demo1.file_many]]) END) `demo1_file_many_je` LEFT JOIN json_each(CASE WHEN json_valid([[demo1.rel_one]]) THEN [[demo1.rel_one]] ELSE json_array([[demo1.rel_one]]) END) `demo1_rel_one_je` LEFT JOIN json_each(CASE WHEN json_valid([[demo1.rel_many]]) THEN [[demo1.rel_many]] ELSE json_array([[demo1.rel_many]]) END) `demo1_rel_many_je` WHERE ([[demo1_select_one_je.value]] > 1 AND [[demo1_select_one_je.value]] < 1 AND (([[demo1_select_many_je.value]] > 1) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo1_select_many_je.value]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each(CASE WHEN json_valid([[__mm_demo1.select_many]]) THEN [[__mm_demo1.select_many]] ELSE json_array([[__mm_demo1.select_many]]) END) `__mm_demo1_select_many_je` WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] > 1)))) AND [[demo1_select_many_je.value]] < 1 AND [[demo1_file_one_je.value]] > 1 AND [[demo1_file_one_je.value]] < 1 AND (([[demo1_file_many_je.value]] > 1) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo1_file_many_je.value]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each(CASE WHEN json_valid([[__mm_demo1.file_many]]) THEN [[__mm_demo1.file_many]] ELSE json_array([[__mm_demo1.file_many]]) END) `__mm_demo1_file_many_je` WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] > 1)))) AND [[demo1_file_many_je.value]] < 1 AND [[demo1_rel_one_je.value]] > 1 AND [[demo1_rel_one_je.value]] < 1 AND (([[demo1_rel_many_je.value]] > 1) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo1_rel_many_je.value]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each(CASE WHEN json_valid([[__mm_demo1.rel_many]]) THEN [[__mm_demo1.rel_many]] ELSE json_array([[__mm_demo1.rel_many]]) END) `__mm_demo1_rel_many_je` WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] > 1)))) AND [[demo1_rel_many_je.value]] < 1)",
|
||||
"SELECT DISTINCT `demo1`.* FROM `demo1` LEFT JOIN json_each(CASE WHEN iif(json_valid([[demo1.select_one]]), json_type([[demo1.select_one]])='array', FALSE) THEN [[demo1.select_one]] ELSE json_array([[demo1.select_one]]) END) `demo1_select_one_je` LEFT JOIN json_each(CASE WHEN iif(json_valid([[demo1.select_many]]), json_type([[demo1.select_many]])='array', FALSE) THEN [[demo1.select_many]] ELSE json_array([[demo1.select_many]]) END) `demo1_select_many_je` LEFT JOIN json_each(CASE WHEN iif(json_valid([[demo1.file_one]]), json_type([[demo1.file_one]])='array', FALSE) THEN [[demo1.file_one]] ELSE json_array([[demo1.file_one]]) END) `demo1_file_one_je` LEFT JOIN json_each(CASE WHEN iif(json_valid([[demo1.file_many]]), json_type([[demo1.file_many]])='array', FALSE) THEN [[demo1.file_many]] ELSE json_array([[demo1.file_many]]) END) `demo1_file_many_je` LEFT JOIN json_each(CASE WHEN iif(json_valid([[demo1.rel_one]]), json_type([[demo1.rel_one]])='array', FALSE) THEN [[demo1.rel_one]] ELSE json_array([[demo1.rel_one]]) END) `demo1_rel_one_je` LEFT JOIN json_each(CASE WHEN iif(json_valid([[demo1.rel_many]]), json_type([[demo1.rel_many]])='array', FALSE) THEN [[demo1.rel_many]] ELSE json_array([[demo1.rel_many]]) END) `demo1_rel_many_je` WHERE ([[demo1_select_one_je.value]] > 1 AND [[demo1_select_one_je.value]] < 1 AND (([[demo1_select_many_je.value]] > 1) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo1_select_many_je.value]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each(CASE WHEN iif(json_valid([[__mm_demo1.select_many]]), json_type([[__mm_demo1.select_many]])='array', FALSE) THEN [[__mm_demo1.select_many]] ELSE json_array([[__mm_demo1.select_many]]) END) `__mm_demo1_select_many_je` WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] > 1)))) AND [[demo1_select_many_je.value]] < 1 AND [[demo1_file_one_je.value]] > 1 AND [[demo1_file_one_je.value]] < 1 AND (([[demo1_file_many_je.value]] > 1) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo1_file_many_je.value]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each(CASE WHEN iif(json_valid([[__mm_demo1.file_many]]), json_type([[__mm_demo1.file_many]])='array', FALSE) THEN [[__mm_demo1.file_many]] ELSE json_array([[__mm_demo1.file_many]]) END) `__mm_demo1_file_many_je` WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] > 1)))) AND [[demo1_file_many_je.value]] < 1 AND [[demo1_rel_one_je.value]] > 1 AND [[demo1_rel_one_je.value]] < 1 AND (([[demo1_rel_many_je.value]] > 1) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo1_rel_many_je.value]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each(CASE WHEN iif(json_valid([[__mm_demo1.rel_many]]), json_type([[__mm_demo1.rel_many]])='array', FALSE) THEN [[__mm_demo1.rel_many]] ELSE json_array([[__mm_demo1.rel_many]]) END) `__mm_demo1_rel_many_je` WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] > 1)))) AND [[demo1_rel_many_je.value]] < 1)",
|
||||
},
|
||||
{
|
||||
"arrayble:each vs arrayble:each",
|
||||
@@ -450,7 +450,7 @@ func TestRecordFieldResolverUpdateQuery(t *testing.T) {
|
||||
"select_many:each ?< select_one:each &&" +
|
||||
"select_many:each = @request.body.select_many:each",
|
||||
false,
|
||||
"SELECT DISTINCT `demo1`.* FROM `demo1` LEFT JOIN json_each(CASE WHEN json_valid([[demo1.select_one]]) THEN [[demo1.select_one]] ELSE json_array([[demo1.select_one]]) END) `demo1_select_one_je` LEFT JOIN json_each(CASE WHEN json_valid([[demo1.select_many]]) THEN [[demo1.select_many]] ELSE json_array([[demo1.select_many]]) END) `demo1_select_many_je` LEFT JOIN json_each({:dataEachTEST}) `__dataEach_select_many_je` WHERE (((COALESCE([[demo1_select_one_je.value]], '') IS NOT COALESCE([[demo1_select_many_je.value]], '')) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo1_select_many_je.value]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each(CASE WHEN json_valid([[__mm_demo1.select_many]]) THEN [[__mm_demo1.select_many]] ELSE json_array([[__mm_demo1.select_many]]) END) `__mm_demo1_select_many_je` WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__smTEST}} WHERE NOT (COALESCE([[demo1_select_one_je.value]], '') IS NOT COALESCE([[__smTEST.multiMatchValue]], ''))))) AND (([[demo1_select_many_je.value]] > [[demo1_select_one_je.value]]) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo1_select_many_je.value]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each(CASE WHEN json_valid([[__mm_demo1.select_many]]) THEN [[__mm_demo1.select_many]] ELSE json_array([[__mm_demo1.select_many]]) END) `__mm_demo1_select_many_je` WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] > [[demo1_select_one_je.value]])))) AND [[demo1_select_many_je.value]] < [[demo1_select_one_je.value]] AND (([[demo1_select_many_je.value]] = [[__dataEach_select_many_je.value]]) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo1_select_many_je.value]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each(CASE WHEN json_valid([[__mm_demo1.select_many]]) THEN [[__mm_demo1.select_many]] ELSE json_array([[__mm_demo1.select_many]]) END) `__mm_demo1_select_many_je` WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__mlTEST}} LEFT JOIN (SELECT [[__mm__dataEach_select_many_je.value]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each({:mmdataEachTEST}) `__mm__dataEach_select_many_je` WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__mrTEST}} WHERE NOT (COALESCE([[__mlTEST.multiMatchValue]], '') = COALESCE([[__mrTEST.multiMatchValue]], ''))))))",
|
||||
"SELECT DISTINCT `demo1`.* FROM `demo1` LEFT JOIN json_each(CASE WHEN iif(json_valid([[demo1.select_one]]), json_type([[demo1.select_one]])='array', FALSE) THEN [[demo1.select_one]] ELSE json_array([[demo1.select_one]]) END) `demo1_select_one_je` LEFT JOIN json_each(CASE WHEN iif(json_valid([[demo1.select_many]]), json_type([[demo1.select_many]])='array', FALSE) THEN [[demo1.select_many]] ELSE json_array([[demo1.select_many]]) END) `demo1_select_many_je` LEFT JOIN json_each({:dataEachTEST}) `__dataEach_select_many_je` WHERE (((COALESCE([[demo1_select_one_je.value]], '') IS NOT COALESCE([[demo1_select_many_je.value]], '')) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo1_select_many_je.value]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each(CASE WHEN iif(json_valid([[__mm_demo1.select_many]]), json_type([[__mm_demo1.select_many]])='array', FALSE) THEN [[__mm_demo1.select_many]] ELSE json_array([[__mm_demo1.select_many]]) END) `__mm_demo1_select_many_je` WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__smTEST}} WHERE NOT (COALESCE([[demo1_select_one_je.value]], '') IS NOT COALESCE([[__smTEST.multiMatchValue]], ''))))) AND (([[demo1_select_many_je.value]] > [[demo1_select_one_je.value]]) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo1_select_many_je.value]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each(CASE WHEN iif(json_valid([[__mm_demo1.select_many]]), json_type([[__mm_demo1.select_many]])='array', FALSE) THEN [[__mm_demo1.select_many]] ELSE json_array([[__mm_demo1.select_many]]) END) `__mm_demo1_select_many_je` WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] > [[demo1_select_one_je.value]])))) AND [[demo1_select_many_je.value]] < [[demo1_select_one_je.value]] AND (([[demo1_select_many_je.value]] = [[__dataEach_select_many_je.value]]) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo1_select_many_je.value]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each(CASE WHEN iif(json_valid([[__mm_demo1.select_many]]), json_type([[__mm_demo1.select_many]])='array', FALSE) THEN [[__mm_demo1.select_many]] ELSE json_array([[__mm_demo1.select_many]]) END) `__mm_demo1_select_many_je` WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__mlTEST}} LEFT JOIN (SELECT [[__mm__dataEach_select_many_je.value]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each({:mmdataEachTEST}) `__mm__dataEach_select_many_je` WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__mrTEST}} WHERE NOT (COALESCE([[__mlTEST.multiMatchValue]], '') = COALESCE([[__mrTEST.multiMatchValue]], ''))))))",
|
||||
},
|
||||
{
|
||||
"mixed multi-match vs multi-match",
|
||||
@@ -462,7 +462,7 @@ func TestRecordFieldResolverUpdateQuery(t *testing.T) {
|
||||
"@collection.demo2.active ?= rel_many.rel.active &&" +
|
||||
"rel_many.email > @request.body.rel_many.email",
|
||||
false,
|
||||
"SELECT DISTINCT `demo1`.* FROM `demo1` LEFT JOIN json_each(CASE WHEN json_valid([[demo1.rel_many]]) THEN [[demo1.rel_many]] ELSE json_array([[demo1.rel_many]]) END) `demo1_rel_many_je` LEFT JOIN `users` `demo1_rel_many` ON [[demo1_rel_many.id]] = [[demo1_rel_many_je.value]] LEFT JOIN `demo2` `demo1_rel_many_rel` ON [[demo1_rel_many_rel.id]] = [[demo1_rel_many.rel]] LEFT JOIN `demo1` `demo1_rel_one` ON [[demo1_rel_one.id]] = [[demo1.rel_one]] LEFT JOIN `demo2` `__collection_demo2` LEFT JOIN `users` `__data_users_rel_many` ON [[__data_users_rel_many.id]] IN ({:p0}, {:p1}) WHERE (((COALESCE([[demo1_rel_many_rel.active]], '') IS NOT COALESCE([[demo1_rel_many.name]], '')) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo1_rel_many_rel.active]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each(CASE WHEN json_valid([[__mm_demo1.rel_many]]) THEN [[__mm_demo1.rel_many]] ELSE json_array([[__mm_demo1.rel_many]]) END) `__mm_demo1_rel_many_je` LEFT JOIN `users` `__mm_demo1_rel_many` ON [[__mm_demo1_rel_many.id]] = [[__mm_demo1_rel_many_je.value]] LEFT JOIN `demo2` `__mm_demo1_rel_many_rel` ON [[__mm_demo1_rel_many_rel.id]] = [[__mm_demo1_rel_many.rel]] WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__mlTEST}} LEFT JOIN (SELECT [[__mm_demo1_rel_many.name]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each(CASE WHEN json_valid([[__mm_demo1.rel_many]]) THEN [[__mm_demo1.rel_many]] ELSE json_array([[__mm_demo1.rel_many]]) END) `__mm_demo1_rel_many_je` LEFT JOIN `users` `__mm_demo1_rel_many` ON [[__mm_demo1_rel_many.id]] = [[__mm_demo1_rel_many_je.value]] WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__mrTEST}} WHERE NOT (COALESCE([[__mlTEST.multiMatchValue]], '') IS NOT COALESCE([[__mrTEST.multiMatchValue]], ''))))) AND COALESCE([[demo1_rel_many_rel.active]], '') = COALESCE([[demo1_rel_many.name]], '') AND (([[demo1_rel_many_rel.title]] LIKE ('%' || [[demo1_rel_one.email]] || '%') ESCAPE '\\') AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo1_rel_many_rel.title]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each(CASE WHEN json_valid([[__mm_demo1.rel_many]]) THEN [[__mm_demo1.rel_many]] ELSE json_array([[__mm_demo1.rel_many]]) END) `__mm_demo1_rel_many_je` LEFT JOIN `users` `__mm_demo1_rel_many` ON [[__mm_demo1_rel_many.id]] = [[__mm_demo1_rel_many_je.value]] LEFT JOIN `demo2` `__mm_demo1_rel_many_rel` ON [[__mm_demo1_rel_many_rel.id]] = [[__mm_demo1_rel_many.rel]] WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] LIKE ('%' || [[demo1_rel_one.email]] || '%') ESCAPE '\\')))) AND ((COALESCE([[__collection_demo2.active]], '') = COALESCE([[demo1_rel_many_rel.active]], '')) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm__collection_demo2.active]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN `demo2` `__mm__collection_demo2` WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__mlTEST}} LEFT JOIN (SELECT [[__mm_demo1_rel_many_rel.active]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each(CASE WHEN json_valid([[__mm_demo1.rel_many]]) THEN [[__mm_demo1.rel_many]] ELSE json_array([[__mm_demo1.rel_many]]) END) `__mm_demo1_rel_many_je` LEFT JOIN `users` `__mm_demo1_rel_many` ON [[__mm_demo1_rel_many.id]] = [[__mm_demo1_rel_many_je.value]] LEFT JOIN `demo2` `__mm_demo1_rel_many_rel` ON [[__mm_demo1_rel_many_rel.id]] = [[__mm_demo1_rel_many.rel]] WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__mrTEST}} WHERE NOT (COALESCE([[__mlTEST.multiMatchValue]], '') = COALESCE([[__mrTEST.multiMatchValue]], ''))))) AND COALESCE([[__collection_demo2.active]], '') = COALESCE([[demo1_rel_many_rel.active]], '') AND (((([[demo1_rel_many.email]] > [[__data_users_rel_many.email]]) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo1_rel_many.email]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each(CASE WHEN json_valid([[__mm_demo1.rel_many]]) THEN [[__mm_demo1.rel_many]] ELSE json_array([[__mm_demo1.rel_many]]) END) `__mm_demo1_rel_many_je` LEFT JOIN `users` `__mm_demo1_rel_many` ON [[__mm_demo1_rel_many.id]] = [[__mm_demo1_rel_many_je.value]] WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__mlTEST}} LEFT JOIN (SELECT [[__data_mm_users_rel_many.email]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN `users` `__data_mm_users_rel_many` ON [[__data_mm_users_rel_many.id]] IN ({:p2}, {:p3}) WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__mrTEST}} WHERE NOT ([[__mlTEST.multiMatchValue]] > [[__mrTEST.multiMatchValue]]))))) AND ([[demo1_rel_many.emailVisibility]] = TRUE)))",
|
||||
"SELECT DISTINCT `demo1`.* FROM `demo1` LEFT JOIN json_each(CASE WHEN iif(json_valid([[demo1.rel_many]]), json_type([[demo1.rel_many]])='array', FALSE) THEN [[demo1.rel_many]] ELSE json_array([[demo1.rel_many]]) END) `demo1_rel_many_je` LEFT JOIN `users` `demo1_rel_many` ON [[demo1_rel_many.id]] = [[demo1_rel_many_je.value]] LEFT JOIN `demo2` `demo1_rel_many_rel` ON [[demo1_rel_many_rel.id]] = [[demo1_rel_many.rel]] LEFT JOIN `demo1` `demo1_rel_one` ON [[demo1_rel_one.id]] = [[demo1.rel_one]] LEFT JOIN `demo2` `__collection_demo2` LEFT JOIN `users` `__data_users_rel_many` ON [[__data_users_rel_many.id]] IN ({:p0}, {:p1}) WHERE (((COALESCE([[demo1_rel_many_rel.active]], '') IS NOT COALESCE([[demo1_rel_many.name]], '')) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo1_rel_many_rel.active]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each(CASE WHEN iif(json_valid([[__mm_demo1.rel_many]]), json_type([[__mm_demo1.rel_many]])='array', FALSE) THEN [[__mm_demo1.rel_many]] ELSE json_array([[__mm_demo1.rel_many]]) END) `__mm_demo1_rel_many_je` LEFT JOIN `users` `__mm_demo1_rel_many` ON [[__mm_demo1_rel_many.id]] = [[__mm_demo1_rel_many_je.value]] LEFT JOIN `demo2` `__mm_demo1_rel_many_rel` ON [[__mm_demo1_rel_many_rel.id]] = [[__mm_demo1_rel_many.rel]] WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__mlTEST}} LEFT JOIN (SELECT [[__mm_demo1_rel_many.name]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each(CASE WHEN iif(json_valid([[__mm_demo1.rel_many]]), json_type([[__mm_demo1.rel_many]])='array', FALSE) THEN [[__mm_demo1.rel_many]] ELSE json_array([[__mm_demo1.rel_many]]) END) `__mm_demo1_rel_many_je` LEFT JOIN `users` `__mm_demo1_rel_many` ON [[__mm_demo1_rel_many.id]] = [[__mm_demo1_rel_many_je.value]] WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__mrTEST}} WHERE NOT (COALESCE([[__mlTEST.multiMatchValue]], '') IS NOT COALESCE([[__mrTEST.multiMatchValue]], ''))))) AND COALESCE([[demo1_rel_many_rel.active]], '') = COALESCE([[demo1_rel_many.name]], '') AND (([[demo1_rel_many_rel.title]] LIKE ('%' || [[demo1_rel_one.email]] || '%') ESCAPE '\\') AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo1_rel_many_rel.title]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each(CASE WHEN iif(json_valid([[__mm_demo1.rel_many]]), json_type([[__mm_demo1.rel_many]])='array', FALSE) THEN [[__mm_demo1.rel_many]] ELSE json_array([[__mm_demo1.rel_many]]) END) `__mm_demo1_rel_many_je` LEFT JOIN `users` `__mm_demo1_rel_many` ON [[__mm_demo1_rel_many.id]] = [[__mm_demo1_rel_many_je.value]] LEFT JOIN `demo2` `__mm_demo1_rel_many_rel` ON [[__mm_demo1_rel_many_rel.id]] = [[__mm_demo1_rel_many.rel]] WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] LIKE ('%' || [[demo1_rel_one.email]] || '%') ESCAPE '\\')))) AND ((COALESCE([[__collection_demo2.active]], '') = COALESCE([[demo1_rel_many_rel.active]], '')) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm__collection_demo2.active]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN `demo2` `__mm__collection_demo2` WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__mlTEST}} LEFT JOIN (SELECT [[__mm_demo1_rel_many_rel.active]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each(CASE WHEN iif(json_valid([[__mm_demo1.rel_many]]), json_type([[__mm_demo1.rel_many]])='array', FALSE) THEN [[__mm_demo1.rel_many]] ELSE json_array([[__mm_demo1.rel_many]]) END) `__mm_demo1_rel_many_je` LEFT JOIN `users` `__mm_demo1_rel_many` ON [[__mm_demo1_rel_many.id]] = [[__mm_demo1_rel_many_je.value]] LEFT JOIN `demo2` `__mm_demo1_rel_many_rel` ON [[__mm_demo1_rel_many_rel.id]] = [[__mm_demo1_rel_many.rel]] WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__mrTEST}} WHERE NOT (COALESCE([[__mlTEST.multiMatchValue]], '') = COALESCE([[__mrTEST.multiMatchValue]], ''))))) AND COALESCE([[__collection_demo2.active]], '') = COALESCE([[demo1_rel_many_rel.active]], '') AND (((([[demo1_rel_many.email]] > [[__data_users_rel_many.email]]) AND (NOT EXISTS (SELECT 1 FROM (SELECT [[__mm_demo1_rel_many.email]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN json_each(CASE WHEN iif(json_valid([[__mm_demo1.rel_many]]), json_type([[__mm_demo1.rel_many]])='array', FALSE) THEN [[__mm_demo1.rel_many]] ELSE json_array([[__mm_demo1.rel_many]]) END) `__mm_demo1_rel_many_je` LEFT JOIN `users` `__mm_demo1_rel_many` ON [[__mm_demo1_rel_many.id]] = [[__mm_demo1_rel_many_je.value]] WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__mlTEST}} LEFT JOIN (SELECT [[__data_mm_users_rel_many.email]] as [[multiMatchValue]] FROM `demo1` `__mm_demo1` LEFT JOIN `users` `__data_mm_users_rel_many` ON [[__data_mm_users_rel_many.id]] IN ({:p2}, {:p3}) WHERE `__mm_demo1`.`id` = `demo1`.`id`) {{__mrTEST}} WHERE NOT ([[__mlTEST.multiMatchValue]] > [[__mrTEST.multiMatchValue]]))))) AND ([[demo1_rel_many.emailVisibility]] = TRUE)))",
|
||||
},
|
||||
{
|
||||
"@request.body.arrayable:length fields",
|
||||
@@ -495,14 +495,14 @@ func TestRecordFieldResolverUpdateQuery(t *testing.T) {
|
||||
"self_rel_one.rel_many_cascade.files:length != 7 &&" +
|
||||
"self_rel_one.rel_many_cascade.files:length ?!= 8",
|
||||
false,
|
||||
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN `demo4` `__data_demo4_self_rel_one` ON [[__data_demo4_self_rel_one.id]]={:p0} LEFT JOIN `demo3` `__data_demo3_rel_many_cascade` ON [[__data_demo3_rel_many_cascade.id]] IN ({:p1}, {:p2}) LEFT JOIN `demo3` `__data_demo3_rel_one_cascade` ON [[__data_demo3_rel_one_cascade.id]]={:p3} LEFT JOIN `demo4` `demo4_self_rel_one` ON [[demo4_self_rel_one.id]] = [[demo4.self_rel_one]] LEFT JOIN json_each(CASE WHEN json_valid([[demo4_self_rel_one.rel_many_cascade]]) THEN [[demo4_self_rel_one.rel_many_cascade]] ELSE json_array([[demo4_self_rel_one.rel_many_cascade]]) END) `demo4_self_rel_one_rel_many_cascade_je` LEFT JOIN `demo3` `demo4_self_rel_one_rel_many_cascade` ON [[demo4_self_rel_one_rel_many_cascade.id]] = [[demo4_self_rel_one_rel_many_cascade_je.value]] WHERE (json_array_length(CASE WHEN json_valid([[__data_demo4_self_rel_one.self_rel_many]]) THEN [[__data_demo4_self_rel_one.self_rel_many]] ELSE (CASE WHEN [[__data_demo4_self_rel_one.self_rel_many]] = '' OR [[__data_demo4_self_rel_one.self_rel_many]] IS NULL THEN json_array() ELSE json_array([[__data_demo4_self_rel_one.self_rel_many]]) END) END) > {:TEST} AND json_array_length(CASE WHEN json_valid([[__data_demo4_self_rel_one.self_rel_many]]) THEN [[__data_demo4_self_rel_one.self_rel_many]] ELSE (CASE WHEN [[__data_demo4_self_rel_one.self_rel_many]] = '' OR [[__data_demo4_self_rel_one.self_rel_many]] IS NULL THEN json_array() ELSE json_array([[__data_demo4_self_rel_one.self_rel_many]]) END) END) > {:TEST} AND json_array_length(CASE WHEN json_valid([[__data_demo3_rel_many_cascade.files]]) THEN [[__data_demo3_rel_many_cascade.files]] ELSE (CASE WHEN [[__data_demo3_rel_many_cascade.files]] = '' OR [[__data_demo3_rel_many_cascade.files]] IS NULL THEN json_array() ELSE json_array([[__data_demo3_rel_many_cascade.files]]) END) END) < {:TEST} AND ((json_array_length(CASE WHEN json_valid([[__data_demo3_rel_many_cascade.files]]) THEN [[__data_demo3_rel_many_cascade.files]] ELSE (CASE WHEN [[__data_demo3_rel_many_cascade.files]] = '' OR [[__data_demo3_rel_many_cascade.files]] IS NULL THEN json_array() ELSE json_array([[__data_demo3_rel_many_cascade.files]]) END) END) < {:TEST}) AND (NOT EXISTS (SELECT 1 FROM (SELECT json_array_length(CASE WHEN json_valid([[__data_mm_demo3_rel_many_cascade.files]]) THEN [[__data_mm_demo3_rel_many_cascade.files]] ELSE (CASE WHEN [[__data_mm_demo3_rel_many_cascade.files]] = '' OR [[__data_mm_demo3_rel_many_cascade.files]] IS NULL THEN json_array() ELSE json_array([[__data_mm_demo3_rel_many_cascade.files]]) END) END) as [[multiMatchValue]] FROM `demo4` `__mm_demo4` LEFT JOIN `demo3` `__data_mm_demo3_rel_many_cascade` ON [[__data_mm_demo3_rel_many_cascade.id]] IN ({:p8}, {:p9}) WHERE `__mm_demo4`.`id` = `demo4`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] < {:TEST})))) AND json_array_length(CASE WHEN json_valid([[__data_demo3_rel_one_cascade.files]]) THEN [[__data_demo3_rel_one_cascade.files]] ELSE (CASE WHEN [[__data_demo3_rel_one_cascade.files]] = '' OR [[__data_demo3_rel_one_cascade.files]] IS NULL THEN json_array() ELSE json_array([[__data_demo3_rel_one_cascade.files]]) END) END) < {:TEST} AND json_array_length(CASE WHEN json_valid([[demo4_self_rel_one.self_rel_many]]) THEN [[demo4_self_rel_one.self_rel_many]] ELSE (CASE WHEN [[demo4_self_rel_one.self_rel_many]] = '' OR [[demo4_self_rel_one.self_rel_many]] IS NULL THEN json_array() ELSE json_array([[demo4_self_rel_one.self_rel_many]]) END) END) = {:TEST} AND json_array_length(CASE WHEN json_valid([[demo4_self_rel_one.self_rel_many]]) THEN [[demo4_self_rel_one.self_rel_many]] ELSE (CASE WHEN [[demo4_self_rel_one.self_rel_many]] = '' OR [[demo4_self_rel_one.self_rel_many]] IS NULL THEN json_array() ELSE json_array([[demo4_self_rel_one.self_rel_many]]) END) END) = {:TEST} AND ((json_array_length(CASE WHEN json_valid([[demo4_self_rel_one_rel_many_cascade.files]]) THEN [[demo4_self_rel_one_rel_many_cascade.files]] ELSE (CASE WHEN [[demo4_self_rel_one_rel_many_cascade.files]] = '' OR [[demo4_self_rel_one_rel_many_cascade.files]] IS NULL THEN json_array() ELSE json_array([[demo4_self_rel_one_rel_many_cascade.files]]) END) END) IS NOT {:TEST}) AND (NOT EXISTS (SELECT 1 FROM (SELECT json_array_length(CASE WHEN json_valid([[__mm_demo4_self_rel_one_rel_many_cascade.files]]) THEN [[__mm_demo4_self_rel_one_rel_many_cascade.files]] ELSE (CASE WHEN [[__mm_demo4_self_rel_one_rel_many_cascade.files]] = '' OR [[__mm_demo4_self_rel_one_rel_many_cascade.files]] IS NULL THEN json_array() ELSE json_array([[__mm_demo4_self_rel_one_rel_many_cascade.files]]) END) END) as [[multiMatchValue]] FROM `demo4` `__mm_demo4` LEFT JOIN `demo4` `__mm_demo4_self_rel_one` ON [[__mm_demo4_self_rel_one.id]] = [[__mm_demo4.self_rel_one]] LEFT JOIN json_each(CASE WHEN json_valid([[__mm_demo4_self_rel_one.rel_many_cascade]]) THEN [[__mm_demo4_self_rel_one.rel_many_cascade]] ELSE json_array([[__mm_demo4_self_rel_one.rel_many_cascade]]) END) `__mm_demo4_self_rel_one_rel_mLine truncated
|
||||
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN `demo4` `__data_demo4_self_rel_one` ON [[__data_demo4_self_rel_one.id]]={:p0} LEFT JOIN `demo3` `__data_demo3_rel_many_cascade` ON [[__data_demo3_rel_many_cascade.id]] IN ({:p1}, {:p2}) LEFT JOIN `demo3` `__data_demo3_rel_one_cascade` ON [[__data_demo3_rel_one_cascade.id]]={:p3} LEFT JOIN `demo4` `demo4_self_rel_one` ON [[demo4_self_rel_one.id]] = [[demo4.self_rel_one]] LEFT JOIN json_each(CASE WHEN iif(json_valid([[demo4_self_rel_one.rel_many_cascade]]), json_type([[demo4_self_rel_one.rel_many_cascade]])='array', FALSE) THEN [[demo4_self_rel_one.rel_many_cascade]] ELSE json_array([[demo4_self_rel_one.rel_many_cascade]]) END) `demo4_self_rel_one_rel_many_cascade_je` LEFT JOIN `demo3` `demo4_self_rel_one_rel_many_cascade` ON [[demo4_self_rel_one_rel_many_cascade.id]] = [[demo4_self_rel_one_rel_many_cascade_je.value]] WHERE (json_array_length(CASE WHEN iif(json_valid([[__data_demo4_self_rel_one.self_rel_many]]), json_type([[__data_demo4_self_rel_one.self_rel_many]])='array', FALSE) THEN [[__data_demo4_self_rel_one.self_rel_many]] ELSE (CASE WHEN [[__data_demo4_self_rel_one.self_rel_many]] = '' OR [[__data_demo4_self_rel_one.self_rel_many]] IS NULL THEN json_array() ELSE json_array([[__data_demo4_self_rel_one.self_rel_many]]) END) END) > {:TEST} AND json_array_length(CASE WHEN iif(json_valid([[__data_demo4_self_rel_one.self_rel_many]]), json_type([[__data_demo4_self_rel_one.self_rel_many]])='array', FALSE) THEN [[__data_demo4_self_rel_one.self_rel_many]] ELSE (CASE WHEN [[__data_demo4_self_rel_one.self_rel_many]] = '' OR [[__data_demo4_self_rel_one.self_rel_many]] IS NULL THEN json_array() ELSE json_array([[__data_demo4_self_rel_one.self_rel_many]]) END) END) > {:TEST} AND json_array_length(CASE WHEN iif(json_valid([[__data_demo3_rel_many_cascade.files]]), json_type([[__data_demo3_rel_many_cascade.files]])='array', FALSE) THEN [[__data_demo3_rel_many_cascade.files]] ELSE (CASE WHEN [[__data_demo3_rel_many_cascade.files]] = '' OR [[__data_demo3_rel_many_cascade.files]] IS NULL THEN json_array() ELSE json_array([[__data_demo3_rel_many_cascade.files]]) END) END) < {:TEST} AND ((json_array_length(CASE WHEN iif(json_valid([[__data_demo3_rel_many_cascade.files]]), json_type([[__data_demo3_rel_many_cascade.files]])='array', FALSE) THEN [[__data_demo3_rel_many_cascade.files]] ELSE (CASE WHEN [[__data_demo3_rel_many_cascade.files]] = '' OR [[__data_demo3_rel_many_cascade.files]] IS NULL THEN json_array() ELSE json_array([[__data_demo3_rel_many_cascade.files]]) END) END) < {:TEST}) AND (NOT EXISTS (SELECT 1 FROM (SELECT json_array_length(CASE WHEN iif(json_valid([[__data_mm_demo3_rel_many_cascade.files]]), json_type([[__data_mm_demo3_rel_many_cascade.files]])='array', FALSE) THEN [[__data_mm_demo3_rel_many_cascade.files]] ELSE (CASE WHEN [[__data_mm_demo3_rel_many_cascade.files]] = '' OR [[__data_mm_demo3_rel_many_cascade.files]] IS NULL THEN json_array() ELSE json_array([[__data_mm_demo3_rel_many_cascade.files]]) END) END) as [[multiMatchValue]] FROM `demo4` `__mm_demo4` LEFT JOIN `demo3` `__data_mm_demo3_rel_many_cascade` ON [[__data_mm_demo3_rel_many_cascade.id]] IN ({:p8}, {:p9}) WHERE `__mm_demo4`.`id` = `demo4`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] < {:TEST})))) AND json_array_length(CASE WHEN iif(json_valid([[__data_demo3_rel_one_cascade.files]]), json_type([[__data_demo3_rel_one_cascade.files]])='array', FALSE) THEN [[__data_demo3_rel_one_cascade.files]] ELSE (CASE WHEN [[__data_demo3_rel_one_cascade.files]] = '' OR [[__data_demo3_rel_one_cascade.files]] IS NULL THEN json_array() ELSE json_array([[__data_demo3_rel_one_cascade.files]]) END) END) < {:TEST} AND json_array_length(CASE WHEN iif(json_valid([[demo4_self_rel_one.self_rel_many]]), json_type([[demo4_self_rel_one.self_rel_many]])='array', FALSE) THEN [[demo4_self_rel_one.self_rel_many]] ELSE (CASE WHEN [[demo4_self_rel_one.self_rel_many]] = '' OR [[demo4_self_rel_one.self_rel_many]] IS NULL THEN json_array() ELSE json_array([[demo4_self_rel_one.self_rel_many]]) END) END) = {:TEST} AND json_array_length(CASE WHEN iif(json_valid([[demo4_self_rel_one.self_rel_many]]), json_type([[demo4_self_rel_one.self_rel_many]])='array', FALSE) THEN [[demo4_self_rel_one.self_rel_many]] ELSE (CASE WHEN [[demo4_self_rel_one.self_rel_many]] = '' OR [[demo4_self_rel_one.self_rel_many]] IS NULL THEN json_array() ELSE json_array([[demo4_self_rel_one.self_rel_many]]) END) END) = {:TEST} AND ((json_array_length(CASE WHEN iif(json_valid([[demo4_self_rel_one_rel_many_cascade.files]]), json_type([[demo4_self_rel_one_rel_many_cascade.files]])='array', FALSE) THEN [[demo4_self_rel_one_rel_many_cascade.files]] ELSE (CASE WHEN [[demo4_self_rel_one_rel_many_cascade.files]] = '' OR [[demo4_self_rel_one_rel_many_cascade.files]] IS NULL THEN json_array() ELSE json_array([[demo4_self_rel_one_rel_many_cascade.files]]) END) END) IS NOT {:TEST}) AND (NOT EXISTS (SELECT 1 FROM (SELECT json_array_length(CASE WHEN iif(json_vLine truncated
|
||||
},
|
||||
{
|
||||
"json_extract and json_array_length COALESCE equal normalizations",
|
||||
"demo4",
|
||||
"json_object.a.b = '' && self_rel_many:length != 2 && json_object.a.b > 3 && self_rel_many:length <= 4",
|
||||
false,
|
||||
"SELECT `demo4`.* FROM `demo4` WHERE ((CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$.a.b') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb.a.b') END) IS {:TEST} AND json_array_length(CASE WHEN json_valid([[demo4.self_rel_many]]) THEN [[demo4.self_rel_many]] ELSE (CASE WHEN [[demo4.self_rel_many]] = '' OR [[demo4.self_rel_many]] IS NULL THEN json_array() ELSE json_array([[demo4.self_rel_many]]) END) END) IS NOT {:TEST} AND (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$.a.b') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb.a.b') END) > {:TEST} AND json_array_length(CASE WHEN json_valid([[demo4.self_rel_many]]) THEN [[demo4.self_rel_many]] ELSE (CASE WHEN [[demo4.self_rel_many]] = '' OR [[demo4.self_rel_many]] IS NULL THEN json_array() ELSE json_array([[demo4.self_rel_many]]) END) END) <= {:TEST})",
|
||||
"SELECT `demo4`.* FROM `demo4` WHERE ((CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$.a.b') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb.a.b') END) IS {:TEST} AND json_array_length(CASE WHEN iif(json_valid([[demo4.self_rel_many]]), json_type([[demo4.self_rel_many]])='array', FALSE) THEN [[demo4.self_rel_many]] ELSE (CASE WHEN [[demo4.self_rel_many]] = '' OR [[demo4.self_rel_many]] IS NULL THEN json_array() ELSE json_array([[demo4.self_rel_many]]) END) END) IS NOT {:TEST} AND (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$.a.b') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb.a.b') END) > {:TEST} AND json_array_length(CASE WHEN iif(json_valid([[demo4.self_rel_many]]), json_type([[demo4.self_rel_many]])='array', FALSE) THEN [[demo4.self_rel_many]] ELSE (CASE WHEN [[demo4.self_rel_many]] = '' OR [[demo4.self_rel_many]] IS NULL THEN json_array() ELSE json_array([[demo4.self_rel_many]]) END) END) <= {:TEST})",
|
||||
},
|
||||
{
|
||||
"json field equal normalization checks",
|
||||
@@ -516,7 +516,7 @@ func TestRecordFieldResolverUpdateQuery(t *testing.T) {
|
||||
"self_rel_many.json_object = '' || null = self_rel_many.json_object ||" +
|
||||
"self_rel_many.json_object = self_rel_many.json_object",
|
||||
false,
|
||||
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN json_each(CASE WHEN json_valid([[demo4.self_rel_many]]) THEN [[demo4.self_rel_many]] ELSE json_array([[demo4.self_rel_many]]) END) `demo4_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many` ON [[demo4_self_rel_many.id]] = [[demo4_self_rel_many_je.value]] WHERE ((CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS {:TEST} OR (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS NOT {:TEST} OR {:TEST} IS (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR {:TEST} IS NOT (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS NULL OR (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS NOT NULL OR NULL IS (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR NULL IS NOT (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS 1 OR (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS NOT 1 OR 1 IS (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR 1 IS NOT (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS NOT (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS [[demo4.title]] OR [[demo4.title]] IS NOT (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR (((CASE WHEN json_valid([[demo4_self_rel_many.json_object]]) THEN JSON_EXTRACT([[demo4_self_rel_many.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4_self_rel_many.json_object]]), '$.pb') END) IS {:TEST}) AND (NOT EXISTS (SELECT 1 FROM (SELECT (CASE WHEN json_valid([[__mm_demo4_self_rel_many.json_object]]) THEN JSON_EXTRACT([[__mm_demo4_self_rel_many.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[__mm_demo4_self_rel_many.json_object]]), '$.pb') END) as [[multiMatchValue]] FROM `demo4` `__mm_demo4` LEFT JOIN json_each(CASE WHEN json_valid([[__mm_demo4.self_rel_many]]) THEN [[__mm_demo4.self_rel_many]] ELSE json_array([[__mm_demo4.self_rel_many]]) END) `__mm_demo4_self_rel_many_je` LEFT JOIN `demo4` `__mm_demo4_self_rel_many` ON [[__mm_demo4_self_rel_many.id]] = [[__mm_demo4_self_rel_many_je.value]] WHERE `__mm_demo4`.`id` = `demo4`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] IS {:TEST})))) OR ((NULL IS (CASE WHEN json_valid([[demo4_self_rel_many.json_object]]) THEN JSON_EXTRACT([[demo4_self_rel_many.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4_self_rel_many.json_object]]), '$.pb') END)) AND (NOT EXISTS (SELECT 1 FROM (SELECT (CASE WHEN json_valid([[__mm_demo4_self_rel_many.json_object]]) THEN JSON_EXTRACT([[__mm_demo4_self_rel_many.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[__mm_demo4_self_rel_many.json_object]]), '$.pb') END) as [[multiMatchValue]] FROM `demo4` `__mm_demo4` LEFT JOIN json_each(CASE WHEN jsonLine truncated
|
||||
"SELECT DISTINCT `demo4`.* FROM `demo4` LEFT JOIN json_each(CASE WHEN iif(json_valid([[demo4.self_rel_many]]), json_type([[demo4.self_rel_many]])='array', FALSE) THEN [[demo4.self_rel_many]] ELSE json_array([[demo4.self_rel_many]]) END) `demo4_self_rel_many_je` LEFT JOIN `demo4` `demo4_self_rel_many` ON [[demo4_self_rel_many.id]] = [[demo4_self_rel_many_je.value]] WHERE ((CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS {:TEST} OR (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS NOT {:TEST} OR {:TEST} IS (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR {:TEST} IS NOT (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS NULL OR (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS NOT NULL OR NULL IS (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR NULL IS NOT (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS 1 OR (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS NOT 1 OR 1 IS (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR 1 IS NOT (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS NOT (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) IS [[demo4.title]] OR [[demo4.title]] IS NOT (CASE WHEN json_valid([[demo4.json_object]]) THEN JSON_EXTRACT([[demo4.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4.json_object]]), '$.pb') END) OR (((CASE WHEN json_valid([[demo4_self_rel_many.json_object]]) THEN JSON_EXTRACT([[demo4_self_rel_many.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4_self_rel_many.json_object]]), '$.pb') END) IS {:TEST}) AND (NOT EXISTS (SELECT 1 FROM (SELECT (CASE WHEN json_valid([[__mm_demo4_self_rel_many.json_object]]) THEN JSON_EXTRACT([[__mm_demo4_self_rel_many.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[__mm_demo4_self_rel_many.json_object]]), '$.pb') END) as [[multiMatchValue]] FROM `demo4` `__mm_demo4` LEFT JOIN json_each(CASE WHEN iif(json_valid([[__mm_demo4.self_rel_many]]), json_type([[__mm_demo4.self_rel_many]])='array', FALSE) THEN [[__mm_demo4.self_rel_many]] ELSE json_array([[__mm_demo4.self_rel_many]]) END) `__mm_demo4_self_rel_many_je` LEFT JOIN `demo4` `__mm_demo4_self_rel_many` ON [[__mm_demo4_self_rel_many.id]] = [[__mm_demo4_self_rel_many_je.value]] WHERE `__mm_demo4`.`id` = `demo4`.`id`) {{__smTEST}} WHERE NOT ([[__smTEST.multiMatchValue]] IS {:TEST})))) OR ((NULL IS (CASE WHEN json_valid([[demo4_self_rel_many.json_object]]) THEN JSON_EXTRACT([[demo4_self_rel_many.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[demo4_self_rel_many.json_object]]), '$.pb') END)) AND (NOT EXISTS (SELECT 1 FROM (SELECT (CASE WHEN json_valid([[__mm_demo4_self_rel_many.json_object]]) THEN JSON_EXTRACT([[__mm_demo4_self_rel_many.json_object]], '$') ELSE JSON_EXTRACT(json_object('pb', [[__mm_demo4_self_rel_Line truncated
|
||||
},
|
||||
{
|
||||
"geoPoint props access",
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
validation "github.com/go-ozzo/ozzo-validation/v4"
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/core/validators"
|
||||
"github.com/pocketbase/pocketbase/tools/dbutils"
|
||||
"github.com/pocketbase/pocketbase/tools/filesystem"
|
||||
"github.com/pocketbase/pocketbase/tools/hook"
|
||||
"github.com/pocketbase/pocketbase/tools/inflector"
|
||||
@@ -1530,8 +1531,8 @@ func cascadeRecordDelete(app App, mainRecord *Record, refs map[*Collection][]Fie
|
||||
query.AndWhere(dbx.HashExp{prefixedFieldName: mainRecord.Id})
|
||||
} else {
|
||||
query.AndWhere(dbx.Exists(dbx.NewExp(fmt.Sprintf(
|
||||
`SELECT 1 FROM json_each(CASE WHEN json_valid([[%s]]) THEN [[%s]] ELSE json_array([[%s]]) END) {{__je__}} WHERE [[__je__.value]]={:jevalue}`,
|
||||
prefixedFieldName, prefixedFieldName, prefixedFieldName,
|
||||
`SELECT 1 FROM %s {{__je__}} WHERE [[__je__.value]]={:jevalue}`,
|
||||
dbutils.JSONEach(prefixedFieldName),
|
||||
), dbx.Params{
|
||||
"jevalue": mainRecord.Id,
|
||||
})))
|
||||
|
||||
@@ -2254,13 +2254,13 @@ func TestRecordDelete(t *testing.T) {
|
||||
app.NonconcurrentDB().(*dbx.DB).QueryLogFunc = func(ctx context.Context, t time.Duration, sql string, rows *sql.Rows, err error) {
|
||||
calledQueries = append(calledQueries, sql)
|
||||
}
|
||||
app.DB().(*dbx.DB).QueryLogFunc = func(ctx context.Context, t time.Duration, sql string, rows *sql.Rows, err error) {
|
||||
app.ConcurrentDB().(*dbx.DB).QueryLogFunc = func(ctx context.Context, t time.Duration, sql string, rows *sql.Rows, err error) {
|
||||
calledQueries = append(calledQueries, sql)
|
||||
}
|
||||
app.NonconcurrentDB().(*dbx.DB).ExecLogFunc = func(ctx context.Context, t time.Duration, sql string, result sql.Result, err error) {
|
||||
calledQueries = append(calledQueries, sql)
|
||||
}
|
||||
app.DB().(*dbx.DB).ExecLogFunc = func(ctx context.Context, t time.Duration, sql string, result sql.Result, err error) {
|
||||
app.ConcurrentDB().(*dbx.DB).ExecLogFunc = func(ctx context.Context, t time.Duration, sql string, result sql.Result, err error) {
|
||||
calledQueries = append(calledQueries, sql)
|
||||
}
|
||||
rec3, _ := app.FindRecordById("users", "oap640cot4yru2s")
|
||||
@@ -2280,7 +2280,7 @@ func TestRecordDelete(t *testing.T) {
|
||||
}
|
||||
// ensure that the json rel fields were prefixed
|
||||
joinedQueries := strings.Join(calledQueries, " ")
|
||||
expectedRelManyPart := "SELECT `demo1`.* FROM `demo1` WHERE EXISTS (SELECT 1 FROM json_each(CASE WHEN json_valid([[demo1.rel_many]]) THEN [[demo1.rel_many]] ELSE json_array([[demo1.rel_many]]) END) {{__je__}} WHERE [[__je__.value]]='"
|
||||
expectedRelManyPart := "SELECT `demo1`.* FROM `demo1` WHERE EXISTS (SELECT 1 FROM json_each(CASE WHEN iif(json_valid([[demo1.rel_many]]), json_type([[demo1.rel_many]])='array', FALSE) THEN [[demo1.rel_many]] ELSE json_array([[demo1.rel_many]]) END) {{__je__}} WHERE [[__je__.value]]='"
|
||||
if !strings.Contains(joinedQueries, expectedRelManyPart) {
|
||||
t.Fatalf("(rec3) Expected the cascade delete to call the query \n%v, got \n%v", expectedRelManyPart, calledQueries)
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ func (app *BaseApp) RecordQuery(collectionModelOrIdentifier any) *dbx.SelectQuer
|
||||
tableName = "@@__invalidCollectionModelOrIdentifier"
|
||||
}
|
||||
|
||||
query := app.DB().Select(app.DB().QuoteSimpleColumnName(tableName) + ".*").From(tableName)
|
||||
query := app.ConcurrentDB().Select(app.ConcurrentDB().QuoteSimpleColumnName(tableName) + ".*").From(tableName)
|
||||
|
||||
// in case of an error attach a new context and cancel it immediately with the error
|
||||
if collectionErr != nil {
|
||||
|
||||
@@ -103,7 +103,7 @@ func (app *BaseApp) expandRecords(records []*Record, expandPath string, fetchFun
|
||||
// add the related id(s) as a dynamic relation field value to
|
||||
// allow further expand checks at later stage in a more unified manner
|
||||
prepErr := func() error {
|
||||
q := app.DB().Select("id").
|
||||
q := app.ConcurrentDB().Select("id").
|
||||
From(indirectRel.Name).
|
||||
Limit(1000) // the limit is arbitrary chosen and may change in the future
|
||||
|
||||
|
||||
@@ -227,7 +227,7 @@ func (form *RecordUpsert) DrySubmit(callback func(txApp core.App, drySavedRecord
|
||||
|
||||
app := form.app.UnsafeWithoutHooks()
|
||||
|
||||
_, isTransactional := app.DB().(*dbx.Tx)
|
||||
isTransactional := app.IsTransactional()
|
||||
if !isTransactional {
|
||||
return app.RunInTransaction(func(txApp core.App) error {
|
||||
tx, ok := txApp.DB().(*dbx.Tx)
|
||||
|
||||
@@ -9,19 +9,19 @@ require (
|
||||
github.com/dop251/goja_nodejs v0.0.0-20250314160716-c55ecee183c0
|
||||
github.com/fatih/color v1.18.0
|
||||
github.com/fsnotify/fsnotify v1.7.0
|
||||
github.com/gabriel-vasile/mimetype v1.4.8
|
||||
github.com/gabriel-vasile/mimetype v1.4.9
|
||||
github.com/ganigeorgiev/fexpr v0.5.0
|
||||
github.com/go-ozzo/ozzo-validation/v4 v4.3.0
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2
|
||||
github.com/pocketbase/dbx v1.11.0
|
||||
github.com/pocketbase/tygoja v0.0.0-20250103200817-ca580d8c5119
|
||||
github.com/spf13/cast v1.7.1
|
||||
github.com/spf13/cast v1.8.0
|
||||
github.com/spf13/cobra v1.9.1
|
||||
golang.org/x/crypto v0.37.0
|
||||
golang.org/x/image v0.26.0
|
||||
golang.org/x/net v0.39.0
|
||||
golang.org/x/oauth2 v0.29.0
|
||||
golang.org/x/sync v0.13.0
|
||||
golang.org/x/crypto v0.38.0
|
||||
golang.org/x/image v0.27.0
|
||||
golang.org/x/net v0.40.0
|
||||
golang.org/x/oauth2 v0.30.0
|
||||
golang.org/x/sync v0.14.0
|
||||
modernc.org/sqlite v1.37.0
|
||||
)
|
||||
|
||||
@@ -39,11 +39,11 @@ require (
|
||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/spf13/pflag v1.0.6 // indirect
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect
|
||||
golang.org/x/mod v0.24.0 // indirect
|
||||
golang.org/x/sys v0.32.0 // indirect
|
||||
golang.org/x/text v0.24.0 // indirect
|
||||
golang.org/x/tools v0.32.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/text v0.25.0 // indirect
|
||||
golang.org/x/tools v0.33.0 // indirect
|
||||
modernc.org/libc v1.62.1 // indirect
|
||||
modernc.org/mathutil v1.7.1 // indirect
|
||||
modernc.org/memory v1.9.1 // indirect
|
||||
|
||||
@@ -26,8 +26,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
|
||||
github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
|
||||
github.com/ganigeorgiev/fexpr v0.5.0 h1:XA9JxtTE/Xm+g/JFI6RfZEHSiQlk+1glLvRK1Lpv/Tk=
|
||||
github.com/ganigeorgiev/fexpr v0.5.0/go.mod h1:RyGiGqmeXhEQ6+mlGdnUleLHgtzzu/VGO2WtJkF5drE=
|
||||
github.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es=
|
||||
@@ -68,8 +68,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qq
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
|
||||
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cast v1.8.0 h1:gEN9K4b8Xws4EX0+a0reLmhq8moKn7ntRlQYgjPeCDk=
|
||||
github.com/spf13/cast v1.8.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
||||
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
@@ -78,33 +78,33 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
||||
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM=
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8=
|
||||
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
||||
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI=
|
||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.26.0 h1:4XjIFEZWQmCZi6Wv8BoxsDhRU3RVnLX04dToTDAEPlY=
|
||||
golang.org/x/image v0.26.0/go.mod h1:lcxbMFAovzpnJxzXS3nyL83K27tmqtKzIJpctK8YO5c=
|
||||
golang.org/x/image v0.27.0 h1:C8gA4oWU/tKkdCfYT6T2u4faJu3MeNS5O8UPWlPF61w=
|
||||
golang.org/x/image v0.27.0/go.mod h1:xbdrClrAUway1MUTEZDq9mz/UpRwYAkFFNUslZtcB+g=
|
||||
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
||||
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
|
||||
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
|
||||
golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
|
||||
golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
||||
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
|
||||
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
||||
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
|
||||
golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
|
||||
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
|
||||
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
|
||||
google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
+5100
-4797
File diff suppressed because it is too large.
Load diff
@@ -8,9 +8,11 @@ import (
|
||||
// JSONEach returns JSON_EACH SQLite string expression with
|
||||
// some normalizations for non-json columns.
|
||||
func JSONEach(column string) string {
|
||||
// note: we are not using the new and shorter "if(x,y)" syntax for
|
||||
// compatability with custom drivers that use older SQLite version
|
||||
return fmt.Sprintf(
|
||||
`json_each(CASE WHEN json_valid([[%s]]) THEN [[%s]] ELSE json_array([[%s]]) END)`,
|
||||
column, column, column,
|
||||
`json_each(CASE WHEN iif(json_valid([[%s]]), json_type([[%s]])='array', FALSE) THEN [[%s]] ELSE json_array([[%s]]) END)`,
|
||||
column, column, column, column,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -21,9 +23,11 @@ func JSONEach(column string) string {
|
||||
//
|
||||
// Returns 0 for empty string or NULL column values.
|
||||
func JSONArrayLength(column string) string {
|
||||
// note: we are not using the new and shorter "if(x,y)" syntax for
|
||||
// compatability with custom drivers that use older SQLite version
|
||||
return fmt.Sprintf(
|
||||
`json_array_length(CASE WHEN json_valid([[%s]]) THEN [[%s]] ELSE (CASE WHEN [[%s]] = '' OR [[%s]] IS NULL THEN json_array() ELSE json_array([[%s]]) END) END)`,
|
||||
column, column, column, column, column,
|
||||
`json_array_length(CASE WHEN iif(json_valid([[%s]]), json_type([[%s]])='array', FALSE) THEN [[%s]] ELSE (CASE WHEN [[%s]] = '' OR [[%s]] IS NULL THEN json_array() ELSE json_array([[%s]]) END) END)`,
|
||||
column, column, column, column, column, column,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
func TestJSONEach(t *testing.T) {
|
||||
result := dbutils.JSONEach("a.b")
|
||||
|
||||
expected := "json_each(CASE WHEN json_valid([[a.b]]) THEN [[a.b]] ELSE json_array([[a.b]]) END)"
|
||||
expected := "json_each(CASE WHEN iif(json_valid([[a.b]]), json_type([[a.b]])='array', FALSE) THEN [[a.b]] ELSE json_array([[a.b]]) END)"
|
||||
|
||||
if result != expected {
|
||||
t.Fatalf("Expected\n%v\ngot\n%v", expected, result)
|
||||
@@ -19,7 +19,7 @@ func TestJSONEach(t *testing.T) {
|
||||
func TestJSONArrayLength(t *testing.T) {
|
||||
result := dbutils.JSONArrayLength("a.b")
|
||||
|
||||
expected := "json_array_length(CASE WHEN json_valid([[a.b]]) THEN [[a.b]] ELSE (CASE WHEN [[a.b]] = '' OR [[a.b]] IS NULL THEN json_array() ELSE json_array([[a.b]]) END) END)"
|
||||
expected := "json_array_length(CASE WHEN iif(json_valid([[a.b]]), json_type([[a.b]])='array', FALSE) THEN [[a.b]] ELSE (CASE WHEN [[a.b]] = '' OR [[a.b]] IS NULL THEN json_array() ELSE json_array([[a.b]]) END) END)"
|
||||
|
||||
if result != expected {
|
||||
t.Fatalf("Expected\n%v\ngot\n%v", expected, result)
|
||||
|
||||
@@ -699,6 +699,8 @@ func (b *Bucket) Delete(ctx context.Context, key string) (err error) {
|
||||
}
|
||||
|
||||
// Close releases any resources used for the bucket.
|
||||
//
|
||||
// @todo Consider removing it.
|
||||
func (b *Bucket) Close() error {
|
||||
b.mu.Lock()
|
||||
prev := b.closed
|
||||
|
||||
@@ -40,8 +40,7 @@ type Driver interface {
|
||||
NormalizeError(err error) error
|
||||
|
||||
// Attributes returns attributes for the blob. If the specified object does
|
||||
// not exist, Attributes must return an error for which ErrorCode returns
|
||||
// gcerrors.NotFound.
|
||||
// not exist, Attributes must return an error for which ErrorCode returns ErrNotFound.
|
||||
// The portable type will not modify the returned Attributes.
|
||||
Attributes(ctx context.Context, key string) (*Attributes, error)
|
||||
|
||||
@@ -57,8 +56,7 @@ type Driver interface {
|
||||
// NewRangeReader returns a Reader that reads part of an object, reading at
|
||||
// most length bytes starting at the given offset. If length is negative, it
|
||||
// will read until the end of the object. If the specified object does not
|
||||
// exist, NewRangeReader must return an error for which ErrorCode returns
|
||||
// gcerrors.NotFound.
|
||||
// exist, NewRangeReader must return an error for which ErrorCode returns ErrNotFound.
|
||||
// opts is guaranteed to be non-nil.
|
||||
//
|
||||
// The returned Reader *may* also implement Downloader if the underlying
|
||||
@@ -90,7 +88,7 @@ type Driver interface {
|
||||
// Copy copies the object associated with srcKey to dstKey.
|
||||
//
|
||||
// If the source object does not exist, Copy must return an error for which
|
||||
// ErrorCode returns gcerrors.NotFound.
|
||||
// ErrorCode returns ErrNotFound.
|
||||
//
|
||||
// If the destination object already exists, it should be overwritten.
|
||||
//
|
||||
@@ -98,8 +96,7 @@ type Driver interface {
|
||||
Copy(ctx context.Context, dstKey, srcKey string) error
|
||||
|
||||
// Delete deletes the object associated with key. If the specified object does
|
||||
// not exist, Delete must return an error for which ErrorCode returns
|
||||
// gcerrors.NotFound.
|
||||
// not exist, Delete must return an error for which ErrorCode returns ErrNotFound.
|
||||
Delete(ctx context.Context, key string) error
|
||||
|
||||
// Close cleans up any resources used by the Bucket. Once Close is called,
|
||||
|
||||
@@ -176,6 +176,18 @@ func (r *bytesReadSeekCloser) Close() error {
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
var _ FileReader = (openFuncAsReader)(nil)
|
||||
|
||||
// openFuncAsReader defines a FileReader from a bare Open function.
|
||||
type openFuncAsReader func() (io.ReadSeekCloser, error)
|
||||
|
||||
// Open implements the [filesystem.FileReader] interface.
|
||||
func (r openFuncAsReader) Open() (io.ReadSeekCloser, error) {
|
||||
return r()
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
var extInvalidCharsRegex = regexp.MustCompile(`[^\w\.\*\-\+\=\#]+`)
|
||||
|
||||
const randomAlphabet = "abcdefghijklmnopqrstuvwxyz0123456789"
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
@@ -15,6 +16,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/disintegration/imaging"
|
||||
"github.com/fatih/color"
|
||||
"github.com/gabriel-vasile/mimetype"
|
||||
"github.com/pocketbase/pocketbase/tools/filesystem/blob"
|
||||
"github.com/pocketbase/pocketbase/tools/filesystem/internal/fileblob"
|
||||
@@ -29,6 +31,8 @@ import (
|
||||
// note: the same as blob.ErrNotFound for backward compatibility with earlier versions
|
||||
var ErrNotFound = blob.ErrNotFound
|
||||
|
||||
const metadataOriginalName = "original-filename"
|
||||
|
||||
type System struct {
|
||||
ctx context.Context
|
||||
bucket *blob.Bucket
|
||||
@@ -107,15 +111,60 @@ func (s *System) Attributes(fileKey string) (*blob.Attributes, error) {
|
||||
return s.bucket.Attributes(s.ctx, fileKey)
|
||||
}
|
||||
|
||||
// GetFile returns a file content reader for the given fileKey.
|
||||
// GetReader returns a file content reader for the given fileKey.
|
||||
//
|
||||
// NB! Make sure to call Close() on the file after you are done working with it.
|
||||
//
|
||||
// If the file doesn't exist returns ErrNotFound.
|
||||
func (s *System) GetFile(fileKey string) (*blob.Reader, error) {
|
||||
func (s *System) GetReader(fileKey string) (*blob.Reader, error) {
|
||||
return s.bucket.NewReader(s.ctx, fileKey)
|
||||
}
|
||||
|
||||
// Deprecated: Please use GetReader(fileKey) instead.
|
||||
func (s *System) GetFile(fileKey string) (*blob.Reader, error) {
|
||||
color.Yellow("Deprecated: Please replace GetFile with GetReader.")
|
||||
return s.GetReader(fileKey)
|
||||
}
|
||||
|
||||
// GetReuploadableFile constructs a new reuploadable File value
|
||||
// from the associated fileKey blob.Reader.
|
||||
//
|
||||
// If preserveName is false then the returned File.Name will have
|
||||
// a new randomly generated suffix, otherwise it will reuse the original one.
|
||||
//
|
||||
// This method could be useful in case you want to clone an existing
|
||||
// Record file and assign it to a new Record (e.g. in a Record duplicate action).
|
||||
//
|
||||
// If you simply want to copy an existing file to a new location you
|
||||
// could check the Copy(srcKey, dstKey) method.
|
||||
func (s *System) GetReuploadableFile(fileKey string, preserveName bool) (*File, error) {
|
||||
attrs, err := s.Attributes(fileKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
name := path.Base(fileKey)
|
||||
originalName := attrs.Metadata[metadataOriginalName]
|
||||
if originalName == "" {
|
||||
originalName = name
|
||||
}
|
||||
|
||||
file := &File{}
|
||||
file.Size = attrs.Size
|
||||
file.OriginalName = originalName
|
||||
file.Reader = openFuncAsReader(func() (io.ReadSeekCloser, error) {
|
||||
return s.GetReader(fileKey)
|
||||
})
|
||||
|
||||
if preserveName {
|
||||
file.Name = name
|
||||
} else {
|
||||
file.Name = normalizeName(file.Reader, originalName)
|
||||
}
|
||||
|
||||
return file, nil
|
||||
}
|
||||
|
||||
// Copy copies the file stored at srcKey to dstKey.
|
||||
//
|
||||
// If srcKey file doesn't exist, it returns ErrNotFound.
|
||||
@@ -190,7 +239,7 @@ func (s *System) UploadFile(file *File, fileKey string) error {
|
||||
opts := &blob.WriterOptions{
|
||||
ContentType: mt.String(),
|
||||
Metadata: map[string]string{
|
||||
"original-filename": originalName,
|
||||
metadataOriginalName: originalName,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -232,7 +281,7 @@ func (s *System) UploadMultipart(fh *multipart.FileHeader, fileKey string) error
|
||||
opts := &blob.WriterOptions{
|
||||
ContentType: mt.String(),
|
||||
Metadata: map[string]string{
|
||||
"original-filename": originalName,
|
||||
metadataOriginalName: originalName,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -241,7 +290,8 @@ func (s *System) UploadMultipart(fh *multipart.FileHeader, fileKey string) error
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := w.ReadFrom(f); err != nil {
|
||||
_, err = w.ReadFrom(f)
|
||||
if err != nil {
|
||||
w.Close()
|
||||
return err
|
||||
}
|
||||
@@ -379,7 +429,7 @@ const forceAttachmentParam = "download"
|
||||
// Internally this method uses [http.ServeContent] so Range requests,
|
||||
// If-Match, If-Unmodified-Since, etc. headers are handled transparently.
|
||||
func (s *System) Serve(res http.ResponseWriter, req *http.Request, fileKey string, name string) error {
|
||||
br, readErr := s.GetFile(fileKey)
|
||||
br, readErr := s.GetReader(fileKey)
|
||||
if readErr != nil {
|
||||
return readErr
|
||||
}
|
||||
@@ -451,7 +501,7 @@ func (s *System) CreateThumb(originalKey string, thumbKey, thumbSize string) err
|
||||
}
|
||||
|
||||
// fetch the original
|
||||
r, readErr := s.GetFile(originalKey)
|
||||
r, readErr := s.GetReader(originalKey)
|
||||
if readErr != nil {
|
||||
return readErr
|
||||
}
|
||||
|
||||
@@ -526,7 +526,7 @@ func TestFileSystemServe(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileSystemGetFile(t *testing.T) {
|
||||
func TestFileSystemGetReader(t *testing.T) {
|
||||
dir := createTestDir(t)
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
@@ -547,7 +547,7 @@ func TestFileSystemGetFile(t *testing.T) {
|
||||
|
||||
for _, s := range scenarios {
|
||||
t.Run(s.file, func(t *testing.T) {
|
||||
f, err := fsys.GetFile(s.file)
|
||||
f, err := fsys.GetReader(s.file)
|
||||
defer func() {
|
||||
if f != nil {
|
||||
f.Close()
|
||||
@@ -578,6 +578,83 @@ func TestFileSystemGetFile(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileSystemGetReuploadableFile(t *testing.T) {
|
||||
dir := createTestDir(t)
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
fsys, err := filesystem.NewLocal(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer fsys.Close()
|
||||
|
||||
t.Run("missing.txt", func(t *testing.T) {
|
||||
_, err := fsys.GetReuploadableFile("missing.txt", false)
|
||||
if err == nil {
|
||||
t.Fatal("Expected error, got nil")
|
||||
}
|
||||
})
|
||||
|
||||
testReader := func(t *testing.T, f *filesystem.File, expectedContent string) {
|
||||
r, err := f.Reader.Open()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
raw, err := io.ReadAll(r)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
rawStr := string(raw)
|
||||
|
||||
if rawStr != expectedContent {
|
||||
t.Fatalf("Expected content %q, got %q", expectedContent, rawStr)
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("existing (preserve name)", func(t *testing.T) {
|
||||
file, err := fsys.GetReuploadableFile("test/sub1.txt", true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if v := file.OriginalName; v != "sub1.txt" {
|
||||
t.Fatalf("Expected originalName %q, got %q", "sub1.txt", v)
|
||||
}
|
||||
|
||||
if v := file.Size; v != 4 {
|
||||
t.Fatalf("Expected size %d, got %d", 4, v)
|
||||
}
|
||||
|
||||
if v := file.Name; v != "sub1.txt" {
|
||||
t.Fatalf("Expected name to be preserved, got %q", v)
|
||||
}
|
||||
|
||||
testReader(t, file, "sub1")
|
||||
})
|
||||
|
||||
t.Run("existing (new random suffix name)", func(t *testing.T) {
|
||||
file, err := fsys.GetReuploadableFile("test/sub1.txt", false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if v := file.OriginalName; v != "sub1.txt" {
|
||||
t.Fatalf("Expected originalName %q, got %q", "sub1.txt", v)
|
||||
}
|
||||
|
||||
if v := file.Size; v != 4 {
|
||||
t.Fatalf("Expected size %d, got %d", 4, v)
|
||||
}
|
||||
|
||||
if v := file.Name; v == "sub1.txt" || len(v) <= len("sub1.txt.png") {
|
||||
t.Fatalf("Expected name to have new random suffix, got %q", v)
|
||||
}
|
||||
|
||||
testReader(t, file, "sub1")
|
||||
})
|
||||
}
|
||||
|
||||
func TestFileSystemCopy(t *testing.T) {
|
||||
dir := createTestDir(t)
|
||||
defer os.RemoveAll(dir)
|
||||
@@ -600,7 +677,7 @@ func TestFileSystemCopy(t *testing.T) {
|
||||
if err := fsys.Copy(src, dst); err != nil {
|
||||
t.Fatalf("Failed to copy %q to %q: %v", src, dst, err)
|
||||
}
|
||||
f, err := fsys.GetFile(dst)
|
||||
f, err := fsys.GetReader(dst)
|
||||
//nolint
|
||||
defer f.Close()
|
||||
if err != nil {
|
||||
@@ -801,7 +878,7 @@ func TestFileSystemCreateThumb(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
f, err := fsys.GetFile(s.thumb)
|
||||
f, err := fsys.GetReader(s.thumb)
|
||||
if err != nil {
|
||||
t.Fatalf("Missing expected thumb %s (%v)", s.thumb, err)
|
||||
}
|
||||
@@ -849,7 +926,6 @@ func createTestDir(t *testing.T) string {
|
||||
|
||||
// png
|
||||
{
|
||||
|
||||
file, err := os.OpenFile(filepath.Join(dir, "image.png"), os.O_WRONLY|os.O_CREATE, 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -9,4 +9,4 @@ PB_DOCS_URL = "https://pocketbase.io/docs"
|
||||
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.27.2"
|
||||
PB_VERSION = "v0.28.1"
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{S as Ce,i as Be,s as Te,V as Le,X as J,h as u,d as ae,t as Q,a as G,I as N,Z as we,_ as Se,C as De,$ as Re,D as Ue,l as d,n as a,m as ne,u as c,A as y,v as k,c as ie,w as h,p as oe,J as je,k as O,o as qe,W as Ee}from"./index-rRnVk674.js";import{F as Fe}from"./FieldsQueryParam-BEgqkb0I.js";function ye(n,s,l){const o=n.slice();return o[8]=s[l],o}function Me(n,s,l){const o=n.slice();return o[8]=s[l],o}function Ae(n,s){let l,o=s[8].code+"",p,b,i,f;function m(){return s[6](s[8])}return{key:n,first:null,c(){l=c("button"),p=y(o),b=k(),h(l,"class","tab-item"),O(l,"active",s[1]===s[8].code),this.first=l},m(v,$){d(v,l,$),a(l,p),a(l,b),i||(f=qe(l,"click",m),i=!0)},p(v,$){s=v,$&4&&o!==(o=s[8].code+"")&&N(p,o),$&6&&O(l,"active",s[1]===s[8].code)},d(v){v&&u(l),i=!1,f()}}}function Pe(n,s){let l,o,p,b;return o=new Ee({props:{content:s[8].body}}),{key:n,first:null,c(){l=c("div"),ie(o.$$.fragment),p=k(),h(l,"class","tab-item"),O(l,"active",s[1]===s[8].code),this.first=l},m(i,f){d(i,l,f),ne(o,l,null),a(l,p),b=!0},p(i,f){s=i;const m={};f&4&&(m.content=s[8].body),o.$set(m),(!b||f&6)&&O(l,"active",s[1]===s[8].code)},i(i){b||(G(o.$$.fragment,i),b=!0)},o(i){Q(o.$$.fragment,i),b=!1},d(i){i&&u(l),ae(o)}}}function He(n){var ke,ge;let s,l,o=n[0].name+"",p,b,i,f,m,v,$,g=n[0].name+"",V,ce,W,M,X,L,Z,A,E,re,F,S,ue,z,H=n[0].name+"",K,de,Y,D,x,P,ee,fe,te,T,le,R,se,C,U,w=[],me=new Map,pe,j,_=[],be=new Map,B;M=new Le({props:{js:`
|
||||
import{S as Ce,i as Be,s as Te,V as Le,X as J,h as u,d as ae,t as Q,a as G,I as N,Z as we,_ as Se,C as De,$ as Re,D as Ue,l as d,n as a,m as ne,u as c,A as y,v as k,c as ie,w as h,p as oe,J as je,k as O,o as qe,W as Ee}from"./index-BH0nlDnw.js";import{F as Fe}from"./FieldsQueryParam-DQVKTiQb.js";function ye(n,s,l){const o=n.slice();return o[8]=s[l],o}function Me(n,s,l){const o=n.slice();return o[8]=s[l],o}function Ae(n,s){let l,o=s[8].code+"",p,b,i,f;function m(){return s[6](s[8])}return{key:n,first:null,c(){l=c("button"),p=y(o),b=k(),h(l,"class","tab-item"),O(l,"active",s[1]===s[8].code),this.first=l},m(v,$){d(v,l,$),a(l,p),a(l,b),i||(f=qe(l,"click",m),i=!0)},p(v,$){s=v,$&4&&o!==(o=s[8].code+"")&&N(p,o),$&6&&O(l,"active",s[1]===s[8].code)},d(v){v&&u(l),i=!1,f()}}}function Pe(n,s){let l,o,p,b;return o=new Ee({props:{content:s[8].body}}),{key:n,first:null,c(){l=c("div"),ie(o.$$.fragment),p=k(),h(l,"class","tab-item"),O(l,"active",s[1]===s[8].code),this.first=l},m(i,f){d(i,l,f),ne(o,l,null),a(l,p),b=!0},p(i,f){s=i;const m={};f&4&&(m.content=s[8].body),o.$set(m),(!b||f&6)&&O(l,"active",s[1]===s[8].code)},i(i){b||(G(o.$$.fragment,i),b=!0)},o(i){Q(o.$$.fragment,i),b=!1},d(i){i&&u(l),ae(o)}}}function He(n){var ke,ge;let s,l,o=n[0].name+"",p,b,i,f,m,v,$,g=n[0].name+"",V,ce,W,M,X,L,Z,A,E,re,F,S,ue,z,H=n[0].name+"",K,de,Y,D,x,P,ee,fe,te,T,le,R,se,C,U,w=[],me=new Map,pe,j,_=[],be=new Map,B;M=new Le({props:{js:`
|
||||
import PocketBase from 'pocketbase';
|
||||
|
||||
const pb = new PocketBase('${n[3]}');
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{S as je,i as xe,s as Ie,V as Ke,W as Ue,X as I,h as d,d as K,t as E,a as z,I as de,Z as Oe,_ as Qe,C as We,$ as Xe,D as Ze,l as u,n as o,m as Q,u as s,A as k,v as p,c as W,w as b,J as Ve,p as Ge,k as X,o as Ye}from"./index-rRnVk674.js";import{F as et}from"./FieldsQueryParam-BEgqkb0I.js";function Ee(r,a,l){const n=r.slice();return n[5]=a[l],n}function ze(r,a,l){const n=r.slice();return n[5]=a[l],n}function Je(r,a){let l,n=a[5].code+"",m,_,i,h;function g(){return a[4](a[5])}return{key:r,first:null,c(){l=s("button"),m=k(n),_=p(),b(l,"class","tab-item"),X(l,"active",a[1]===a[5].code),this.first=l},m(v,w){u(v,l,w),o(l,m),o(l,_),i||(h=Ye(l,"click",g),i=!0)},p(v,w){a=v,w&4&&n!==(n=a[5].code+"")&&de(m,n),w&6&&X(l,"active",a[1]===a[5].code)},d(v){v&&d(l),i=!1,h()}}}function Ne(r,a){let l,n,m,_;return n=new Ue({props:{content:a[5].body}}),{key:r,first:null,c(){l=s("div"),W(n.$$.fragment),m=p(),b(l,"class","tab-item"),X(l,"active",a[1]===a[5].code),this.first=l},m(i,h){u(i,l,h),Q(n,l,null),o(l,m),_=!0},p(i,h){a=i;const g={};h&4&&(g.content=a[5].body),n.$set(g),(!_||h&6)&&X(l,"active",a[1]===a[5].code)},i(i){_||(z(n.$$.fragment,i),_=!0)},o(i){E(n.$$.fragment,i),_=!1},d(i){i&&d(l),K(n)}}}function tt(r){var qe,Fe;let a,l,n=r[0].name+"",m,_,i,h,g,v,w,D,Z,S,J,ue,N,M,pe,G,U=r[0].name+"",Y,he,fe,j,ee,q,te,T,oe,be,F,C,ae,me,le,_e,f,ke,P,ge,ve,$e,se,ye,ne,Se,we,Te,re,Ce,Re,A,ie,H,ce,R,L,y=[],Pe=new Map,Ae,O,$=[],Be=new Map,B;v=new Ke({props:{js:`
|
||||
import{S as je,i as xe,s as Ie,V as Ke,W as Ue,X as I,h as d,d as K,t as E,a as z,I as de,Z as Oe,_ as Qe,C as We,$ as Xe,D as Ze,l as u,n as o,m as Q,u as s,A as k,v as p,c as W,w as b,J as Ve,p as Ge,k as X,o as Ye}from"./index-BH0nlDnw.js";import{F as et}from"./FieldsQueryParam-DQVKTiQb.js";function Ee(r,a,l){const n=r.slice();return n[5]=a[l],n}function ze(r,a,l){const n=r.slice();return n[5]=a[l],n}function Je(r,a){let l,n=a[5].code+"",m,_,i,h;function g(){return a[4](a[5])}return{key:r,first:null,c(){l=s("button"),m=k(n),_=p(),b(l,"class","tab-item"),X(l,"active",a[1]===a[5].code),this.first=l},m(v,w){u(v,l,w),o(l,m),o(l,_),i||(h=Ye(l,"click",g),i=!0)},p(v,w){a=v,w&4&&n!==(n=a[5].code+"")&&de(m,n),w&6&&X(l,"active",a[1]===a[5].code)},d(v){v&&d(l),i=!1,h()}}}function Ne(r,a){let l,n,m,_;return n=new Ue({props:{content:a[5].body}}),{key:r,first:null,c(){l=s("div"),W(n.$$.fragment),m=p(),b(l,"class","tab-item"),X(l,"active",a[1]===a[5].code),this.first=l},m(i,h){u(i,l,h),Q(n,l,null),o(l,m),_=!0},p(i,h){a=i;const g={};h&4&&(g.content=a[5].body),n.$set(g),(!_||h&6)&&X(l,"active",a[1]===a[5].code)},i(i){_||(z(n.$$.fragment,i),_=!0)},o(i){E(n.$$.fragment,i),_=!1},d(i){i&&d(l),K(n)}}}function tt(r){var qe,Fe;let a,l,n=r[0].name+"",m,_,i,h,g,v,w,D,Z,S,J,ue,N,M,pe,G,U=r[0].name+"",Y,he,fe,j,ee,q,te,T,oe,be,F,C,ae,me,le,_e,f,ke,P,ge,ve,$e,se,ye,ne,Se,we,Te,re,Ce,Re,A,ie,H,ce,R,L,y=[],Pe=new Map,Ae,O,$=[],Be=new Map,B;v=new Ke({props:{js:`
|
||||
import PocketBase from 'pocketbase';
|
||||
|
||||
const pb = new PocketBase('${r[3]}');
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{S as Je,i as xe,s as Ee,V as Ne,W as je,X as Q,h as r,d as Z,t as j,a as J,I as pe,Z as Ue,_ as Ie,C as Qe,$ as Ze,D as ze,l as c,n as a,m as z,u as o,A as _,v as h,c as K,w as p,J as Be,p as Ke,k as X,o as Xe}from"./index-rRnVk674.js";import{F as Ge}from"./FieldsQueryParam-BEgqkb0I.js";function Fe(s,l,n){const i=s.slice();return i[5]=l[n],i}function Le(s,l,n){const i=s.slice();return i[5]=l[n],i}function He(s,l){let n,i=l[5].code+"",f,g,d,b;function k(){return l[4](l[5])}return{key:s,first:null,c(){n=o("button"),f=_(i),g=h(),p(n,"class","tab-item"),X(n,"active",l[1]===l[5].code),this.first=n},m(v,O){c(v,n,O),a(n,f),a(n,g),d||(b=Xe(n,"click",k),d=!0)},p(v,O){l=v,O&4&&i!==(i=l[5].code+"")&&pe(f,i),O&6&&X(n,"active",l[1]===l[5].code)},d(v){v&&r(n),d=!1,b()}}}function Ve(s,l){let n,i,f,g;return i=new je({props:{content:l[5].body}}),{key:s,first:null,c(){n=o("div"),K(i.$$.fragment),f=h(),p(n,"class","tab-item"),X(n,"active",l[1]===l[5].code),this.first=n},m(d,b){c(d,n,b),z(i,n,null),a(n,f),g=!0},p(d,b){l=d;const k={};b&4&&(k.content=l[5].body),i.$set(k),(!g||b&6)&&X(n,"active",l[1]===l[5].code)},i(d){g||(J(i.$$.fragment,d),g=!0)},o(d){j(i.$$.fragment,d),g=!1},d(d){d&&r(n),Z(i)}}}function Ye(s){let l,n,i=s[0].name+"",f,g,d,b,k,v,O,R,G,A,x,be,E,P,me,Y,N=s[0].name+"",ee,fe,te,M,ae,W,le,U,ne,y,oe,ge,B,S,se,_e,ie,ke,m,ve,C,we,$e,Oe,re,Ae,ce,ye,Se,Te,de,Ce,qe,q,ue,F,he,T,L,$=[],De=new Map,Re,H,w=[],Pe=new Map,D;v=new Ne({props:{js:`
|
||||
import{S as Je,i as xe,s as Ee,V as Ne,W as je,X as Q,h as r,d as Z,t as j,a as J,I as pe,Z as Ue,_ as Ie,C as Qe,$ as Ze,D as ze,l as c,n as a,m as z,u as o,A as _,v as h,c as K,w as p,J as Be,p as Ke,k as X,o as Xe}from"./index-BH0nlDnw.js";import{F as Ge}from"./FieldsQueryParam-DQVKTiQb.js";function Fe(s,l,n){const i=s.slice();return i[5]=l[n],i}function Le(s,l,n){const i=s.slice();return i[5]=l[n],i}function He(s,l){let n,i=l[5].code+"",f,g,d,b;function k(){return l[4](l[5])}return{key:s,first:null,c(){n=o("button"),f=_(i),g=h(),p(n,"class","tab-item"),X(n,"active",l[1]===l[5].code),this.first=n},m(v,O){c(v,n,O),a(n,f),a(n,g),d||(b=Xe(n,"click",k),d=!0)},p(v,O){l=v,O&4&&i!==(i=l[5].code+"")&&pe(f,i),O&6&&X(n,"active",l[1]===l[5].code)},d(v){v&&r(n),d=!1,b()}}}function Ve(s,l){let n,i,f,g;return i=new je({props:{content:l[5].body}}),{key:s,first:null,c(){n=o("div"),K(i.$$.fragment),f=h(),p(n,"class","tab-item"),X(n,"active",l[1]===l[5].code),this.first=n},m(d,b){c(d,n,b),z(i,n,null),a(n,f),g=!0},p(d,b){l=d;const k={};b&4&&(k.content=l[5].body),i.$set(k),(!g||b&6)&&X(n,"active",l[1]===l[5].code)},i(d){g||(J(i.$$.fragment,d),g=!0)},o(d){j(i.$$.fragment,d),g=!1},d(d){d&&r(n),Z(i)}}}function Ye(s){let l,n,i=s[0].name+"",f,g,d,b,k,v,O,R,G,A,x,be,E,P,me,Y,N=s[0].name+"",ee,fe,te,M,ae,W,le,U,ne,y,oe,ge,B,S,se,_e,ie,ke,m,ve,C,we,$e,Oe,re,Ae,ce,ye,Se,Te,de,Ce,qe,q,ue,F,he,T,L,$=[],De=new Map,Re,H,w=[],Pe=new Map,D;v=new Ne({props:{js:`
|
||||
import PocketBase from 'pocketbase';
|
||||
|
||||
const pb = new PocketBase('${s[3]}');
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{S as be,i as _e,s as ve,W as ge,X as V,h as b,d as x,t as j,a as J,I as ce,Z as de,_ as je,C as ue,$ as Qe,D as he,l as _,n as s,m as ee,u as d,v as T,A as R,c as te,w as g,J as ke,k as N,o as $e,V as Ke,Y as De,p as Xe,a0 as Me}from"./index-rRnVk674.js";import{F as Ze}from"./FieldsQueryParam-BEgqkb0I.js";function Be(a,t,e){const l=a.slice();return l[4]=t[e],l}function Ie(a,t,e){const l=a.slice();return l[4]=t[e],l}function We(a,t){let e,l=t[4].code+"",h,i,c,n;function m(){return t[3](t[4])}return{key:a,first:null,c(){e=d("button"),h=R(l),i=T(),g(e,"class","tab-item"),N(e,"active",t[1]===t[4].code),this.first=e},m(v,C){_(v,e,C),s(e,h),s(e,i),c||(n=$e(e,"click",m),c=!0)},p(v,C){t=v,C&4&&l!==(l=t[4].code+"")&&ce(h,l),C&6&&N(e,"active",t[1]===t[4].code)},d(v){v&&b(e),c=!1,n()}}}function Fe(a,t){let e,l,h,i;return l=new ge({props:{content:t[4].body}}),{key:a,first:null,c(){e=d("div"),te(l.$$.fragment),h=T(),g(e,"class","tab-item"),N(e,"active",t[1]===t[4].code),this.first=e},m(c,n){_(c,e,n),ee(l,e,null),s(e,h),i=!0},p(c,n){t=c;const m={};n&4&&(m.content=t[4].body),l.$set(m),(!i||n&6)&&N(e,"active",t[1]===t[4].code)},i(c){i||(J(l.$$.fragment,c),i=!0)},o(c){j(l.$$.fragment,c),i=!1},d(c){c&&b(e),x(l)}}}function ze(a){let t,e,l,h,i,c,n,m=a[0].name+"",v,C,F,B,I,D,Q,M,U,y,O,q,k,L,Y,A,X,E,o,$,P,z,u,p,S,w,Z,we,Te,Pe,pe,Oe,ye,le,fe,oe,me,G,ae,K=[],Se=new Map,qe,ne,H=[],Ce=new Map,se;P=new ge({props:{content:"?expand=relField1,relField2.subRelField"}}),le=new Ze({props:{prefix:"record."}});let re=V(a[2]);const Ae=r=>r[4].code;for(let r=0;r<re.length;r+=1){let f=Ie(a,re,r),W=Ae(f);Se.set(W,K[r]=We(W,f))}let ie=V(a[2]);const Re=r=>r[4].code;for(let r=0;r<ie.length;r+=1){let f=Be(a,ie,r),W=Re(f);Ce.set(W,H[r]=Fe(W,f))}return{c(){t=d("div"),e=d("strong"),e.textContent="POST",l=T(),h=d("div"),i=d("p"),c=R("/api/collections/"),n=d("strong"),v=R(m),C=R("/auth-with-otp"),F=T(),B=d("div"),B.textContent="Body Parameters",I=T(),D=d("table"),D.innerHTML='<thead><tr><th>Param</th> <th>Type</th> <th width="50%">Description</th></tr></thead> <tbody><tr><td><div class="inline-flex"><span class="label label-success">Required</span> <span>otpId</span></div></td> <td><span class="label">String</span></td> <td>The id of the OTP request.</td></tr> <tr><td><div class="inline-flex"><span class="label label-success">Required</span> <span>password</span></div></td> <td><span class="label">String</span></td> <td>The one-time password.</td></tr></tbody>',Q=T(),M=d("div"),M.textContent="Query parameters",U=T(),y=d("table"),O=d("thead"),O.innerHTML='<tr><th>Param</th> <th>Type</th> <th width="60%">Description</th></tr>',q=T(),k=d("tbody"),L=d("tr"),Y=d("td"),Y.textContent="expand",A=T(),X=d("td"),X.innerHTML='<span class="label">String</span>',E=T(),o=d("td"),$=R(`Auto expand record relations. Ex.:
|
||||
import{S as be,i as _e,s as ve,W as ge,X as V,h as b,d as x,t as j,a as J,I as ce,Z as de,_ as je,C as ue,$ as Qe,D as he,l as _,n as s,m as ee,u as d,v as T,A as R,c as te,w as g,J as ke,k as N,o as $e,V as Ke,Y as De,p as Xe,a0 as Me}from"./index-BH0nlDnw.js";import{F as Ze}from"./FieldsQueryParam-DQVKTiQb.js";function Be(a,t,e){const l=a.slice();return l[4]=t[e],l}function Ie(a,t,e){const l=a.slice();return l[4]=t[e],l}function We(a,t){let e,l=t[4].code+"",h,i,c,n;function m(){return t[3](t[4])}return{key:a,first:null,c(){e=d("button"),h=R(l),i=T(),g(e,"class","tab-item"),N(e,"active",t[1]===t[4].code),this.first=e},m(v,C){_(v,e,C),s(e,h),s(e,i),c||(n=$e(e,"click",m),c=!0)},p(v,C){t=v,C&4&&l!==(l=t[4].code+"")&&ce(h,l),C&6&&N(e,"active",t[1]===t[4].code)},d(v){v&&b(e),c=!1,n()}}}function Fe(a,t){let e,l,h,i;return l=new ge({props:{content:t[4].body}}),{key:a,first:null,c(){e=d("div"),te(l.$$.fragment),h=T(),g(e,"class","tab-item"),N(e,"active",t[1]===t[4].code),this.first=e},m(c,n){_(c,e,n),ee(l,e,null),s(e,h),i=!0},p(c,n){t=c;const m={};n&4&&(m.content=t[4].body),l.$set(m),(!i||n&6)&&N(e,"active",t[1]===t[4].code)},i(c){i||(J(l.$$.fragment,c),i=!0)},o(c){j(l.$$.fragment,c),i=!1},d(c){c&&b(e),x(l)}}}function ze(a){let t,e,l,h,i,c,n,m=a[0].name+"",v,C,F,B,I,D,Q,M,U,y,O,q,k,L,Y,A,X,E,o,$,P,z,u,p,S,w,Z,we,Te,Pe,pe,Oe,ye,le,fe,oe,me,G,ae,K=[],Se=new Map,qe,ne,H=[],Ce=new Map,se;P=new ge({props:{content:"?expand=relField1,relField2.subRelField"}}),le=new Ze({props:{prefix:"record."}});let re=V(a[2]);const Ae=r=>r[4].code;for(let r=0;r<re.length;r+=1){let f=Ie(a,re,r),W=Ae(f);Se.set(W,K[r]=We(W,f))}let ie=V(a[2]);const Re=r=>r[4].code;for(let r=0;r<ie.length;r+=1){let f=Be(a,ie,r),W=Re(f);Ce.set(W,H[r]=Fe(W,f))}return{c(){t=d("div"),e=d("strong"),e.textContent="POST",l=T(),h=d("div"),i=d("p"),c=R("/api/collections/"),n=d("strong"),v=R(m),C=R("/auth-with-otp"),F=T(),B=d("div"),B.textContent="Body Parameters",I=T(),D=d("table"),D.innerHTML='<thead><tr><th>Param</th> <th>Type</th> <th width="50%">Description</th></tr></thead> <tbody><tr><td><div class="inline-flex"><span class="label label-success">Required</span> <span>otpId</span></div></td> <td><span class="label">String</span></td> <td>The id of the OTP request.</td></tr> <tr><td><div class="inline-flex"><span class="label label-success">Required</span> <span>password</span></div></td> <td><span class="label">String</span></td> <td>The one-time password.</td></tr></tbody>',Q=T(),M=d("div"),M.textContent="Query parameters",U=T(),y=d("table"),O=d("thead"),O.innerHTML='<tr><th>Param</th> <th>Type</th> <th width="60%">Description</th></tr>',q=T(),k=d("tbody"),L=d("tr"),Y=d("td"),Y.textContent="expand",A=T(),X=d("td"),X.innerHTML='<span class="label">String</span>',E=T(),o=d("td"),$=R(`Auto expand record relations. Ex.:
|
||||
`),te(P.$$.fragment),z=R(`
|
||||
Supports up to 6-levels depth nested relations expansion. `),u=d("br"),p=R(`
|
||||
The expanded relations will be appended to the record under the
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{S as kt,i as gt,s as vt,V as St,X as L,W as _t,h as c,d as ae,Y as wt,t as X,a as Z,I as z,Z as ct,_ as yt,C as $t,$ as Pt,D as Ct,l as d,n as t,m as oe,u as s,A as f,v as u,c as se,w as k,J as dt,p as Rt,k as ne,o as Ot}from"./index-rRnVk674.js";import{F as Tt}from"./FieldsQueryParam-BEgqkb0I.js";function pt(i,o,a){const n=i.slice();return n[7]=o[a],n}function ut(i,o,a){const n=i.slice();return n[7]=o[a],n}function ht(i,o,a){const n=i.slice();return n[12]=o[a],n[14]=a,n}function At(i){let o;return{c(){o=f("or")},m(a,n){d(a,o,n)},d(a){a&&c(o)}}}function bt(i){let o,a,n=i[12]+"",m,b=i[14]>0&&At();return{c(){b&&b.c(),o=u(),a=s("strong"),m=f(n)},m(r,h){b&&b.m(r,h),d(r,o,h),d(r,a,h),t(a,m)},p(r,h){h&2&&n!==(n=r[12]+"")&&z(m,n)},d(r){r&&(c(o),c(a)),b&&b.d(r)}}}function ft(i,o){let a,n=o[7].code+"",m,b,r,h;function g(){return o[6](o[7])}return{key:i,first:null,c(){a=s("button"),m=f(n),b=u(),k(a,"class","tab-item"),ne(a,"active",o[2]===o[7].code),this.first=a},m($,_){d($,a,_),t(a,m),t(a,b),r||(h=Ot(a,"click",g),r=!0)},p($,_){o=$,_&8&&n!==(n=o[7].code+"")&&z(m,n),_&12&&ne(a,"active",o[2]===o[7].code)},d($){$&&c(a),r=!1,h()}}}function mt(i,o){let a,n,m,b;return n=new _t({props:{content:o[7].body}}),{key:i,first:null,c(){a=s("div"),se(n.$$.fragment),m=u(),k(a,"class","tab-item"),ne(a,"active",o[2]===o[7].code),this.first=a},m(r,h){d(r,a,h),oe(n,a,null),t(a,m),b=!0},p(r,h){o=r;const g={};h&8&&(g.content=o[7].body),n.$set(g),(!b||h&12)&&ne(a,"active",o[2]===o[7].code)},i(r){b||(Z(n.$$.fragment,r),b=!0)},o(r){X(n.$$.fragment,r),b=!1},d(r){r&&c(a),ae(n)}}}function Dt(i){var ot,st;let o,a,n=i[0].name+"",m,b,r,h,g,$,_,G=i[1].join("/")+"",ie,De,re,We,ce,C,de,q,pe,R,x,Fe,ee,H,Me,ue,te=i[0].name+"",he,Ue,be,Y,fe,O,me,Be,j,T,_e,Le,ke,qe,V,ge,He,ve,Se,E,we,A,ye,Ye,N,D,$e,je,Pe,Ve,v,Ee,M,Ne,Ie,Je,Ce,Qe,Re,Ke,Xe,Ze,Oe,ze,Ge,U,Te,I,Ae,W,J,P=[],xe=new Map,et,Q,w=[],tt=new Map,F;C=new St({props:{js:`
|
||||
import{S as kt,i as gt,s as vt,V as St,X as L,W as _t,h as c,d as ae,Y as wt,t as X,a as Z,I as z,Z as ct,_ as yt,C as $t,$ as Pt,D as Ct,l as d,n as t,m as oe,u as s,A as f,v as u,c as se,w as k,J as dt,p as Rt,k as ne,o as Ot}from"./index-BH0nlDnw.js";import{F as Tt}from"./FieldsQueryParam-DQVKTiQb.js";function pt(i,o,a){const n=i.slice();return n[7]=o[a],n}function ut(i,o,a){const n=i.slice();return n[7]=o[a],n}function ht(i,o,a){const n=i.slice();return n[12]=o[a],n[14]=a,n}function At(i){let o;return{c(){o=f("or")},m(a,n){d(a,o,n)},d(a){a&&c(o)}}}function bt(i){let o,a,n=i[12]+"",m,b=i[14]>0&&At();return{c(){b&&b.c(),o=u(),a=s("strong"),m=f(n)},m(r,h){b&&b.m(r,h),d(r,o,h),d(r,a,h),t(a,m)},p(r,h){h&2&&n!==(n=r[12]+"")&&z(m,n)},d(r){r&&(c(o),c(a)),b&&b.d(r)}}}function ft(i,o){let a,n=o[7].code+"",m,b,r,h;function g(){return o[6](o[7])}return{key:i,first:null,c(){a=s("button"),m=f(n),b=u(),k(a,"class","tab-item"),ne(a,"active",o[2]===o[7].code),this.first=a},m($,_){d($,a,_),t(a,m),t(a,b),r||(h=Ot(a,"click",g),r=!0)},p($,_){o=$,_&8&&n!==(n=o[7].code+"")&&z(m,n),_&12&&ne(a,"active",o[2]===o[7].code)},d($){$&&c(a),r=!1,h()}}}function mt(i,o){let a,n,m,b;return n=new _t({props:{content:o[7].body}}),{key:i,first:null,c(){a=s("div"),se(n.$$.fragment),m=u(),k(a,"class","tab-item"),ne(a,"active",o[2]===o[7].code),this.first=a},m(r,h){d(r,a,h),oe(n,a,null),t(a,m),b=!0},p(r,h){o=r;const g={};h&8&&(g.content=o[7].body),n.$set(g),(!b||h&12)&&ne(a,"active",o[2]===o[7].code)},i(r){b||(Z(n.$$.fragment,r),b=!0)},o(r){X(n.$$.fragment,r),b=!1},d(r){r&&c(a),ae(n)}}}function Dt(i){var ot,st;let o,a,n=i[0].name+"",m,b,r,h,g,$,_,G=i[1].join("/")+"",ie,De,re,We,ce,C,de,q,pe,R,x,Fe,ee,H,Me,ue,te=i[0].name+"",he,Ue,be,Y,fe,O,me,Be,j,T,_e,Le,ke,qe,V,ge,He,ve,Se,E,we,A,ye,Ye,N,D,$e,je,Pe,Ve,v,Ee,M,Ne,Ie,Je,Ce,Qe,Re,Ke,Xe,Ze,Oe,ze,Ge,U,Te,I,Ae,W,J,P=[],xe=new Map,et,Q,w=[],tt=new Map,F;C=new St({props:{js:`
|
||||
import PocketBase from 'pocketbase';
|
||||
|
||||
const pb = new PocketBase('${i[5]}');
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{S as St,i as At,s as Lt,V as Mt,W as Ht,X as Q,h as d,d as Re,t as Y,a as x,I as jt,Z as Pt,_ as Nt,C as Ut,$ as Jt,D as zt,l as u,n as t,m as Te,E as Wt,G as Gt,u as o,A as _,v as i,c as Pe,w as b,J as Ft,p as Kt,k as ee,o as Vt}from"./index-rRnVk674.js";function Bt(a,s,n){const c=a.slice();return c[6]=s[n],c}function Et(a,s,n){const c=a.slice();return c[6]=s[n],c}function Ot(a,s){let n,c,y;function f(){return s[5](s[6])}return{key:a,first:null,c(){n=o("button"),n.textContent=`${s[6].code} `,b(n,"class","tab-item"),ee(n,"active",s[1]===s[6].code),this.first=n},m(r,h){u(r,n,h),c||(y=Vt(n,"click",f),c=!0)},p(r,h){s=r,h&10&&ee(n,"active",s[1]===s[6].code)},d(r){r&&d(n),c=!1,y()}}}function It(a,s){let n,c,y,f;return c=new Ht({props:{content:s[6].body}}),{key:a,first:null,c(){n=o("div"),Pe(c.$$.fragment),y=i(),b(n,"class","tab-item"),ee(n,"active",s[1]===s[6].code),this.first=n},m(r,h){u(r,n,h),Te(c,n,null),t(n,y),f=!0},p(r,h){s=r,(!f||h&10)&&ee(n,"active",s[1]===s[6].code)},i(r){f||(x(c.$$.fragment,r),f=!0)},o(r){Y(c.$$.fragment,r),f=!1},d(r){r&&d(n),Re(c)}}}function Xt(a){var pt,mt,bt,ht,ft,_t,yt,kt;let s,n,c=a[0].name+"",y,f,r,h,F,g,U,Fe,P,B,Be,E,Ee,Oe,te,le,q,oe,O,ae,I,se,H,ne,J,ie,w,ce,Ie,re,S,z,He,k,W,Se,de,Ae,C,G,Le,ue,Me,K,je,pe,Ne,D,Ue,me,Je,ze,We,V,Ge,X,Ke,be,Ve,he,Xe,fe,Ze,p,_e,Qe,ye,Ye,ke,xe,$e,et,ge,tt,ve,lt,ot,at,Ce,st,R,De,A,qe,T,L,v=[],nt=new Map,it,M,$=[],ct=new Map,j,we,rt;q=new Mt({props:{js:`
|
||||
import{S as St,i as At,s as Lt,V as Mt,W as Ht,X as Q,h as d,d as Re,t as Y,a as x,I as jt,Z as Pt,_ as Nt,C as Ut,$ as Jt,D as zt,l as u,n as t,m as Te,E as Wt,G as Gt,u as o,A as _,v as i,c as Pe,w as b,J as Ft,p as Kt,k as ee,o as Vt}from"./index-BH0nlDnw.js";function Bt(a,s,n){const c=a.slice();return c[6]=s[n],c}function Et(a,s,n){const c=a.slice();return c[6]=s[n],c}function Ot(a,s){let n,c,y;function f(){return s[5](s[6])}return{key:a,first:null,c(){n=o("button"),n.textContent=`${s[6].code} `,b(n,"class","tab-item"),ee(n,"active",s[1]===s[6].code),this.first=n},m(r,h){u(r,n,h),c||(y=Vt(n,"click",f),c=!0)},p(r,h){s=r,h&10&&ee(n,"active",s[1]===s[6].code)},d(r){r&&d(n),c=!1,y()}}}function It(a,s){let n,c,y,f;return c=new Ht({props:{content:s[6].body}}),{key:a,first:null,c(){n=o("div"),Pe(c.$$.fragment),y=i(),b(n,"class","tab-item"),ee(n,"active",s[1]===s[6].code),this.first=n},m(r,h){u(r,n,h),Te(c,n,null),t(n,y),f=!0},p(r,h){s=r,(!f||h&10)&&ee(n,"active",s[1]===s[6].code)},i(r){f||(x(c.$$.fragment,r),f=!0)},o(r){Y(c.$$.fragment,r),f=!1},d(r){r&&d(n),Re(c)}}}function Xt(a){var pt,mt,bt,ht,ft,_t,yt,kt;let s,n,c=a[0].name+"",y,f,r,h,F,g,U,Fe,P,B,Be,E,Ee,Oe,te,le,q,oe,O,ae,I,se,H,ne,J,ie,w,ce,Ie,re,S,z,He,k,W,Se,de,Ae,C,G,Le,ue,Me,K,je,pe,Ne,D,Ue,me,Je,ze,We,V,Ge,X,Ke,be,Ve,he,Xe,fe,Ze,p,_e,Qe,ye,Ye,ke,xe,$e,et,ge,tt,ve,lt,ot,at,Ce,st,R,De,A,qe,T,L,v=[],nt=new Map,it,M,$=[],ct=new Map,j,we,rt;q=new Mt({props:{js:`
|
||||
import PocketBase from 'pocketbase';
|
||||
|
||||
const pb = new PocketBase('${a[2]}');
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{S as vt,i as Tt,s as wt,H as IO,h as _t,a1 as OO,l as qt,u as Yt,w as Rt,O as Vt,T as jt,U as zt,Q as Gt,J as Wt,y as Ut}from"./index-rRnVk674.js";import{P as Ct,N as Et,w as At,D as Mt,x as RO,T as tO,I as VO,y as Lt,z as I,A as n,L as D,B as J,F as K,G as V,H as jO,J as F,v as U,K as Ye,M as g,E as R,O as Re,Q as Ve,R as je,U as Bt,V as Nt,W as It,X as ze,Y as Dt,b as C,e as Jt,f as Kt,g as Ft,i as Ht,j as Oa,k as ea,l as ta,m as aa,r as ra,n as ia,o as sa,p as la,C as eO,u as na,c as oa,d as ca,s as Qa,h as pa,a as ha,q as DO}from"./index-CXcDhfsk.js";var JO={};class sO{constructor(O,t,a,r,s,i,l,o,Q,h=0,c){this.p=O,this.stack=t,this.state=a,this.reducePos=r,this.pos=s,this.score=i,this.buffer=l,this.bufferBase=o,this.curContext=Q,this.lookAhead=h,this.parent=c}toString(){return`[${this.stack.filter((O,t)=>t%3==0).concat(this.state)}]@${this.pos}${this.score?"!"+this.score:""}`}static start(O,t,a=0){let r=O.parser.context;return new sO(O,[],t,a,a,0,[],0,r?new KO(r,r.start):null,0,null)}get context(){return this.curContext?this.curContext.context:null}pushState(O,t){this.stack.push(this.state,t,this.bufferBase+this.buffer.length),this.state=O}reduce(O){var t;let a=O>>19,r=O&65535,{parser:s}=this.p,i=this.reducePos<this.pos-25;i&&this.setLookAhead(this.pos);let l=s.dynamicPrecedence(r);if(l&&(this.score+=l),a==0){this.pushState(s.getGoto(this.state,r,!0),this.reducePos),r<s.minRepeatTerm&&this.storeNode(r,this.reducePos,this.reducePos,i?8:4,!0),this.reduceContext(r,this.reducePos);return}let o=this.stack.length-(a-1)*3-(O&262144?6:0),Q=o?this.stack[o-2]:this.p.ranges[0].from,h=this.reducePos-Q;h>=2e3&&!(!((t=this.p.parser.nodeSet.types[r])===null||t===void 0)&&t.isAnonymous)&&(Q==this.p.lastBigReductionStart?(this.p.bigReductionCount++,this.p.lastBigReductionSize=h):this.p.lastBigReductionSize<h&&(this.p.bigReductionCount=1,this.p.lastBigReductionStart=Q,this.p.lastBigReductionSize=h));let c=o?this.stack[o-1]:0,d=this.bufferBase+this.buffer.length-c;if(r<s.minRepeatTerm||O&131072){let p=s.stateFlag(this.state,1)?this.pos:this.reducePos;this.storeNode(r,Q,p,d+4,!0)}if(O&262144)this.state=this.stack[o];else{let p=this.stack[o-3];this.state=s.getGoto(p,r,!0)}for(;this.stack.length>o;)this.stack.pop();this.reduceContext(r,Q)}storeNode(O,t,a,r=4,s=!1){if(O==0&&(!this.stack.length||this.stack[this.stack.length-1]<this.buffer.length+this.bufferBase)){let i=this,l=this.buffer.length;if(l==0&&i.parent&&(l=i.bufferBase-i.parent.bufferBase,i=i.parent),l>0&&i.buffer[l-4]==0&&i.buffer[l-1]>-1){if(t==a)return;if(i.buffer[l-2]>=t){i.buffer[l-2]=a;return}}}if(!s||this.pos==a)this.buffer.push(O,t,a,r);else{let i=this.buffer.length;if(i>0&&this.buffer[i-4]!=0){let l=!1;for(let o=i;o>0&&this.buffer[o-2]>a;o-=4)if(this.buffer[o-1]>=0){l=!0;break}if(l)for(;i>0&&this.buffer[i-2]>a;)this.buffer[i]=this.buffer[i-4],this.buffer[i+1]=this.buffer[i-3],this.buffer[i+2]=this.buffer[i-2],this.buffer[i+3]=this.buffer[i-1],i-=4,r>4&&(r-=4)}this.buffer[i]=O,this.buffer[i+1]=t,this.buffer[i+2]=a,this.buffer[i+3]=r}}shift(O,t,a,r){if(O&131072)this.pushState(O&65535,this.pos);else if(O&262144)this.pos=r,this.shiftContext(t,a),t<=this.p.parser.maxNode&&this.buffer.push(t,a,r,4);else{let s=O,{parser:i}=this.p;(r>this.pos||t<=i.maxNode)&&(this.pos=r,i.stateFlag(s,1)||(this.reducePos=r)),this.pushState(s,a),this.shiftContext(t,a),t<=i.maxNode&&this.buffer.push(t,a,r,4)}}apply(O,t,a,r){O&65536?this.reduce(O):this.shift(O,t,a,r)}useNode(O,t){let a=this.p.reused.length-1;(a<0||this.p.reused[a]!=O)&&(this.p.reused.push(O),a++);let r=this.pos;this.reducePos=this.pos=r+O.length,this.pushState(t,r),this.buffer.push(a,r,this.reducePos,-1),this.curContext&&this.updateContext(this.curContext.tracker.reuse(this.curContext.context,O,this,this.p.stream.reset(this.pos-O.length)))}split(){let O=this,t=O.buffer.length;for(;t>0&&O.buffer[t-2]>O.reducePos;)t-=4;let a=O.buffer.slice(t),r=O.bufferBase+t;for(;O&&r==O.bufferBase;)O=O.parent;return new sO(this.p,this.stack.slice(),this.state,this.reducePos,this.pos,this.score,a,r,this.curContext,this.lookAhead,O)}recoverByDelete(O,t){let a=O<=this.p.parser.maxNode;a&&this.storeNode(O,this.pos,t,4),this.storeNode(0,this.pos,t,a?8:4),this.pos=this.reducePos=t,this.score-=190}canShift(O){for(let t=new ua(this);;){let a=this.p.parser.stateSlot(t.state,4)||this.p.parser.hasAction(t.state,O);if(a==0)return!1;if(!(a&65536))return!0;t.reduce(a)}}recoverByInsert(O){if(this.stack.length>=300)return[];let t=this.p.parser.nextStates(this.state);if(t.length>8||this.stack.length>=120){let r=[];for(let s=0,i;s<t.length;s+=2)(i=t[s+1])!=this.state&&this.p.parser.hasAction(i,O)&&r.push(t[s],i);if(this.stack.length<120)for(let s=0;r.length<8&&s<t.length;s+=2){let i=t[s+1];r.some((l,o)=>o&1&&l==i)||r.push(t[s],i)}t=r}let a=[];for(let r=0;r<t.length&&a.length<4;r+=2){let s=t[r+1];if(s==this.state)continue;let i=this.split();i.pushState(s,this.pos),i.storeNode(0,i.pos,i.pos,4,!0),i.shiftContext(t[r],this.pos),i.reducePos=this.pos,iLine truncated
|
||||
import{S as vt,i as Tt,s as wt,H as IO,h as _t,a1 as OO,l as qt,u as Yt,w as Rt,O as Vt,T as jt,U as zt,Q as Gt,J as Wt,y as Ut}from"./index-BH0nlDnw.js";import{P as Ct,N as Et,w as At,D as Mt,x as RO,T as tO,I as VO,y as Lt,z as I,A as n,L as D,B as J,F as K,G as V,H as jO,J as F,v as U,K as Ye,M as g,E as R,O as Re,Q as Ve,R as je,U as Bt,V as Nt,W as It,X as ze,Y as Dt,b as C,e as Jt,f as Kt,g as Ft,i as Ht,j as Oa,k as ea,l as ta,m as aa,r as ra,n as ia,o as sa,p as la,C as eO,u as na,c as oa,d as ca,s as Qa,h as pa,a as ha,q as DO}from"./index-Bd1MzT5k.js";var JO={};class sO{constructor(O,t,a,r,s,i,l,o,Q,h=0,c){this.p=O,this.stack=t,this.state=a,this.reducePos=r,this.pos=s,this.score=i,this.buffer=l,this.bufferBase=o,this.curContext=Q,this.lookAhead=h,this.parent=c}toString(){return`[${this.stack.filter((O,t)=>t%3==0).concat(this.state)}]@${this.pos}${this.score?"!"+this.score:""}`}static start(O,t,a=0){let r=O.parser.context;return new sO(O,[],t,a,a,0,[],0,r?new KO(r,r.start):null,0,null)}get context(){return this.curContext?this.curContext.context:null}pushState(O,t){this.stack.push(this.state,t,this.bufferBase+this.buffer.length),this.state=O}reduce(O){var t;let a=O>>19,r=O&65535,{parser:s}=this.p,i=this.reducePos<this.pos-25;i&&this.setLookAhead(this.pos);let l=s.dynamicPrecedence(r);if(l&&(this.score+=l),a==0){this.pushState(s.getGoto(this.state,r,!0),this.reducePos),r<s.minRepeatTerm&&this.storeNode(r,this.reducePos,this.reducePos,i?8:4,!0),this.reduceContext(r,this.reducePos);return}let o=this.stack.length-(a-1)*3-(O&262144?6:0),Q=o?this.stack[o-2]:this.p.ranges[0].from,h=this.reducePos-Q;h>=2e3&&!(!((t=this.p.parser.nodeSet.types[r])===null||t===void 0)&&t.isAnonymous)&&(Q==this.p.lastBigReductionStart?(this.p.bigReductionCount++,this.p.lastBigReductionSize=h):this.p.lastBigReductionSize<h&&(this.p.bigReductionCount=1,this.p.lastBigReductionStart=Q,this.p.lastBigReductionSize=h));let c=o?this.stack[o-1]:0,d=this.bufferBase+this.buffer.length-c;if(r<s.minRepeatTerm||O&131072){let p=s.stateFlag(this.state,1)?this.pos:this.reducePos;this.storeNode(r,Q,p,d+4,!0)}if(O&262144)this.state=this.stack[o];else{let p=this.stack[o-3];this.state=s.getGoto(p,r,!0)}for(;this.stack.length>o;)this.stack.pop();this.reduceContext(r,Q)}storeNode(O,t,a,r=4,s=!1){if(O==0&&(!this.stack.length||this.stack[this.stack.length-1]<this.buffer.length+this.bufferBase)){let i=this,l=this.buffer.length;if(l==0&&i.parent&&(l=i.bufferBase-i.parent.bufferBase,i=i.parent),l>0&&i.buffer[l-4]==0&&i.buffer[l-1]>-1){if(t==a)return;if(i.buffer[l-2]>=t){i.buffer[l-2]=a;return}}}if(!s||this.pos==a)this.buffer.push(O,t,a,r);else{let i=this.buffer.length;if(i>0&&this.buffer[i-4]!=0){let l=!1;for(let o=i;o>0&&this.buffer[o-2]>a;o-=4)if(this.buffer[o-1]>=0){l=!0;break}if(l)for(;i>0&&this.buffer[i-2]>a;)this.buffer[i]=this.buffer[i-4],this.buffer[i+1]=this.buffer[i-3],this.buffer[i+2]=this.buffer[i-2],this.buffer[i+3]=this.buffer[i-1],i-=4,r>4&&(r-=4)}this.buffer[i]=O,this.buffer[i+1]=t,this.buffer[i+2]=a,this.buffer[i+3]=r}}shift(O,t,a,r){if(O&131072)this.pushState(O&65535,this.pos);else if(O&262144)this.pos=r,this.shiftContext(t,a),t<=this.p.parser.maxNode&&this.buffer.push(t,a,r,4);else{let s=O,{parser:i}=this.p;(r>this.pos||t<=i.maxNode)&&(this.pos=r,i.stateFlag(s,1)||(this.reducePos=r)),this.pushState(s,a),this.shiftContext(t,a),t<=i.maxNode&&this.buffer.push(t,a,r,4)}}apply(O,t,a,r){O&65536?this.reduce(O):this.shift(O,t,a,r)}useNode(O,t){let a=this.p.reused.length-1;(a<0||this.p.reused[a]!=O)&&(this.p.reused.push(O),a++);let r=this.pos;this.reducePos=this.pos=r+O.length,this.pushState(t,r),this.buffer.push(a,r,this.reducePos,-1),this.curContext&&this.updateContext(this.curContext.tracker.reuse(this.curContext.context,O,this,this.p.stream.reset(this.pos-O.length)))}split(){let O=this,t=O.buffer.length;for(;t>0&&O.buffer[t-2]>O.reducePos;)t-=4;let a=O.buffer.slice(t),r=O.bufferBase+t;for(;O&&r==O.bufferBase;)O=O.parent;return new sO(this.p,this.stack.slice(),this.state,this.reducePos,this.pos,this.score,a,r,this.curContext,this.lookAhead,O)}recoverByDelete(O,t){let a=O<=this.p.parser.maxNode;a&&this.storeNode(O,this.pos,t,4),this.storeNode(0,this.pos,t,a?8:4),this.pos=this.reducePos=t,this.score-=190}canShift(O){for(let t=new ua(this);;){let a=this.p.parser.stateSlot(t.state,4)||this.p.parser.hasAction(t.state,O);if(a==0)return!1;if(!(a&65536))return!0;t.reduce(a)}}recoverByInsert(O){if(this.stack.length>=300)return[];let t=this.p.parser.nextStates(this.state);if(t.length>8||this.stack.length>=120){let r=[];for(let s=0,i;s<t.length;s+=2)(i=t[s+1])!=this.state&&this.p.parser.hasAction(i,O)&&r.push(t[s],i);if(this.stack.length<120)for(let s=0;r.length<8&&s<t.length;s+=2){let i=t[s+1];r.some((l,o)=>o&1&&l==i)||r.push(t[s],i)}t=r}let a=[];for(let r=0;r<t.length&&a.length<4;r+=2){let s=t[r+1];if(s==this.state)continue;let i=this.split();i.pushState(s,this.pos),i.storeNode(0,i.pos,i.pos,4,!0),i.shiftContext(t[r],this.pos),i.reducePos=this.pos,iLine truncated
|
||||
\${}
|
||||
} catch (\${error}) {
|
||||
\${}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{S as $t,i as qt,s as Tt,V as St,X as ce,W as Ct,h as o,d as $e,t as he,a as ve,I as ae,Z as Ne,_ as pt,C as Mt,$ as Pt,D as Lt,l as r,n as i,m as qe,u as a,A as b,v as p,c as Te,w,J as we,p as Ft,k as Se,o as Ht,L as Ot,H as fe}from"./index-rRnVk674.js";import{F as Rt}from"./FieldsQueryParam-BEgqkb0I.js";function mt(s,e,t){const l=s.slice();return l[10]=e[t],l}function bt(s,e,t){const l=s.slice();return l[10]=e[t],l}function _t(s,e,t){const l=s.slice();return l[15]=e[t],l}function kt(s){let e;return{c(){e=a("p"),e.innerHTML="Requires superuser <code>Authorization:TOKEN</code> header",w(e,"class","txt-hint txt-sm txt-right")},m(t,l){r(t,e,l)},d(t){t&&o(e)}}}function yt(s){let e,t,l,c,f,u,_,m,q,y,g,B,S,$,R,P,I,D,M,W,L,T,k,F,ee,z,U,oe,K,X,Y;function ue(h,C){var N,x,O;return C&1&&(u=null),u==null&&(u=!!((O=(x=(N=h[0])==null?void 0:N.fields)==null?void 0:x.find(Yt))!=null&&O.required)),u?Bt:At}let te=ue(s,-1),E=te(s);function Z(h,C){var N,x,O;return C&1&&(I=null),I==null&&(I=!!((O=(x=(N=h[0])==null?void 0:N.fields)==null?void 0:x.find(Xt))!=null&&O.required)),I?Nt:Vt}let G=Z(s,-1),H=G(s);return{c(){e=a("tr"),e.innerHTML='<td colspan="3" class="txt-hint txt-bold">Auth specific fields</td>',t=p(),l=a("tr"),c=a("td"),f=a("div"),E.c(),_=p(),m=a("span"),m.textContent="email",q=p(),y=a("td"),y.innerHTML='<span class="label">String</span>',g=p(),B=a("td"),B.textContent="Auth record email address.",S=p(),$=a("tr"),R=a("td"),P=a("div"),H.c(),D=p(),M=a("span"),M.textContent="emailVisibility",W=p(),L=a("td"),L.innerHTML='<span class="label">Boolean</span>',T=p(),k=a("td"),k.textContent="Whether to show/hide the auth record email when fetching the record data.",F=p(),ee=a("tr"),ee.innerHTML='<td><div class="inline-flex"><span class="label label-success">Required</span> <span>password</span></div></td> <td><span class="label">String</span></td> <td>Auth record password.</td>',z=p(),U=a("tr"),U.innerHTML='<td><div class="inline-flex"><span class="label label-success">Required</span> <span>passwordConfirm</span></div></td> <td><span class="label">String</span></td> <td>Auth record password confirmation.</td>',oe=p(),K=a("tr"),K.innerHTML=`<td><div class="inline-flex"><span class="label label-warning">Optional</span> <span>verified</span></div></td> <td><span class="label">Boolean</span></td> <td>Indicates whether the auth record is verified or not.
|
||||
import{S as $t,i as qt,s as Tt,V as St,X as ce,W as Ct,h as o,d as $e,t as he,a as ve,I as ae,Z as Ne,_ as pt,C as Mt,$ as Pt,D as Lt,l as r,n as i,m as qe,u as a,A as b,v as p,c as Te,w,J as we,p as Ft,k as Se,o as Ht,L as Ot,H as fe}from"./index-BH0nlDnw.js";import{F as Rt}from"./FieldsQueryParam-DQVKTiQb.js";function mt(s,e,t){const l=s.slice();return l[10]=e[t],l}function bt(s,e,t){const l=s.slice();return l[10]=e[t],l}function _t(s,e,t){const l=s.slice();return l[15]=e[t],l}function kt(s){let e;return{c(){e=a("p"),e.innerHTML="Requires superuser <code>Authorization:TOKEN</code> header",w(e,"class","txt-hint txt-sm txt-right")},m(t,l){r(t,e,l)},d(t){t&&o(e)}}}function yt(s){let e,t,l,c,f,u,_,m,q,y,g,B,S,$,R,P,I,D,M,W,L,T,k,F,ee,z,U,oe,K,X,Y;function ue(h,C){var N,x,O;return C&1&&(u=null),u==null&&(u=!!((O=(x=(N=h[0])==null?void 0:N.fields)==null?void 0:x.find(Yt))!=null&&O.required)),u?Bt:At}let te=ue(s,-1),E=te(s);function Z(h,C){var N,x,O;return C&1&&(I=null),I==null&&(I=!!((O=(x=(N=h[0])==null?void 0:N.fields)==null?void 0:x.find(Xt))!=null&&O.required)),I?Nt:Vt}let G=Z(s,-1),H=G(s);return{c(){e=a("tr"),e.innerHTML='<td colspan="3" class="txt-hint txt-bold">Auth specific fields</td>',t=p(),l=a("tr"),c=a("td"),f=a("div"),E.c(),_=p(),m=a("span"),m.textContent="email",q=p(),y=a("td"),y.innerHTML='<span class="label">String</span>',g=p(),B=a("td"),B.textContent="Auth record email address.",S=p(),$=a("tr"),R=a("td"),P=a("div"),H.c(),D=p(),M=a("span"),M.textContent="emailVisibility",W=p(),L=a("td"),L.innerHTML='<span class="label">Boolean</span>',T=p(),k=a("td"),k.textContent="Whether to show/hide the auth record email when fetching the record data.",F=p(),ee=a("tr"),ee.innerHTML='<td><div class="inline-flex"><span class="label label-success">Required</span> <span>password</span></div></td> <td><span class="label">String</span></td> <td>Auth record password.</td>',z=p(),U=a("tr"),U.innerHTML='<td><div class="inline-flex"><span class="label label-success">Required</span> <span>passwordConfirm</span></div></td> <td><span class="label">String</span></td> <td>Auth record password confirmation.</td>',oe=p(),K=a("tr"),K.innerHTML=`<td><div class="inline-flex"><span class="label label-warning">Optional</span> <span>verified</span></div></td> <td><span class="label">Boolean</span></td> <td>Indicates whether the auth record is verified or not.
|
||||
<br/>
|
||||
This field can be set only by superusers or auth records with "Manage" access.</td>`,X=p(),Y=a("tr"),Y.innerHTML='<td colspan="3" class="txt-hint txt-bold">Other fields</td>',w(f,"class","inline-flex"),w(P,"class","inline-flex")},m(h,C){r(h,e,C),r(h,t,C),r(h,l,C),i(l,c),i(c,f),E.m(f,null),i(f,_),i(f,m),i(l,q),i(l,y),i(l,g),i(l,B),r(h,S,C),r(h,$,C),i($,R),i(R,P),H.m(P,null),i(P,D),i(P,M),i($,W),i($,L),i($,T),i($,k),r(h,F,C),r(h,ee,C),r(h,z,C),r(h,U,C),r(h,oe,C),r(h,K,C),r(h,X,C),r(h,Y,C)},p(h,C){te!==(te=ue(h,C))&&(E.d(1),E=te(h),E&&(E.c(),E.m(f,_))),G!==(G=Z(h,C))&&(H.d(1),H=G(h),H&&(H.c(),H.m(P,D)))},d(h){h&&(o(e),o(t),o(l),o(S),o($),o(F),o(ee),o(z),o(U),o(oe),o(K),o(X),o(Y)),E.d(),H.d()}}}function At(s){let e;return{c(){e=a("span"),e.textContent="Optional",w(e,"class","label label-warning")},m(t,l){r(t,e,l)},d(t){t&&o(e)}}}function Bt(s){let e;return{c(){e=a("span"),e.textContent="Required",w(e,"class","label label-success")},m(t,l){r(t,e,l)},d(t){t&&o(e)}}}function Vt(s){let e;return{c(){e=a("span"),e.textContent="Optional",w(e,"class","label label-warning")},m(t,l){r(t,e,l)},d(t){t&&o(e)}}}function Nt(s){let e;return{c(){e=a("span"),e.textContent="Required",w(e,"class","label label-success")},m(t,l){r(t,e,l)},d(t){t&&o(e)}}}function jt(s){let e;return{c(){e=a("span"),e.textContent="Required",w(e,"class","label label-success")},m(t,l){r(t,e,l)},d(t){t&&o(e)}}}function Jt(s){let e;return{c(){e=a("span"),e.textContent="Optional",w(e,"class","label label-warning")},m(t,l){r(t,e,l)},d(t){t&&o(e)}}}function Dt(s){let e,t=s[15].maxSelect===1?"id":"ids",l,c;return{c(){e=b("Relation record "),l=b(t),c=b(".")},m(f,u){r(f,e,u),r(f,l,u),r(f,c,u)},p(f,u){u&32&&t!==(t=f[15].maxSelect===1?"id":"ids")&&ae(l,t)},d(f){f&&(o(e),o(l),o(c))}}}function Et(s){let e,t,l,c,f,u,_,m,q;return{c(){e=b("File object."),t=a("br"),l=b(`
|
||||
Set to empty value (`),c=a("code"),c.textContent="null",f=b(", "),u=a("code"),u.textContent='""',_=b(" or "),m=a("code"),m.textContent="[]",q=b(`) to delete
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{S as Re,i as Ee,s as Pe,V as Te,X as j,h as p,d as De,t as te,a as le,I as ee,Z as he,_ as Be,C as Ie,$ as Oe,D as Ae,l as f,n as i,m as Ce,u as c,A as $,v as k,c as we,w as m,J as Me,p as qe,k as z,o as Le,W as Se}from"./index-rRnVk674.js";function ke(a,l,s){const n=a.slice();return n[6]=l[s],n}function ge(a,l,s){const n=a.slice();return n[6]=l[s],n}function ve(a){let l;return{c(){l=c("p"),l.innerHTML="Requires superuser <code>Authorization:TOKEN</code> header",m(l,"class","txt-hint txt-sm txt-right")},m(s,n){f(s,l,n)},d(s){s&&p(l)}}}function $e(a,l){let s,n,h;function r(){return l[5](l[6])}return{key:a,first:null,c(){s=c("button"),s.textContent=`${l[6].code} `,m(s,"class","tab-item"),z(s,"active",l[2]===l[6].code),this.first=s},m(o,d){f(o,s,d),n||(h=Le(s,"click",r),n=!0)},p(o,d){l=o,d&20&&z(s,"active",l[2]===l[6].code)},d(o){o&&p(s),n=!1,h()}}}function ye(a,l){let s,n,h,r;return n=new Se({props:{content:l[6].body}}),{key:a,first:null,c(){s=c("div"),we(n.$$.fragment),h=k(),m(s,"class","tab-item"),z(s,"active",l[2]===l[6].code),this.first=s},m(o,d){f(o,s,d),Ce(n,s,null),i(s,h),r=!0},p(o,d){l=o,(!r||d&20)&&z(s,"active",l[2]===l[6].code)},i(o){r||(le(n.$$.fragment,o),r=!0)},o(o){te(n.$$.fragment,o),r=!1},d(o){o&&p(s),De(n)}}}function He(a){var fe,me;let l,s,n=a[0].name+"",h,r,o,d,y,D,F,q=a[0].name+"",J,se,K,C,N,P,V,g,L,ae,S,E,ne,W,H=a[0].name+"",X,oe,Z,ie,G,T,Q,B,Y,I,x,w,O,v=[],ce=new Map,re,A,b=[],de=new Map,R;C=new Te({props:{js:`
|
||||
import{S as Re,i as Ee,s as Pe,V as Te,X as j,h as p,d as De,t as te,a as le,I as ee,Z as he,_ as Be,C as Ie,$ as Oe,D as Ae,l as f,n as i,m as Ce,u as c,A as $,v as k,c as we,w as m,J as Me,p as qe,k as z,o as Le,W as Se}from"./index-BH0nlDnw.js";function ke(a,l,s){const n=a.slice();return n[6]=l[s],n}function ge(a,l,s){const n=a.slice();return n[6]=l[s],n}function ve(a){let l;return{c(){l=c("p"),l.innerHTML="Requires superuser <code>Authorization:TOKEN</code> header",m(l,"class","txt-hint txt-sm txt-right")},m(s,n){f(s,l,n)},d(s){s&&p(l)}}}function $e(a,l){let s,n,h;function r(){return l[5](l[6])}return{key:a,first:null,c(){s=c("button"),s.textContent=`${l[6].code} `,m(s,"class","tab-item"),z(s,"active",l[2]===l[6].code),this.first=s},m(o,d){f(o,s,d),n||(h=Le(s,"click",r),n=!0)},p(o,d){l=o,d&20&&z(s,"active",l[2]===l[6].code)},d(o){o&&p(s),n=!1,h()}}}function ye(a,l){let s,n,h,r;return n=new Se({props:{content:l[6].body}}),{key:a,first:null,c(){s=c("div"),we(n.$$.fragment),h=k(),m(s,"class","tab-item"),z(s,"active",l[2]===l[6].code),this.first=s},m(o,d){f(o,s,d),Ce(n,s,null),i(s,h),r=!0},p(o,d){l=o,(!r||d&20)&&z(s,"active",l[2]===l[6].code)},i(o){r||(le(n.$$.fragment,o),r=!0)},o(o){te(n.$$.fragment,o),r=!1},d(o){o&&p(s),De(n)}}}function He(a){var fe,me;let l,s,n=a[0].name+"",h,r,o,d,y,D,F,q=a[0].name+"",J,se,K,C,N,P,V,g,L,ae,S,E,ne,W,H=a[0].name+"",X,oe,Z,ie,G,T,Q,B,Y,I,x,w,O,v=[],ce=new Map,re,A,b=[],de=new Map,R;C=new Te({props:{js:`
|
||||
import PocketBase from 'pocketbase';
|
||||
|
||||
const pb = new PocketBase('${a[3]}');
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{S as se,i as oe,s as ie,X as K,h as g,t as X,a as V,I as F,Z as le,_ as Re,C as ne,$ as Se,D as ae,l as v,n as u,u as p,v as y,A as U,w as b,k as Y,o as ce,W as Oe,d as x,m as ee,c as te,V as Me,Y as _e,J as Be,p as De,a0 as be}from"./index-rRnVk674.js";function ge(n,e,t){const l=n.slice();return l[4]=e[t],l}function ve(n,e,t){const l=n.slice();return l[4]=e[t],l}function ke(n,e){let t,l=e[4].code+"",d,i,r,a;function m(){return e[3](e[4])}return{key:n,first:null,c(){t=p("button"),d=U(l),i=y(),b(t,"class","tab-item"),Y(t,"active",e[1]===e[4].code),this.first=t},m(k,q){v(k,t,q),u(t,d),u(t,i),r||(a=ce(t,"click",m),r=!0)},p(k,q){e=k,q&4&&l!==(l=e[4].code+"")&&F(d,l),q&6&&Y(t,"active",e[1]===e[4].code)},d(k){k&&g(t),r=!1,a()}}}function $e(n,e){let t,l,d,i;return l=new Oe({props:{content:e[4].body}}),{key:n,first:null,c(){t=p("div"),te(l.$$.fragment),d=y(),b(t,"class","tab-item"),Y(t,"active",e[1]===e[4].code),this.first=t},m(r,a){v(r,t,a),ee(l,t,null),u(t,d),i=!0},p(r,a){e=r;const m={};a&4&&(m.content=e[4].body),l.$set(m),(!i||a&6)&&Y(t,"active",e[1]===e[4].code)},i(r){i||(V(l.$$.fragment,r),i=!0)},o(r){X(l.$$.fragment,r),i=!1},d(r){r&&g(t),x(l)}}}function Ne(n){let e,t,l,d,i,r,a,m=n[0].name+"",k,q,G,H,J,L,z,B,D,S,N,A=[],O=new Map,P,j,T=[],W=new Map,w,E=K(n[2]);const M=c=>c[4].code;for(let c=0;c<E.length;c+=1){let f=ve(n,E,c),s=M(f);O.set(s,A[c]=ke(s,f))}let _=K(n[2]);const Z=c=>c[4].code;for(let c=0;c<_.length;c+=1){let f=ge(n,_,c),s=Z(f);W.set(s,T[c]=$e(s,f))}return{c(){e=p("div"),t=p("strong"),t.textContent="POST",l=y(),d=p("div"),i=p("p"),r=U("/api/collections/"),a=p("strong"),k=U(m),q=U("/confirm-email-change"),G=y(),H=p("div"),H.textContent="Body Parameters",J=y(),L=p("table"),L.innerHTML='<thead><tr><th>Param</th> <th>Type</th> <th width="50%">Description</th></tr></thead> <tbody><tr><td><div class="inline-flex"><span class="label label-success">Required</span> <span>token</span></div></td> <td><span class="label">String</span></td> <td>The token from the change email request email.</td></tr> <tr><td><div class="inline-flex"><span class="label label-success">Required</span> <span>password</span></div></td> <td><span class="label">String</span></td> <td>The account password to confirm the email change.</td></tr></tbody>',z=y(),B=p("div"),B.textContent="Responses",D=y(),S=p("div"),N=p("div");for(let c=0;c<A.length;c+=1)A[c].c();P=y(),j=p("div");for(let c=0;c<T.length;c+=1)T[c].c();b(t,"class","label label-primary"),b(d,"class","content"),b(e,"class","alert alert-success"),b(H,"class","section-title"),b(L,"class","table-compact table-border m-b-base"),b(B,"class","section-title"),b(N,"class","tabs-header compact combined left"),b(j,"class","tabs-content"),b(S,"class","tabs")},m(c,f){v(c,e,f),u(e,t),u(e,l),u(e,d),u(d,i),u(i,r),u(i,a),u(a,k),u(i,q),v(c,G,f),v(c,H,f),v(c,J,f),v(c,L,f),v(c,z,f),v(c,B,f),v(c,D,f),v(c,S,f),u(S,N);for(let s=0;s<A.length;s+=1)A[s]&&A[s].m(N,null);u(S,P),u(S,j);for(let s=0;s<T.length;s+=1)T[s]&&T[s].m(j,null);w=!0},p(c,[f]){(!w||f&1)&&m!==(m=c[0].name+"")&&F(k,m),f&6&&(E=K(c[2]),A=le(A,f,M,1,c,E,O,N,Re,ke,null,ve)),f&6&&(_=K(c[2]),ne(),T=le(T,f,Z,1,c,_,W,j,Se,$e,null,ge),ae())},i(c){if(!w){for(let f=0;f<_.length;f+=1)V(T[f]);w=!0}},o(c){for(let f=0;f<T.length;f+=1)X(T[f]);w=!1},d(c){c&&(g(e),g(G),g(H),g(J),g(L),g(z),g(B),g(D),g(S));for(let f=0;f<A.length;f+=1)A[f].d();for(let f=0;f<T.length;f+=1)T[f].d()}}}function We(n,e,t){let{collection:l}=e,d=204,i=[];const r=a=>t(1,d=a.code);return n.$$set=a=>{"collection"in a&&t(0,l=a.collection)},t(2,i=[{code:204,body:"null"},{code:400,body:`
|
||||
import{S as se,i as oe,s as ie,X as K,h as g,t as X,a as V,I as F,Z as le,_ as Re,C as ne,$ as Se,D as ae,l as v,n as u,u as p,v as y,A as U,w as b,k as Y,o as ce,W as Oe,d as x,m as ee,c as te,V as Me,Y as _e,J as Be,p as De,a0 as be}from"./index-BH0nlDnw.js";function ge(n,e,t){const l=n.slice();return l[4]=e[t],l}function ve(n,e,t){const l=n.slice();return l[4]=e[t],l}function ke(n,e){let t,l=e[4].code+"",d,i,r,a;function m(){return e[3](e[4])}return{key:n,first:null,c(){t=p("button"),d=U(l),i=y(),b(t,"class","tab-item"),Y(t,"active",e[1]===e[4].code),this.first=t},m(k,q){v(k,t,q),u(t,d),u(t,i),r||(a=ce(t,"click",m),r=!0)},p(k,q){e=k,q&4&&l!==(l=e[4].code+"")&&F(d,l),q&6&&Y(t,"active",e[1]===e[4].code)},d(k){k&&g(t),r=!1,a()}}}function $e(n,e){let t,l,d,i;return l=new Oe({props:{content:e[4].body}}),{key:n,first:null,c(){t=p("div"),te(l.$$.fragment),d=y(),b(t,"class","tab-item"),Y(t,"active",e[1]===e[4].code),this.first=t},m(r,a){v(r,t,a),ee(l,t,null),u(t,d),i=!0},p(r,a){e=r;const m={};a&4&&(m.content=e[4].body),l.$set(m),(!i||a&6)&&Y(t,"active",e[1]===e[4].code)},i(r){i||(V(l.$$.fragment,r),i=!0)},o(r){X(l.$$.fragment,r),i=!1},d(r){r&&g(t),x(l)}}}function Ne(n){let e,t,l,d,i,r,a,m=n[0].name+"",k,q,G,H,J,L,z,B,D,S,N,A=[],O=new Map,P,j,T=[],W=new Map,w,E=K(n[2]);const M=c=>c[4].code;for(let c=0;c<E.length;c+=1){let f=ve(n,E,c),s=M(f);O.set(s,A[c]=ke(s,f))}let _=K(n[2]);const Z=c=>c[4].code;for(let c=0;c<_.length;c+=1){let f=ge(n,_,c),s=Z(f);W.set(s,T[c]=$e(s,f))}return{c(){e=p("div"),t=p("strong"),t.textContent="POST",l=y(),d=p("div"),i=p("p"),r=U("/api/collections/"),a=p("strong"),k=U(m),q=U("/confirm-email-change"),G=y(),H=p("div"),H.textContent="Body Parameters",J=y(),L=p("table"),L.innerHTML='<thead><tr><th>Param</th> <th>Type</th> <th width="50%">Description</th></tr></thead> <tbody><tr><td><div class="inline-flex"><span class="label label-success">Required</span> <span>token</span></div></td> <td><span class="label">String</span></td> <td>The token from the change email request email.</td></tr> <tr><td><div class="inline-flex"><span class="label label-success">Required</span> <span>password</span></div></td> <td><span class="label">String</span></td> <td>The account password to confirm the email change.</td></tr></tbody>',z=y(),B=p("div"),B.textContent="Responses",D=y(),S=p("div"),N=p("div");for(let c=0;c<A.length;c+=1)A[c].c();P=y(),j=p("div");for(let c=0;c<T.length;c+=1)T[c].c();b(t,"class","label label-primary"),b(d,"class","content"),b(e,"class","alert alert-success"),b(H,"class","section-title"),b(L,"class","table-compact table-border m-b-base"),b(B,"class","section-title"),b(N,"class","tabs-header compact combined left"),b(j,"class","tabs-content"),b(S,"class","tabs")},m(c,f){v(c,e,f),u(e,t),u(e,l),u(e,d),u(d,i),u(i,r),u(i,a),u(a,k),u(i,q),v(c,G,f),v(c,H,f),v(c,J,f),v(c,L,f),v(c,z,f),v(c,B,f),v(c,D,f),v(c,S,f),u(S,N);for(let s=0;s<A.length;s+=1)A[s]&&A[s].m(N,null);u(S,P),u(S,j);for(let s=0;s<T.length;s+=1)T[s]&&T[s].m(j,null);w=!0},p(c,[f]){(!w||f&1)&&m!==(m=c[0].name+"")&&F(k,m),f&6&&(E=K(c[2]),A=le(A,f,M,1,c,E,O,N,Re,ke,null,ve)),f&6&&(_=K(c[2]),ne(),T=le(T,f,Z,1,c,_,W,j,Se,$e,null,ge),ae())},i(c){if(!w){for(let f=0;f<_.length;f+=1)V(T[f]);w=!0}},o(c){for(let f=0;f<T.length;f+=1)X(T[f]);w=!1},d(c){c&&(g(e),g(G),g(H),g(J),g(L),g(z),g(B),g(D),g(S));for(let f=0;f<A.length;f+=1)A[f].d();for(let f=0;f<T.length;f+=1)T[f].d()}}}function We(n,e,t){let{collection:l}=e,d=204,i=[];const r=a=>t(1,d=a.code);return n.$$set=a=>{"collection"in a&&t(0,l=a.collection)},t(2,i=[{code:204,body:"null"},{code:400,body:`
|
||||
{
|
||||
"status": 400,
|
||||
"message": "An error occurred while validating the submitted data.",
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{S as J,i as N,s as O,W as P,h as Q,d as R,t as W,a as j,I as z,l as D,n as e,m as G,u as t,v as c,A as i,c as K,w as U}from"./index-rRnVk674.js";function V(f){let n,o,u,d,k,s,p,w,g,y,r,F,_,S,b,E,C,a,$,L,q,H,I,M,m,T,v,A,x;return r=new P({props:{content:"?fields=*,"+f[0]+"expand.relField.name"}}),{c(){n=t("tr"),o=t("td"),o.textContent="fields",u=c(),d=t("td"),d.innerHTML='<span class="label">String</span>',k=c(),s=t("td"),p=t("p"),w=i(`Comma separated string of the fields to return in the JSON response
|
||||
import{S as J,i as N,s as O,W as P,h as Q,d as R,t as W,a as j,I as z,l as D,n as e,m as G,u as t,v as c,A as i,c as K,w as U}from"./index-BH0nlDnw.js";function V(f){let n,o,u,d,k,s,p,w,g,y,r,F,_,S,b,E,C,a,$,L,q,H,I,M,m,T,v,A,x;return r=new P({props:{content:"?fields=*,"+f[0]+"expand.relField.name"}}),{c(){n=t("tr"),o=t("td"),o.textContent="fields",u=c(),d=t("td"),d.innerHTML='<span class="label">String</span>',k=c(),s=t("td"),p=t("p"),w=i(`Comma separated string of the fields to return in the JSON response
|
||||
`),g=t("em"),g.textContent="(by default returns all fields)",y=i(`. Ex.:
|
||||
`),K(r.$$.fragment),F=c(),_=t("p"),_.innerHTML="<code>*</code> targets all keys from the specific depth level.",S=c(),b=t("p"),b.textContent="In addition, the following field modifiers are also supported:",E=c(),C=t("ul"),a=t("li"),$=t("code"),$.textContent=":excerpt(maxLength, withEllipsis?)",L=c(),q=t("br"),H=i(`
|
||||
Returns a short plain text version of the field string value.
|
||||
+1
-1
@@ -1 +1 @@
|
||||
import{S as $,i as ee,s as te,H as M,h as ne,l as re,u as ae,w as ie,O as oe,T as le,U as se,Q as de,J as u,y as ce}from"./index-rRnVk674.js";import{c as fe,d as ue,s as ge,h as he,a as ye,E,b as S,e as pe,f as ke,g as me,i as xe,j as be,k as we,l as Ee,m as Se,r as Ke,n as Ce,o as Re,p as Le,C as R,q as G,t as qe,S as ve,u as Oe,v as We}from"./index-CXcDhfsk.js";function _e(e){return new Worker(""+new URL("autocomplete.worker-SdNqUZMM.js",import.meta.url).href,{name:e==null?void 0:e.name})}function Me(e){Q(e,"start");var r={},t=e.languageData||{},g=!1;for(var h in e)if(h!=t&&e.hasOwnProperty(h))for(var f=r[h]=[],i=e[h],a=0;a<i.length;a++){var o=i[a];f.push(new Je(o,e)),(o.indent||o.dedent)&&(g=!0)}return{name:t.name,startState:function(){return{state:"start",pending:null,indent:g?[]:null}},copyState:function(s){var y={state:s.state,pending:s.pending,indent:s.indent&&s.indent.slice(0)};return s.stack&&(y.stack=s.stack.slice(0)),y},token:Ae(r),indent:He(r,t),mergeTokens:t.mergeTokens,languageData:t}}function Q(e,r){if(!e.hasOwnProperty(r))throw new Error("Undefined state "+r+" in simple mode")}function Te(e,r){if(!e)return/(?:)/;var t="";return e instanceof RegExp?(e.ignoreCase&&(t="i"),e=e.source):e=String(e),new RegExp("^(?:"+e+")",t)}function De(e){if(!e)return null;if(e.apply)return e;if(typeof e=="string")return e.replace(/\./g," ");for(var r=[],t=0;t<e.length;t++)r.push(e[t]&&e[t].replace(/\./g," "));return r}function Je(e,r){(e.next||e.push)&&Q(r,e.next||e.push),this.regex=Te(e.regex),this.token=De(e.token),this.data=e}function Ae(e){return function(r,t){if(t.pending){var g=t.pending.shift();return t.pending.length==0&&(t.pending=null),r.pos+=g.text.length,g.token}for(var h=e[t.state],f=0;f<h.length;f++){var i=h[f],a=(!i.data.sol||r.sol())&&r.match(i.regex);if(a){i.data.next?t.state=i.data.next:i.data.push?((t.stack||(t.stack=[])).push(t.state),t.state=i.data.push):i.data.pop&&t.stack&&t.stack.length&&(t.state=t.stack.pop()),i.data.indent&&t.indent.push(r.indentation()+r.indentUnit),i.data.dedent&&t.indent.pop();var o=i.token;if(o&&o.apply&&(o=o(a)),a.length>2&&i.token&&typeof i.token!="string"){t.pending=[];for(var s=2;s<a.length;s++)a[s]&&t.pending.push({text:a[s],token:i.token[s-1]});return r.backUp(a[0].length-(a[1]?a[1].length:0)),o[0]}else return o&&o.join?o[0]:o}}return r.next(),null}}function He(e,r){return function(t,g){if(t.indent==null||r.dontIndentStates&&r.dontIndentStates.indexOf(t.state)>-1)return null;var h=t.indent.length-1,f=e[t.state];e:for(;;){for(var i=0;i<f.length;i++){var a=f[i];if(a.data.dedent&&a.data.dedentIfLineStart!==!1){var o=a.regex.exec(g);if(o&&o[0]){h--,(a.next||a.push)&&(f=e[a.next||a.push]),g=g.slice(o[0].length);continue e}}}break}return h<0?0:t.indent[h]}}function Ie(e){let r;return{c(){r=ae("div"),ie(r,"class","code-editor")},m(t,g){re(t,r,g),e[15](r)},p:M,i:M,o:M,d(t){t&&ne(r),e[15](null)}}}function Be(e){return JSON.stringify([e==null?void 0:e.name,e==null?void 0:e.type,e==null?void 0:e.fields])}function Ue(e,r,t){let g;oe(e,le,n=>t(21,g=n));const h=se();let{id:f=""}=r,{value:i=""}=r,{disabled:a=!1}=r,{placeholder:o=""}=r,{baseCollection:s=null}=r,{singleLine:y=!1}=r,{extraAutocompleteKeys:L=[]}=r,{disableRequestKeys:b=!1}=r,{disableCollectionJoinKeys:m=!1}=r,d,p,q=a,T=new R,D=new R,J=new R,A=new R,v=new _e,H=[],I=[],B=[],K="",O="";function W(){d==null||d.focus()}let _=null;v.onmessage=n=>{B=n.data.baseKeys||[],H=n.data.requestKeys||[],I=n.data.collectionJoinKeys||[]};function V(){clearTimeout(_),_=setTimeout(()=>{v.postMessage({baseCollection:s,collections:Z(g),disableRequestKeys:b,disableCollectionJoinKeys:m})},250)}function Z(n){let c=n.slice();return s&&u.pushOrReplaceByKey(c,s,"id"),c}function U(){p==null||p.dispatchEvent(new CustomEvent("change",{detail:{value:i},bubbles:!0}))}function F(){if(!f)return;const n=document.querySelectorAll('[for="'+f+'"]');for(let c of n)c.removeEventListener("click",W)}function N(){if(!f)return;F();const n=document.querySelectorAll('[for="'+f+'"]');for(let c of n)c.addEventListener("click",W)}function j(n=!0,c=!0){let l=[].concat(L);return l=l.concat(B||[]),n&&(l=l.concat(H||[])),c&&(l=l.concat(I||[])),l}function z(n){var w;let c=n.matchBefore(/[\'\"\@\w\.]*/);if(c&&c.from==c.to&&!n.explicit)return null;let l=We(n.state).resolveInner(n.pos,-1);if(((w=l==null?void 0:l.type)==null?void 0:w.name)=="comment")return null;let x=[{label:"false"},{label:"true"},{label:"@now"},{label:"@second"},{label:"@minute"},{label:"@hour"},{label:"@year"},{label:"@day"},{label:"@month"},{label:"@weekday"},{label:"@yesterday"},{label:"@tomorrow"},{label:"@todayStart"},{label:"@todayEnd"},{label:"@monthStart"},{label:"@monthEnd"},{label:"@yearStart"},{label:"@yearEnd"}];m||x.push({label:"@collection.*",apply:"@collection."});let C=j(!b&&c.text.startsWith("@r"),!m&&c.text.startsWith("@c"));for(const k of C)x.push({label:k.endsWith(".")?k+"*":k,apply:k,boost:k.indexOf("_via_")>0?-1:0});return{from:c.from,options:x}}function P(){return ve.define(Me(Line truncated
|
||||
import{S as $,i as ee,s as te,H as M,h as ne,l as re,u as ae,w as ie,O as oe,T as le,U as se,Q as de,J as u,y as ce}from"./index-BH0nlDnw.js";import{c as fe,d as ue,s as ge,h as he,a as ye,E,b as S,e as pe,f as ke,g as me,i as xe,j as be,k as we,l as Ee,m as Se,r as Ke,n as Ce,o as Re,p as Le,C as R,q as G,t as qe,S as ve,u as Oe,v as We}from"./index-Bd1MzT5k.js";function _e(e){return new Worker(""+new URL("autocomplete.worker-SdNqUZMM.js",import.meta.url).href,{name:e==null?void 0:e.name})}function Me(e){Q(e,"start");var r={},t=e.languageData||{},g=!1;for(var h in e)if(h!=t&&e.hasOwnProperty(h))for(var f=r[h]=[],i=e[h],a=0;a<i.length;a++){var o=i[a];f.push(new Je(o,e)),(o.indent||o.dedent)&&(g=!0)}return{name:t.name,startState:function(){return{state:"start",pending:null,indent:g?[]:null}},copyState:function(s){var y={state:s.state,pending:s.pending,indent:s.indent&&s.indent.slice(0)};return s.stack&&(y.stack=s.stack.slice(0)),y},token:Ae(r),indent:He(r,t),mergeTokens:t.mergeTokens,languageData:t}}function Q(e,r){if(!e.hasOwnProperty(r))throw new Error("Undefined state "+r+" in simple mode")}function Te(e,r){if(!e)return/(?:)/;var t="";return e instanceof RegExp?(e.ignoreCase&&(t="i"),e=e.source):e=String(e),new RegExp("^(?:"+e+")",t)}function De(e){if(!e)return null;if(e.apply)return e;if(typeof e=="string")return e.replace(/\./g," ");for(var r=[],t=0;t<e.length;t++)r.push(e[t]&&e[t].replace(/\./g," "));return r}function Je(e,r){(e.next||e.push)&&Q(r,e.next||e.push),this.regex=Te(e.regex),this.token=De(e.token),this.data=e}function Ae(e){return function(r,t){if(t.pending){var g=t.pending.shift();return t.pending.length==0&&(t.pending=null),r.pos+=g.text.length,g.token}for(var h=e[t.state],f=0;f<h.length;f++){var i=h[f],a=(!i.data.sol||r.sol())&&r.match(i.regex);if(a){i.data.next?t.state=i.data.next:i.data.push?((t.stack||(t.stack=[])).push(t.state),t.state=i.data.push):i.data.pop&&t.stack&&t.stack.length&&(t.state=t.stack.pop()),i.data.indent&&t.indent.push(r.indentation()+r.indentUnit),i.data.dedent&&t.indent.pop();var o=i.token;if(o&&o.apply&&(o=o(a)),a.length>2&&i.token&&typeof i.token!="string"){t.pending=[];for(var s=2;s<a.length;s++)a[s]&&t.pending.push({text:a[s],token:i.token[s-1]});return r.backUp(a[0].length-(a[1]?a[1].length:0)),o[0]}else return o&&o.join?o[0]:o}}return r.next(),null}}function He(e,r){return function(t,g){if(t.indent==null||r.dontIndentStates&&r.dontIndentStates.indexOf(t.state)>-1)return null;var h=t.indent.length-1,f=e[t.state];e:for(;;){for(var i=0;i<f.length;i++){var a=f[i];if(a.data.dedent&&a.data.dedentIfLineStart!==!1){var o=a.regex.exec(g);if(o&&o[0]){h--,(a.next||a.push)&&(f=e[a.next||a.push]),g=g.slice(o[0].length);continue e}}}break}return h<0?0:t.indent[h]}}function Ie(e){let r;return{c(){r=ae("div"),ie(r,"class","code-editor")},m(t,g){re(t,r,g),e[15](r)},p:M,i:M,o:M,d(t){t&&ne(r),e[15](null)}}}function Be(e){return JSON.stringify([e==null?void 0:e.name,e==null?void 0:e.type,e==null?void 0:e.fields])}function Ue(e,r,t){let g;oe(e,le,n=>t(21,g=n));const h=se();let{id:f=""}=r,{value:i=""}=r,{disabled:a=!1}=r,{placeholder:o=""}=r,{baseCollection:s=null}=r,{singleLine:y=!1}=r,{extraAutocompleteKeys:L=[]}=r,{disableRequestKeys:b=!1}=r,{disableCollectionJoinKeys:m=!1}=r,d,p,q=a,T=new R,D=new R,J=new R,A=new R,v=new _e,H=[],I=[],B=[],K="",O="";function W(){d==null||d.focus()}let _=null;v.onmessage=n=>{B=n.data.baseKeys||[],H=n.data.requestKeys||[],I=n.data.collectionJoinKeys||[]};function V(){clearTimeout(_),_=setTimeout(()=>{v.postMessage({baseCollection:s,collections:Z(g),disableRequestKeys:b,disableCollectionJoinKeys:m})},250)}function Z(n){let c=n.slice();return s&&u.pushOrReplaceByKey(c,s,"id"),c}function U(){p==null||p.dispatchEvent(new CustomEvent("change",{detail:{value:i},bubbles:!0}))}function F(){if(!f)return;const n=document.querySelectorAll('[for="'+f+'"]');for(let c of n)c.removeEventListener("click",W)}function N(){if(!f)return;F();const n=document.querySelectorAll('[for="'+f+'"]');for(let c of n)c.addEventListener("click",W)}function j(n=!0,c=!0){let l=[].concat(L);return l=l.concat(B||[]),n&&(l=l.concat(H||[])),c&&(l=l.concat(I||[])),l}function z(n){var w;let c=n.matchBefore(/[\'\"\@\w\.]*/);if(c&&c.from==c.to&&!n.explicit)return null;let l=We(n.state).resolveInner(n.pos,-1);if(((w=l==null?void 0:l.type)==null?void 0:w.name)=="comment")return null;let x=[{label:"false"},{label:"true"},{label:"@now"},{label:"@second"},{label:"@minute"},{label:"@hour"},{label:"@year"},{label:"@day"},{label:"@month"},{label:"@weekday"},{label:"@yesterday"},{label:"@tomorrow"},{label:"@todayStart"},{label:"@todayEnd"},{label:"@monthStart"},{label:"@monthEnd"},{label:"@yearStart"},{label:"@yearEnd"}];m||x.push({label:"@collection.*",apply:"@collection."});let C=j(!b&&c.text.startsWith("@r"),!m&&c.text.startsWith("@c"));for(const k of C)x.push({label:k.endsWith(".")?k+"*":k,apply:k,boost:k.indexOf("_via_")>0?-1:0});return{from:c.from,options:x}}function P(){return ve.define(Me(Line truncated
|
||||
@@ -1,4 +1,4 @@
|
||||
import{a2 as ss,a3 as rs,S as as,i as hs,s as us,H as Ee,h as ae,z as Cn,w as Y,l as he,n as gt,o as _i,u as vt,v as Ae,Q as ls,X as kn,Y as cs,y as fs,j as ds,I as _s,E as ms,a4 as ps,A as gs}from"./index-rRnVk674.js";var di={exports:{}};/* @preserve
|
||||
import{a2 as ss,a3 as rs,S as as,i as hs,s as us,H as Ee,h as ae,z as Cn,w as Y,l as he,n as gt,o as _i,u as vt,v as Ae,Q as ls,X as kn,Y as cs,y as fs,j as ds,I as _s,E as ms,a4 as ps,A as gs}from"./index-BH0nlDnw.js";var di={exports:{}};/* @preserve
|
||||
* Leaflet 1.9.4, a JS library for interactive maps. https://leafletjs.com
|
||||
* (c) 2010-2023 Vladimir Agafonkin, (c) 2010-2011 CloudMade
|
||||
*/(function(C,g){(function(u,v){v(g)})(rs,function(u){var v="1.9.4";function c(t){var e,i,n,o;for(i=1,n=arguments.length;i<n;i++){o=arguments[i];for(e in o)t[e]=o[e]}return t}var P=Object.create||function(){function t(){}return function(e){return t.prototype=e,new t}}();function _(t,e){var i=Array.prototype.slice;if(t.bind)return t.bind.apply(t,i.call(arguments,1));var n=i.call(arguments,2);return function(){return t.apply(e,n.length?n.concat(i.call(arguments)):arguments)}}var B=0;function m(t){return"_leaflet_id"in t||(t._leaflet_id=++B),t._leaflet_id}function K(t,e,i){var n,o,s,r;return r=function(){n=!1,o&&(s.apply(i,o),o=!1)},s=function(){n?o=arguments:(t.apply(i,arguments),setTimeout(r,e),n=!0)},s}function X(t,e,i){var n=e[1],o=e[0],s=n-o;return t===n&&i?t:((t-o)%s+s)%s+o}function A(){return!1}function H(t,e){if(e===!1)return t;var i=Math.pow(10,e===void 0?6:e);return Math.round(t*i)/i}function nt(t){return t.trim?t.trim():t.replace(/^\s+|\s+$/g,"")}function Z(t){return nt(t).split(/\s+/)}function b(t,e){Object.prototype.hasOwnProperty.call(t,"options")||(t.options=t.options?P(t.options):{});for(var i in e)t.options[i]=e[i];return t.options}function I(t,e,i){var n=[];for(var o in t)n.push(encodeURIComponent(i?o.toUpperCase():o)+"="+encodeURIComponent(t[o]));return(!e||e.indexOf("?")===-1?"?":"&")+n.join("&")}var ot=/\{ *([\w_ -]+) *\}/g;function ue(t,e){return t.replace(ot,function(i,n){var o=e[n];if(o===void 0)throw new Error("No value provided for variable "+i);return typeof o=="function"&&(o=o(e)),o})}var J=Array.isArray||function(t){return Object.prototype.toString.call(t)==="[object Array]"};function Vt(t,e){for(var i=0;i<t.length;i++)if(t[i]===e)return i;return-1}var Zt="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=";function qt(t){return window["webkit"+t]||window["moz"+t]||window["ms"+t]}var N=0;function st(t){var e=+new Date,i=Math.max(0,16-(e-N));return N=e+i,window.setTimeout(t,i)}var $=window.requestAnimationFrame||qt("RequestAnimationFrame")||st,le=window.cancelAnimationFrame||qt("CancelAnimationFrame")||qt("CancelRequestAnimationFrame")||function(t){window.clearTimeout(t)};function q(t,e,i){if(i&&$===st)t.call(e);else return $.call(window,_(t,e))}function at(t){t&&le.call(window,t)}var En={__proto__:null,extend:c,create:P,bind:_,get lastId(){return B},stamp:m,throttle:K,wrapNum:X,falseFn:A,formatNum:H,trim:nt,splitWords:Z,setOptions:b,getParamString:I,template:ue,isArray:J,indexOf:Vt,emptyImageUrl:Zt,requestFn:$,cancelFn:le,requestAnimFrame:q,cancelAnimFrame:at};function yt(){}yt.extend=function(t){var e=function(){b(this),this.initialize&&this.initialize.apply(this,arguments),this.callInitHooks()},i=e.__super__=this.prototype,n=P(i);n.constructor=e,e.prototype=n;for(var o in this)Object.prototype.hasOwnProperty.call(this,o)&&o!=="prototype"&&o!=="__super__"&&(e[o]=this[o]);return t.statics&&c(e,t.statics),t.includes&&(On(t.includes),c.apply(null,[n].concat(t.includes))),c(n,t),delete n.statics,delete n.includes,n.options&&(n.options=i.options?P(i.options):{},c(n.options,t.options)),n._initHooks=[],n.callInitHooks=function(){if(!this._initHooksCalled){i.callInitHooks&&i.callInitHooks.call(this),this._initHooksCalled=!0;for(var s=0,r=n._initHooks.length;s<r;s++)n._initHooks[s].call(this)}},e},yt.include=function(t){var e=this.prototype.options;return c(this.prototype,t),t.options&&(this.prototype.options=e,this.mergeOptions(t.options)),this},yt.mergeOptions=function(t){return c(this.prototype.options,t),this},yt.addInitHook=function(t){var e=Array.prototype.slice.call(arguments,1),i=typeof t=="function"?t:function(){this[t].apply(this,e)};return this.prototype._initHooks=this.prototype._initHooks||[],this.prototype._initHooks.push(i),this};function On(t){if(!(typeof L>"u"||!L||!L.Mixin)){t=J(t)?t:[t];for(var e=0;e<t.length;e++)t[e]===L.Mixin.Events&&console.warn("Deprecated include of L.Mixin.Events: this property will be removed in future releases, please inherit from L.Evented instead.",new Error().stack)}}var rt={on:function(t,e,i){if(typeof t=="object")for(var n in t)this._on(n,t[n],e);else{t=Z(t);for(var o=0,s=t.length;o<s;o++)this._on(t[o],e,i)}return this},off:function(t,e,i){if(!arguments.length)delete this._events;else if(typeof t=="object")for(var n in t)this._off(n,t[n],e);else{t=Z(t);for(var o=arguments.length===1,s=0,r=t.length;s<r;s++)o?this._off(t[s]):this._off(t[s],e,i)}return this},_on:function(t,e,i,n){if(typeof e!="function"){console.warn("wrong listener type: "+typeof e);return}if(this._listens(t,e,i)===!1){i===this&&(i=void 0);var o={fn:e,ctx:i};n&&(o.once=!0),this._events=this._events||{},this._events[t]=this._events[t]||[],this._events[t].push(o)}},_off:function(t,e,i){var n,o,s;if(this._events&&(n=this._events[t],!!n)){if(arguments.length===1){if(this._firingCount)for(o=0,s=n.length;o<s;o++)n[o].fn=A;delete this._events[t];return}if(typeof e!="function"){console.warn("wrong listener type: "+typeof e);return}var r=this._listens(t,e,i);if(r!==!1){var a=Line truncated
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{S as el,i as ll,s as sl,H as ze,h as m,l as h,o as nl,u as e,v as s,L as ol,w as a,n as t,A as g,V as al,W as Le,X as ae,d as Kt,Y as il,t as Ct,a as kt,I as ve,Z as Je,_ as rl,C as cl,$ as dl,D as pl,m as Qt,c as Vt,J as Te,p as fl,k as Ae}from"./index-rRnVk674.js";import{F as ul}from"./FieldsQueryParam-BEgqkb0I.js";function ml(r){let n,o,i;return{c(){n=e("span"),n.textContent="Show details",o=s(),i=e("i"),a(n,"class","txt"),a(i,"class","ri-arrow-down-s-line")},m(f,b){h(f,n,b),h(f,o,b),h(f,i,b)},d(f){f&&(m(n),m(o),m(i))}}}function hl(r){let n,o,i;return{c(){n=e("span"),n.textContent="Hide details",o=s(),i=e("i"),a(n,"class","txt"),a(i,"class","ri-arrow-up-s-line")},m(f,b){h(f,n,b),h(f,o,b),h(f,i,b)},d(f){f&&(m(n),m(o),m(i))}}}function Ke(r){let n,o,i,f,b,p,u,C,_,x,d,Y,yt,Wt,E,Xt,D,it,P,Z,ie,j,U,re,rt,vt,tt,Ft,ce,ct,dt,et,N,Yt,Lt,k,lt,At,Zt,Tt,z,st,Pt,te,Rt,v,pt,Ot,de,ft,pe,H,St,nt,Et,F,ut,fe,J,Nt,ee,qt,le,Dt,ue,L,mt,me,ht,he,M,be,T,Ht,ot,Mt,K,bt,ge,I,It,y,Bt,at,Gt,_e,Q,gt,we,_t,xe,jt,$e,B,Ut,Ce,G,ke,wt,se,R,xt,V,W,O,zt,ne,X;return{c(){n=e("p"),n.innerHTML=`The syntax basically follows the format
|
||||
import{S as el,i as ll,s as sl,H as ze,h as m,l as h,o as nl,u as e,v as s,L as ol,w as a,n as t,A as g,V as al,W as Le,X as ae,d as Kt,Y as il,t as Ct,a as kt,I as ve,Z as Je,_ as rl,C as cl,$ as dl,D as pl,m as Qt,c as Vt,J as Te,p as fl,k as Ae}from"./index-BH0nlDnw.js";import{F as ul}from"./FieldsQueryParam-DQVKTiQb.js";function ml(r){let n,o,i;return{c(){n=e("span"),n.textContent="Show details",o=s(),i=e("i"),a(n,"class","txt"),a(i,"class","ri-arrow-down-s-line")},m(f,b){h(f,n,b),h(f,o,b),h(f,i,b)},d(f){f&&(m(n),m(o),m(i))}}}function hl(r){let n,o,i;return{c(){n=e("span"),n.textContent="Hide details",o=s(),i=e("i"),a(n,"class","txt"),a(i,"class","ri-arrow-up-s-line")},m(f,b){h(f,n,b),h(f,o,b),h(f,i,b)},d(f){f&&(m(n),m(o),m(i))}}}function Ke(r){let n,o,i,f,b,p,u,C,_,x,d,Y,yt,Wt,E,Xt,D,it,P,Z,ie,j,U,re,rt,vt,tt,Ft,ce,ct,dt,et,N,Yt,Lt,k,lt,At,Zt,Tt,z,st,Pt,te,Rt,v,pt,Ot,de,ft,pe,H,St,nt,Et,F,ut,fe,J,Nt,ee,qt,le,Dt,ue,L,mt,me,ht,he,M,be,T,Ht,ot,Mt,K,bt,ge,I,It,y,Bt,at,Gt,_e,Q,gt,we,_t,xe,jt,$e,B,Ut,Ce,G,ke,wt,se,R,xt,V,W,O,zt,ne,X;return{c(){n=e("p"),n.innerHTML=`The syntax basically follows the format
|
||||
<code><span class="txt-success">OPERAND</span> <span class="txt-danger">OPERATOR</span> <span class="txt-success">OPERAND</span></code>, where:`,o=s(),i=e("ul"),f=e("li"),f.innerHTML=`<code class="txt-success">OPERAND</code> - could be any of the above field literal, string (single
|
||||
or double quoted), number, null, true, false`,b=s(),p=e("li"),u=e("code"),u.textContent="OPERATOR",C=g(` - is one of:
|
||||
`),_=e("br"),x=s(),d=e("ul"),Y=e("li"),yt=e("code"),yt.textContent="=",Wt=s(),E=e("span"),E.textContent="Equal",Xt=s(),D=e("li"),it=e("code"),it.textContent="!=",P=s(),Z=e("span"),Z.textContent="NOT equal",ie=s(),j=e("li"),U=e("code"),U.textContent=">",re=s(),rt=e("span"),rt.textContent="Greater than",vt=s(),tt=e("li"),Ft=e("code"),Ft.textContent=">=",ce=s(),ct=e("span"),ct.textContent="Greater than or equal",dt=s(),et=e("li"),N=e("code"),N.textContent="<",Yt=s(),Lt=e("span"),Lt.textContent="Less than",k=s(),lt=e("li"),At=e("code"),At.textContent="<=",Zt=s(),Tt=e("span"),Tt.textContent="Less than or equal",z=s(),st=e("li"),Pt=e("code"),Pt.textContent="~",te=s(),Rt=e("span"),Rt.textContent=`Like/Contains (if not specified auto wraps the right string OPERAND in a "%" for
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
import{S as W,i as G,s as J,F as Q,d as S,t as E,a as O,m as j,c as D,r as M,g as V,p as C,b as X,e as Y,f as K,h as m,j as Z,k as z,l as h,n as T,o as I,q as x,u as k,v as q,w as r,x as ee,y as U,z as A,A as N,B as te}from"./index-rRnVk674.js";function ne(s){let t,o,u,n,e,p,_,d;return{c(){t=k("label"),o=N("Email"),n=q(),e=k("input"),r(t,"for",u=s[20]),r(e,"type","email"),r(e,"autocomplete","off"),r(e,"id",p=s[20]),e.disabled=s[7],e.required=!0},m(a,i){h(a,t,i),T(t,o),h(a,n,i),h(a,e,i),s[11](e),A(e,s[2]),_||(d=I(e,"input",s[12]),_=!0)},p(a,i){i&1048576&&u!==(u=a[20])&&r(t,"for",u),i&1048576&&p!==(p=a[20])&&r(e,"id",p),i&128&&(e.disabled=a[7]),i&4&&e.value!==a[2]&&A(e,a[2])},d(a){a&&(m(t),m(n),m(e)),s[11](null),_=!1,d()}}}function le(s){let t,o,u,n,e,p,_,d,a,i;return{c(){t=k("label"),o=N("Password"),n=q(),e=k("input"),_=q(),d=k("div"),d.textContent="Recommended at least 10 characters.",r(t,"for",u=s[20]),r(e,"type","password"),r(e,"autocomplete","new-password"),r(e,"minlength","10"),r(e,"id",p=s[20]),e.disabled=s[7],e.required=!0,r(d,"class","help-block")},m(c,g){h(c,t,g),T(t,o),h(c,n,g),h(c,e,g),A(e,s[3]),h(c,_,g),h(c,d,g),a||(i=I(e,"input",s[13]),a=!0)},p(c,g){g&1048576&&u!==(u=c[20])&&r(t,"for",u),g&1048576&&p!==(p=c[20])&&r(e,"id",p),g&128&&(e.disabled=c[7]),g&8&&e.value!==c[3]&&A(e,c[3])},d(c){c&&(m(t),m(n),m(e),m(_),m(d)),a=!1,i()}}}function se(s){let t,o,u,n,e,p,_,d;return{c(){t=k("label"),o=N("Password confirm"),n=q(),e=k("input"),r(t,"for",u=s[20]),r(e,"type","password"),r(e,"minlength","10"),r(e,"id",p=s[20]),e.disabled=s[7],e.required=!0},m(a,i){h(a,t,i),T(t,o),h(a,n,i),h(a,e,i),A(e,s[4]),_||(d=I(e,"input",s[14]),_=!0)},p(a,i){i&1048576&&u!==(u=a[20])&&r(t,"for",u),i&1048576&&p!==(p=a[20])&&r(e,"id",p),i&128&&(e.disabled=a[7]),i&16&&e.value!==a[4]&&A(e,a[4])},d(a){a&&(m(t),m(n),m(e)),_=!1,d()}}}function ie(s){let t,o,u,n,e,p,_,d,a,i,c,g,B,w,F,$,v,y,L;return n=new K({props:{class:"form-field required",name:"email",$$slots:{default:[ne,({uniqueId:l})=>({20:l}),({uniqueId:l})=>l?1048576:0]},$$scope:{ctx:s}}}),p=new K({props:{class:"form-field required",name:"password",$$slots:{default:[le,({uniqueId:l})=>({20:l}),({uniqueId:l})=>l?1048576:0]},$$scope:{ctx:s}}}),d=new K({props:{class:"form-field required",name:"passwordConfirm",$$slots:{default:[se,({uniqueId:l})=>({20:l}),({uniqueId:l})=>l?1048576:0]},$$scope:{ctx:s}}}),{c(){t=k("form"),o=k("div"),o.innerHTML="<h4>Create your first superuser account in order to continue</h4>",u=q(),D(n.$$.fragment),e=q(),D(p.$$.fragment),_=q(),D(d.$$.fragment),a=q(),i=k("button"),i.innerHTML='<span class="txt">Create superuser and login</span> <i class="ri-arrow-right-line"></i>',c=q(),g=k("hr"),B=q(),w=k("label"),w.innerHTML='<i class="ri-upload-cloud-line"></i> <span class="txt">Or initialize from backup</span>',F=q(),$=k("input"),r(o,"class","content txt-center m-b-base"),r(i,"type","submit"),r(i,"class","btn btn-lg btn-block btn-next"),z(i,"btn-disabled",s[7]),z(i,"btn-loading",s[0]),r(t,"class","block"),r(t,"autocomplete","off"),r(w,"for","backupFileInput"),r(w,"class","btn btn-lg btn-hint btn-transparent btn-block"),z(w,"btn-disabled",s[7]),z(w,"btn-loading",s[1]),r($,"id","backupFileInput"),r($,"type","file"),r($,"class","hidden"),r($,"accept",".zip")},m(l,b){h(l,t,b),T(t,o),T(t,u),j(n,t,null),T(t,e),j(p,t,null),T(t,_),j(d,t,null),T(t,a),T(t,i),h(l,c,b),h(l,g,b),h(l,B,b),h(l,w,b),h(l,F,b),h(l,$,b),s[15]($),v=!0,y||(L=[I(t,"submit",x(s[8])),I($,"change",s[16])],y=!0)},p(l,b){const H={};b&3145892&&(H.$$scope={dirty:b,ctx:l}),n.$set(H);const f={};b&3145864&&(f.$$scope={dirty:b,ctx:l}),p.$set(f);const P={};b&3145872&&(P.$$scope={dirty:b,ctx:l}),d.$set(P),(!v||b&128)&&z(i,"btn-disabled",l[7]),(!v||b&1)&&z(i,"btn-loading",l[0]),(!v||b&128)&&z(w,"btn-disabled",l[7]),(!v||b&2)&&z(w,"btn-loading",l[1])},i(l){v||(O(n.$$.fragment,l),O(p.$$.fragment,l),O(d.$$.fragment,l),v=!0)},o(l){E(n.$$.fragment,l),E(p.$$.fragment,l),E(d.$$.fragment,l),v=!1},d(l){l&&(m(t),m(c),m(g),m(B),m(w),m(F),m($)),S(n),S(p),S(d),s[15](null),y=!1,Z(L)}}}function ae(s){let t,o;return t=new Q({props:{$$slots:{default:[ie]},$$scope:{ctx:s}}}),{c(){D(t.$$.fragment)},m(u,n){j(t,u,n),o=!0},p(u,[n]){const e={};n&2097407&&(e.$$scope={dirty:n,ctx:u}),t.$set(e)},i(u){o||(O(t.$$.fragment,u),o=!0)},o(u){E(t.$$.fragment,u),o=!1},d(u){S(t,u)}}}function oe(s,t,o){let u,{params:n}=t,e="",p="",_="",d=!1,a=!1,i,c;g();async function g(){if(!(n!=null&&n.token))return M("/");o(0,d=!0);try{const f=V(n==null?void 0:n.token);await C.collection("_superusers").getOne(f.id,{requestKey:"installer_token_check",headers:{Authorization:n==null?void 0:n.token}})}catch(f){f!=null&&f.isAbort||(X("The installer token is invalid or has expired."),M("/"))}o(0,d=!1),await Y(),i==null||i.focus()}async function B(){if(!u){o(0,d=!0);try{await C.collection("_superusers").create({email:e,password:p,passwordConfirm:_},{headers:{Authorization:n==null?void 0:n.token}}),await C.collection("_superusers").authWithPassword(e,p),M("/")}catch(f){C.eLine truncated
|
||||
import{S as W,i as G,s as J,F as Q,d as S,t as E,a as O,m as j,c as D,r as M,g as V,p as C,b as X,e as Y,f as K,h as m,j as Z,k as z,l as h,n as T,o as I,q as x,u as k,v as q,w as r,x as ee,y as U,z as A,A as N,B as te}from"./index-BH0nlDnw.js";function ne(s){let t,o,u,n,e,p,_,d;return{c(){t=k("label"),o=N("Email"),n=q(),e=k("input"),r(t,"for",u=s[20]),r(e,"type","email"),r(e,"autocomplete","off"),r(e,"id",p=s[20]),e.disabled=s[7],e.required=!0},m(a,i){h(a,t,i),T(t,o),h(a,n,i),h(a,e,i),s[11](e),A(e,s[2]),_||(d=I(e,"input",s[12]),_=!0)},p(a,i){i&1048576&&u!==(u=a[20])&&r(t,"for",u),i&1048576&&p!==(p=a[20])&&r(e,"id",p),i&128&&(e.disabled=a[7]),i&4&&e.value!==a[2]&&A(e,a[2])},d(a){a&&(m(t),m(n),m(e)),s[11](null),_=!1,d()}}}function le(s){let t,o,u,n,e,p,_,d,a,i;return{c(){t=k("label"),o=N("Password"),n=q(),e=k("input"),_=q(),d=k("div"),d.textContent="Recommended at least 10 characters.",r(t,"for",u=s[20]),r(e,"type","password"),r(e,"autocomplete","new-password"),r(e,"minlength","10"),r(e,"id",p=s[20]),e.disabled=s[7],e.required=!0,r(d,"class","help-block")},m(c,g){h(c,t,g),T(t,o),h(c,n,g),h(c,e,g),A(e,s[3]),h(c,_,g),h(c,d,g),a||(i=I(e,"input",s[13]),a=!0)},p(c,g){g&1048576&&u!==(u=c[20])&&r(t,"for",u),g&1048576&&p!==(p=c[20])&&r(e,"id",p),g&128&&(e.disabled=c[7]),g&8&&e.value!==c[3]&&A(e,c[3])},d(c){c&&(m(t),m(n),m(e),m(_),m(d)),a=!1,i()}}}function se(s){let t,o,u,n,e,p,_,d;return{c(){t=k("label"),o=N("Password confirm"),n=q(),e=k("input"),r(t,"for",u=s[20]),r(e,"type","password"),r(e,"minlength","10"),r(e,"id",p=s[20]),e.disabled=s[7],e.required=!0},m(a,i){h(a,t,i),T(t,o),h(a,n,i),h(a,e,i),A(e,s[4]),_||(d=I(e,"input",s[14]),_=!0)},p(a,i){i&1048576&&u!==(u=a[20])&&r(t,"for",u),i&1048576&&p!==(p=a[20])&&r(e,"id",p),i&128&&(e.disabled=a[7]),i&16&&e.value!==a[4]&&A(e,a[4])},d(a){a&&(m(t),m(n),m(e)),_=!1,d()}}}function ie(s){let t,o,u,n,e,p,_,d,a,i,c,g,B,w,F,$,v,y,L;return n=new K({props:{class:"form-field required",name:"email",$$slots:{default:[ne,({uniqueId:l})=>({20:l}),({uniqueId:l})=>l?1048576:0]},$$scope:{ctx:s}}}),p=new K({props:{class:"form-field required",name:"password",$$slots:{default:[le,({uniqueId:l})=>({20:l}),({uniqueId:l})=>l?1048576:0]},$$scope:{ctx:s}}}),d=new K({props:{class:"form-field required",name:"passwordConfirm",$$slots:{default:[se,({uniqueId:l})=>({20:l}),({uniqueId:l})=>l?1048576:0]},$$scope:{ctx:s}}}),{c(){t=k("form"),o=k("div"),o.innerHTML="<h4>Create your first superuser account in order to continue</h4>",u=q(),D(n.$$.fragment),e=q(),D(p.$$.fragment),_=q(),D(d.$$.fragment),a=q(),i=k("button"),i.innerHTML='<span class="txt">Create superuser and login</span> <i class="ri-arrow-right-line"></i>',c=q(),g=k("hr"),B=q(),w=k("label"),w.innerHTML='<i class="ri-upload-cloud-line"></i> <span class="txt">Or initialize from backup</span>',F=q(),$=k("input"),r(o,"class","content txt-center m-b-base"),r(i,"type","submit"),r(i,"class","btn btn-lg btn-block btn-next"),z(i,"btn-disabled",s[7]),z(i,"btn-loading",s[0]),r(t,"class","block"),r(t,"autocomplete","off"),r(w,"for","backupFileInput"),r(w,"class","btn btn-lg btn-hint btn-transparent btn-block"),z(w,"btn-disabled",s[7]),z(w,"btn-loading",s[1]),r($,"id","backupFileInput"),r($,"type","file"),r($,"class","hidden"),r($,"accept",".zip")},m(l,b){h(l,t,b),T(t,o),T(t,u),j(n,t,null),T(t,e),j(p,t,null),T(t,_),j(d,t,null),T(t,a),T(t,i),h(l,c,b),h(l,g,b),h(l,B,b),h(l,w,b),h(l,F,b),h(l,$,b),s[15]($),v=!0,y||(L=[I(t,"submit",x(s[8])),I($,"change",s[16])],y=!0)},p(l,b){const H={};b&3145892&&(H.$$scope={dirty:b,ctx:l}),n.$set(H);const f={};b&3145864&&(f.$$scope={dirty:b,ctx:l}),p.$set(f);const P={};b&3145872&&(P.$$scope={dirty:b,ctx:l}),d.$set(P),(!v||b&128)&&z(i,"btn-disabled",l[7]),(!v||b&1)&&z(i,"btn-loading",l[0]),(!v||b&128)&&z(w,"btn-disabled",l[7]),(!v||b&2)&&z(w,"btn-loading",l[1])},i(l){v||(O(n.$$.fragment,l),O(p.$$.fragment,l),O(d.$$.fragment,l),v=!0)},o(l){E(n.$$.fragment,l),E(p.$$.fragment,l),E(d.$$.fragment,l),v=!1},d(l){l&&(m(t),m(c),m(g),m(B),m(w),m(F),m($)),S(n),S(p),S(d),s[15](null),y=!1,Z(L)}}}function ae(s){let t,o;return t=new Q({props:{$$slots:{default:[ie]},$$scope:{ctx:s}}}),{c(){D(t.$$.fragment)},m(u,n){j(t,u,n),o=!0},p(u,[n]){const e={};n&2097407&&(e.$$scope={dirty:n,ctx:u}),t.$set(e)},i(u){o||(O(t.$$.fragment,u),o=!0)},o(u){E(t.$$.fragment,u),o=!1},d(u){S(t,u)}}}function oe(s,t,o){let u,{params:n}=t,e="",p="",_="",d=!1,a=!1,i,c;g();async function g(){if(!(n!=null&&n.token))return M("/");o(0,d=!0);try{const f=V(n==null?void 0:n.token);await C.collection("_superusers").getOne(f.id,{requestKey:"installer_token_check",headers:{Authorization:n==null?void 0:n.token}})}catch(f){f!=null&&f.isAbort||(X("The installer token is invalid or has expired."),M("/"))}o(0,d=!1),await Y(),i==null||i.focus()}async function B(){if(!u){o(0,d=!0);try{await C.collection("_superusers").create({email:e,password:p,passwordConfirm:_},{headers:{Authorization:n==null?void 0:n.token}}),await C.collection("_superusers").authWithPassword(e,p),M("/")}catch(f){C.eLine truncated
|
||||
|
||||
Do you really want to upload and initialize "${f.name}"?`,()=>{$(f)},()=>{w()})}async function $(f){if(!(!f||u)){o(1,a=!0);try{await C.backups.upload({file:f},{headers:{Authorization:n==null?void 0:n.token}}),await C.backups.restore(f.name,{headers:{Authorization:n==null?void 0:n.token}}),te("Please wait while extracting the uploaded archive!"),await new Promise(P=>setTimeout(P,2e3)),M("/")}catch(P){C.error(P)}w(),o(1,a=!1)}}function v(f){U[f?"unshift":"push"](()=>{i=f,o(5,i)})}function y(){e=this.value,o(2,e)}function L(){p=this.value,o(3,p)}function l(){_=this.value,o(4,_)}function b(f){U[f?"unshift":"push"](()=>{c=f,o(6,c)})}const H=f=>{var P,R;F((R=(P=f.target)==null?void 0:P.files)==null?void 0:R[0])};return s.$$set=f=>{"params"in f&&o(10,n=f.params)},s.$$.update=()=>{s.$$.dirty&3&&o(7,u=d||a)},[d,a,e,p,_,i,c,u,B,F,n,v,y,L,l,b,H]}class re extends W{constructor(t){super(),G(this,t,oe,ae,J,{params:10})}}export{re as default};
|
||||
+1
-1
@@ -1 +1 @@
|
||||
import{S as r,i as c,s as l,H as n,h as u,l as h,u as p,w as d,O as f,P as m,Q as g,R as o}from"./index-rRnVk674.js";function _(s){let t;return{c(){t=p("div"),t.innerHTML='<h3 class="m-b-sm">Auth failed.</h3> <h5>You can close this window and go back to the app to try again.</h5>',d(t,"class","content txt-hint txt-center p-base")},m(e,a){h(e,t,a)},p:n,i:n,o:n,d(e){e&&u(t)}}}function b(s,t,e){let a;return f(s,o,i=>e(0,a=i)),m(o,a="OAuth2 auth failed",a),g(()=>{window.close()}),[]}class x extends r{constructor(t){super(),c(this,t,b,_,l,{})}}export{x as default};
|
||||
import{S as r,i as c,s as l,H as n,h as u,l as h,u as p,w as d,O as f,P as m,Q as g,R as o}from"./index-BH0nlDnw.js";function _(s){let t;return{c(){t=p("div"),t.innerHTML='<h3 class="m-b-sm">Auth failed.</h3> <h5>You can close this window and go back to the app to try again.</h5>',d(t,"class","content txt-hint txt-center p-base")},m(e,a){h(e,t,a)},p:n,i:n,o:n,d(e){e&&u(t)}}}function b(s,t,e){let a;return f(s,o,i=>e(0,a=i)),m(o,a="OAuth2 auth failed",a),g(()=>{window.close()}),[]}class x extends r{constructor(t){super(),c(this,t,b,_,l,{})}}export{x as default};
|
||||
+1
-1
@@ -1 +1 @@
|
||||
import{S as i,i as r,s as u,H as n,h as l,l as p,u as h,w as d,O as m,P as f,Q as _,R as o}from"./index-rRnVk674.js";function b(a){let t;return{c(){t=h("div"),t.innerHTML='<h3 class="m-b-sm">Auth completed.</h3> <h5>You can close this window and go back to the app.</h5>',d(t,"class","content txt-hint txt-center p-base")},m(e,s){p(e,t,s)},p:n,i:n,o:n,d(e){e&&l(t)}}}function g(a,t,e){let s;return m(a,o,c=>e(0,s=c)),f(o,s="OAuth2 auth completed",s),_(()=>{window.close()}),[]}class x extends i{constructor(t){super(),r(this,t,g,b,u,{})}}export{x as default};
|
||||
import{S as i,i as r,s as u,H as n,h as l,l as p,u as h,w as d,O as m,P as f,Q as _,R as o}from"./index-BH0nlDnw.js";function b(a){let t;return{c(){t=h("div"),t.innerHTML='<h3 class="m-b-sm">Auth completed.</h3> <h5>You can close this window and go back to the app.</h5>',d(t,"class","content txt-hint txt-center p-base")},m(e,s){p(e,t,s)},p:n,i:n,o:n,d(e){e&&l(t)}}}function g(a,t,e){let s;return m(a,o,c=>e(0,s=c)),f(o,s="OAuth2 auth completed",s),_(()=>{window.close()}),[]}class x extends i{constructor(t){super(),r(this,t,g,b,u,{})}}export{x as default};
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
import{S as J,i as M,s as z,F as A,d as L,t as h,a as v,m as S,c as I,J as D,h as _,D as N,l as b,L as R,M as W,g as Y,p as j,H as P,o as q,u as m,v as y,w as p,f as B,k as T,n as g,q as G,A as C,I as K,z as F,C as O}from"./index-rRnVk674.js";function Q(i){let e,t,n,l,s,o,f,a,r,u,k,$,d=i[3]&&H(i);return o=new B({props:{class:"form-field required",name:"password",$$slots:{default:[V,({uniqueId:c})=>({8:c}),({uniqueId:c})=>c?256:0]},$$scope:{ctx:i}}}),{c(){e=m("form"),t=m("div"),n=m("h5"),l=C(`Type your password to confirm changing your email address
|
||||
import{S as J,i as M,s as z,F as A,d as L,t as h,a as v,m as S,c as I,J as D,h as _,D as N,l as b,L as R,M as W,g as Y,p as j,H as P,o as q,u as m,v as y,w as p,f as B,k as T,n as g,q as G,A as C,I as K,z as F,C as O}from"./index-BH0nlDnw.js";function Q(i){let e,t,n,l,s,o,f,a,r,u,k,$,d=i[3]&&H(i);return o=new B({props:{class:"form-field required",name:"password",$$slots:{default:[V,({uniqueId:c})=>({8:c}),({uniqueId:c})=>c?256:0]},$$scope:{ctx:i}}}),{c(){e=m("form"),t=m("div"),n=m("h5"),l=C(`Type your password to confirm changing your email address
|
||||
`),d&&d.c(),s=y(),I(o.$$.fragment),f=y(),a=m("button"),r=m("span"),r.textContent="Confirm new email",p(t,"class","content txt-center m-b-base"),p(r,"class","txt"),p(a,"type","submit"),p(a,"class","btn btn-lg btn-block"),a.disabled=i[1],T(a,"btn-loading",i[1])},m(c,w){b(c,e,w),g(e,t),g(t,n),g(n,l),d&&d.m(n,null),g(e,s),S(o,e,null),g(e,f),g(e,a),g(a,r),u=!0,k||($=q(e,"submit",G(i[4])),k=!0)},p(c,w){c[3]?d?d.p(c,w):(d=H(c),d.c(),d.m(n,null)):d&&(d.d(1),d=null);const E={};w&769&&(E.$$scope={dirty:w,ctx:c}),o.$set(E),(!u||w&2)&&(a.disabled=c[1]),(!u||w&2)&&T(a,"btn-loading",c[1])},i(c){u||(v(o.$$.fragment,c),u=!0)},o(c){h(o.$$.fragment,c),u=!1},d(c){c&&_(e),d&&d.d(),L(o),k=!1,$()}}}function U(i){let e,t,n,l,s;return{c(){e=m("div"),e.innerHTML='<div class="icon"><i class="ri-checkbox-circle-line"></i></div> <div class="content txt-bold"><p>Successfully changed the user email address.</p> <p>You can now sign in with your new email address.</p></div>',t=y(),n=m("button"),n.textContent="Close",p(e,"class","alert alert-success"),p(n,"type","button"),p(n,"class","btn btn-transparent btn-block")},m(o,f){b(o,e,f),b(o,t,f),b(o,n,f),l||(s=q(n,"click",i[6]),l=!0)},p:P,i:P,o:P,d(o){o&&(_(e),_(t),_(n)),l=!1,s()}}}function H(i){let e,t,n;return{c(){e=C("to "),t=m("strong"),n=C(i[3]),p(t,"class","txt-nowrap")},m(l,s){b(l,e,s),b(l,t,s),g(t,n)},p(l,s){s&8&&K(n,l[3])},d(l){l&&(_(e),_(t))}}}function V(i){let e,t,n,l,s,o,f,a;return{c(){e=m("label"),t=C("Password"),l=y(),s=m("input"),p(e,"for",n=i[8]),p(s,"type","password"),p(s,"id",o=i[8]),s.required=!0,s.autofocus=!0},m(r,u){b(r,e,u),g(e,t),b(r,l,u),b(r,s,u),F(s,i[0]),s.focus(),f||(a=q(s,"input",i[7]),f=!0)},p(r,u){u&256&&n!==(n=r[8])&&p(e,"for",n),u&256&&o!==(o=r[8])&&p(s,"id",o),u&1&&s.value!==r[0]&&F(s,r[0])},d(r){r&&(_(e),_(l),_(s)),f=!1,a()}}}function X(i){let e,t,n,l;const s=[U,Q],o=[];function f(a,r){return a[2]?0:1}return e=f(i),t=o[e]=s[e](i),{c(){t.c(),n=R()},m(a,r){o[e].m(a,r),b(a,n,r),l=!0},p(a,r){let u=e;e=f(a),e===u?o[e].p(a,r):(O(),h(o[u],1,1,()=>{o[u]=null}),N(),t=o[e],t?t.p(a,r):(t=o[e]=s[e](a),t.c()),v(t,1),t.m(n.parentNode,n))},i(a){l||(v(t),l=!0)},o(a){h(t),l=!1},d(a){a&&_(n),o[e].d(a)}}}function Z(i){let e,t;return e=new A({props:{nobranding:!0,$$slots:{default:[X]},$$scope:{ctx:i}}}),{c(){I(e.$$.fragment)},m(n,l){S(e,n,l),t=!0},p(n,[l]){const s={};l&527&&(s.$$scope={dirty:l,ctx:n}),e.$set(s)},i(n){t||(v(e.$$.fragment,n),t=!0)},o(n){h(e.$$.fragment,n),t=!1},d(n){L(e,n)}}}function x(i,e,t){let n,{params:l}=e,s="",o=!1,f=!1;async function a(){if(o)return;t(1,o=!0);const k=new W("../");try{const $=Y(l==null?void 0:l.token);await k.collection($.collectionId).confirmEmailChange(l==null?void 0:l.token,s),t(2,f=!0)}catch($){j.error($)}t(1,o=!1)}const r=()=>window.close();function u(){s=this.value,t(0,s)}return i.$$set=k=>{"params"in k&&t(5,l=k.params)},i.$$.update=()=>{i.$$.dirty&32&&t(3,n=D.getJWTPayload(l==null?void 0:l.token).newEmail||"")},[s,o,f,n,a,l,r,u]}class te extends J{constructor(e){super(),M(this,e,x,Z,z,{params:5})}}export{te as default};
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
import{S as A,i as D,s as W,F as Y,d as H,t as P,a as q,m as L,c as N,J as j,h as _,C as B,D as E,l as m,L as G,M as K,g as O,p as Q,H as F,o as S,u as b,v as C,w as p,f as J,k as M,n as w,q as U,A as y,I as V,z as R}from"./index-rRnVk674.js";function X(a){let e,l,s,n,t,o,c,r,i,u,v,g,k,h,d=a[4]&&z(a);return o=new J({props:{class:"form-field required",name:"password",$$slots:{default:[x,({uniqueId:f})=>({10:f}),({uniqueId:f})=>f?1024:0]},$$scope:{ctx:a}}}),r=new J({props:{class:"form-field required",name:"passwordConfirm",$$slots:{default:[ee,({uniqueId:f})=>({10:f}),({uniqueId:f})=>f?1024:0]},$$scope:{ctx:a}}}),{c(){e=b("form"),l=b("div"),s=b("h5"),n=y(`Reset your user password
|
||||
import{S as A,i as D,s as W,F as Y,d as H,t as P,a as q,m as L,c as N,J as j,h as _,C as B,D as E,l as m,L as G,M as K,g as O,p as Q,H as F,o as S,u as b,v as C,w as p,f as J,k as M,n as w,q as U,A as y,I as V,z as R}from"./index-BH0nlDnw.js";function X(a){let e,l,s,n,t,o,c,r,i,u,v,g,k,h,d=a[4]&&z(a);return o=new J({props:{class:"form-field required",name:"password",$$slots:{default:[x,({uniqueId:f})=>({10:f}),({uniqueId:f})=>f?1024:0]},$$scope:{ctx:a}}}),r=new J({props:{class:"form-field required",name:"passwordConfirm",$$slots:{default:[ee,({uniqueId:f})=>({10:f}),({uniqueId:f})=>f?1024:0]},$$scope:{ctx:a}}}),{c(){e=b("form"),l=b("div"),s=b("h5"),n=y(`Reset your user password
|
||||
`),d&&d.c(),t=C(),N(o.$$.fragment),c=C(),N(r.$$.fragment),i=C(),u=b("button"),v=b("span"),v.textContent="Set new password",p(l,"class","content txt-center m-b-base"),p(v,"class","txt"),p(u,"type","submit"),p(u,"class","btn btn-lg btn-block"),u.disabled=a[2],M(u,"btn-loading",a[2])},m(f,$){m(f,e,$),w(e,l),w(l,s),w(s,n),d&&d.m(s,null),w(e,t),L(o,e,null),w(e,c),L(r,e,null),w(e,i),w(e,u),w(u,v),g=!0,k||(h=S(e,"submit",U(a[5])),k=!0)},p(f,$){f[4]?d?d.p(f,$):(d=z(f),d.c(),d.m(s,null)):d&&(d.d(1),d=null);const T={};$&3073&&(T.$$scope={dirty:$,ctx:f}),o.$set(T);const I={};$&3074&&(I.$$scope={dirty:$,ctx:f}),r.$set(I),(!g||$&4)&&(u.disabled=f[2]),(!g||$&4)&&M(u,"btn-loading",f[2])},i(f){g||(q(o.$$.fragment,f),q(r.$$.fragment,f),g=!0)},o(f){P(o.$$.fragment,f),P(r.$$.fragment,f),g=!1},d(f){f&&_(e),d&&d.d(),H(o),H(r),k=!1,h()}}}function Z(a){let e,l,s,n,t;return{c(){e=b("div"),e.innerHTML='<div class="icon"><i class="ri-checkbox-circle-line"></i></div> <div class="content txt-bold"><p>Successfully changed the user password.</p> <p>You can now sign in with your new password.</p></div>',l=C(),s=b("button"),s.textContent="Close",p(e,"class","alert alert-success"),p(s,"type","button"),p(s,"class","btn btn-transparent btn-block")},m(o,c){m(o,e,c),m(o,l,c),m(o,s,c),n||(t=S(s,"click",a[7]),n=!0)},p:F,i:F,o:F,d(o){o&&(_(e),_(l),_(s)),n=!1,t()}}}function z(a){let e,l,s;return{c(){e=y("for "),l=b("strong"),s=y(a[4])},m(n,t){m(n,e,t),m(n,l,t),w(l,s)},p(n,t){t&16&&V(s,n[4])},d(n){n&&(_(e),_(l))}}}function x(a){let e,l,s,n,t,o,c,r;return{c(){e=b("label"),l=y("New password"),n=C(),t=b("input"),p(e,"for",s=a[10]),p(t,"type","password"),p(t,"id",o=a[10]),t.required=!0,t.autofocus=!0},m(i,u){m(i,e,u),w(e,l),m(i,n,u),m(i,t,u),R(t,a[0]),t.focus(),c||(r=S(t,"input",a[8]),c=!0)},p(i,u){u&1024&&s!==(s=i[10])&&p(e,"for",s),u&1024&&o!==(o=i[10])&&p(t,"id",o),u&1&&t.value!==i[0]&&R(t,i[0])},d(i){i&&(_(e),_(n),_(t)),c=!1,r()}}}function ee(a){let e,l,s,n,t,o,c,r;return{c(){e=b("label"),l=y("New password confirm"),n=C(),t=b("input"),p(e,"for",s=a[10]),p(t,"type","password"),p(t,"id",o=a[10]),t.required=!0},m(i,u){m(i,e,u),w(e,l),m(i,n,u),m(i,t,u),R(t,a[1]),c||(r=S(t,"input",a[9]),c=!0)},p(i,u){u&1024&&s!==(s=i[10])&&p(e,"for",s),u&1024&&o!==(o=i[10])&&p(t,"id",o),u&2&&t.value!==i[1]&&R(t,i[1])},d(i){i&&(_(e),_(n),_(t)),c=!1,r()}}}function te(a){let e,l,s,n;const t=[Z,X],o=[];function c(r,i){return r[3]?0:1}return e=c(a),l=o[e]=t[e](a),{c(){l.c(),s=G()},m(r,i){o[e].m(r,i),m(r,s,i),n=!0},p(r,i){let u=e;e=c(r),e===u?o[e].p(r,i):(B(),P(o[u],1,1,()=>{o[u]=null}),E(),l=o[e],l?l.p(r,i):(l=o[e]=t[e](r),l.c()),q(l,1),l.m(s.parentNode,s))},i(r){n||(q(l),n=!0)},o(r){P(l),n=!1},d(r){r&&_(s),o[e].d(r)}}}function se(a){let e,l;return e=new Y({props:{nobranding:!0,$$slots:{default:[te]},$$scope:{ctx:a}}}),{c(){N(e.$$.fragment)},m(s,n){L(e,s,n),l=!0},p(s,[n]){const t={};n&2079&&(t.$$scope={dirty:n,ctx:s}),e.$set(t)},i(s){l||(q(e.$$.fragment,s),l=!0)},o(s){P(e.$$.fragment,s),l=!1},d(s){H(e,s)}}}function le(a,e,l){let s,{params:n}=e,t="",o="",c=!1,r=!1;async function i(){if(c)return;l(2,c=!0);const k=new K("../");try{const h=O(n==null?void 0:n.token);await k.collection(h.collectionId).confirmPasswordReset(n==null?void 0:n.token,t,o),l(3,r=!0)}catch(h){Q.error(h)}l(2,c=!1)}const u=()=>window.close();function v(){t=this.value,l(0,t)}function g(){o=this.value,l(1,o)}return a.$$set=k=>{"params"in k&&l(6,n=k.params)},a.$$.update=()=>{a.$$.dirty&64&&l(4,s=j.getJWTPayload(n==null?void 0:n.token).email||"")},[t,o,c,r,s,i,n,u,v,g]}class oe extends A{constructor(e){super(),D(this,e,le,se,W,{params:6})}}export{oe as default};
|
||||
+1
-1
@@ -1 +1 @@
|
||||
import{S as M,i as P,s as R,F as I,d as N,t as S,a as V,m as q,c as F,M as w,g as y,N as E,h as r,l as a,L as g,p as j,H as k,u,w as d,o as m,v,k as C,n as z}from"./index-rRnVk674.js";function A(o){let e,l,n;function t(i,f){return i[4]?K:J}let s=t(o),c=s(o);return{c(){e=u("div"),e.innerHTML='<div class="icon"><i class="ri-error-warning-line"></i></div> <div class="content txt-bold"><p>Invalid or expired verification token.</p></div>',l=v(),c.c(),n=g(),d(e,"class","alert alert-danger")},m(i,f){a(i,e,f),a(i,l,f),c.m(i,f),a(i,n,f)},p(i,f){s===(s=t(i))&&c?c.p(i,f):(c.d(1),c=s(i),c&&(c.c(),c.m(n.parentNode,n)))},d(i){i&&(r(e),r(l),r(n)),c.d(i)}}}function B(o){let e,l,n,t,s;return{c(){e=u("div"),e.innerHTML='<div class="icon"><i class="ri-checkbox-circle-line"></i></div> <div class="content txt-bold"><p>Please check your email for the new verification link.</p></div>',l=v(),n=u("button"),n.textContent="Close",d(e,"class","alert alert-success"),d(n,"type","button"),d(n,"class","btn btn-transparent btn-block")},m(c,i){a(c,e,i),a(c,l,i),a(c,n,i),t||(s=m(n,"click",o[8]),t=!0)},p:k,d(c){c&&(r(e),r(l),r(n)),t=!1,s()}}}function D(o){let e,l,n,t,s;return{c(){e=u("div"),e.innerHTML='<div class="icon"><i class="ri-checkbox-circle-line"></i></div> <div class="content txt-bold"><p>Successfully verified email address.</p></div>',l=v(),n=u("button"),n.textContent="Close",d(e,"class","alert alert-success"),d(n,"type","button"),d(n,"class","btn btn-transparent btn-block")},m(c,i){a(c,e,i),a(c,l,i),a(c,n,i),t||(s=m(n,"click",o[7]),t=!0)},p:k,d(c){c&&(r(e),r(l),r(n)),t=!1,s()}}}function G(o){let e;return{c(){e=u("div"),e.innerHTML='<div class="loader loader-lg"><em>Please wait...</em></div>',d(e,"class","txt-center")},m(l,n){a(l,e,n)},p:k,d(l){l&&r(e)}}}function J(o){let e,l,n;return{c(){e=u("button"),e.textContent="Close",d(e,"type","button"),d(e,"class","btn btn-transparent btn-block")},m(t,s){a(t,e,s),l||(n=m(e,"click",o[9]),l=!0)},p:k,d(t){t&&r(e),l=!1,n()}}}function K(o){let e,l,n,t;return{c(){e=u("button"),l=u("span"),l.textContent="Resend",d(l,"class","txt"),d(e,"type","button"),d(e,"class","btn btn-transparent btn-block"),e.disabled=o[3],C(e,"btn-loading",o[3])},m(s,c){a(s,e,c),z(e,l),n||(t=m(e,"click",o[5]),n=!0)},p(s,c){c&8&&(e.disabled=s[3]),c&8&&C(e,"btn-loading",s[3])},d(s){s&&r(e),n=!1,t()}}}function O(o){let e;function l(s,c){return s[1]?G:s[0]?D:s[2]?B:A}let n=l(o),t=n(o);return{c(){t.c(),e=g()},m(s,c){t.m(s,c),a(s,e,c)},p(s,c){n===(n=l(s))&&t?t.p(s,c):(t.d(1),t=n(s),t&&(t.c(),t.m(e.parentNode,e)))},d(s){s&&r(e),t.d(s)}}}function Q(o){let e,l;return e=new I({props:{nobranding:!0,$$slots:{default:[O]},$$scope:{ctx:o}}}),{c(){F(e.$$.fragment)},m(n,t){q(e,n,t),l=!0},p(n,[t]){const s={};t&2079&&(s.$$scope={dirty:t,ctx:n}),e.$set(s)},i(n){l||(V(e.$$.fragment,n),l=!0)},o(n){S(e.$$.fragment,n),l=!1},d(n){N(e,n)}}}function U(o,e,l){let n,{params:t}=e,s=!1,c=!1,i=!1,f=!1;x();async function x(){if(c)return;l(1,c=!0);const p=new w("../");try{const b=y(t==null?void 0:t.token);await p.collection(b.collectionId).confirmVerification(t==null?void 0:t.token),l(0,s=!0)}catch{l(0,s=!1)}l(1,c=!1)}async function T(){const p=y(t==null?void 0:t.token);if(f||!p.collectionId||!p.email)return;l(3,f=!0);const b=new w("../");try{const _=y(t==null?void 0:t.token);await b.collection(_.collectionId).requestVerification(_.email),l(2,i=!0)}catch(_){j.error(_),l(2,i=!1)}l(3,f=!1)}const h=()=>window.close(),H=()=>window.close(),L=()=>window.close();return o.$$set=p=>{"params"in p&&l(6,t=p.params)},o.$$.update=()=>{o.$$.dirty&64&&l(4,n=(t==null?void 0:t.token)&&E(t.token))},[s,c,i,f,n,T,t,h,H,L]}class X extends M{constructor(e){super(),P(this,e,U,Q,R,{params:6})}}export{X as default};
|
||||
import{S as M,i as P,s as R,F as I,d as N,t as S,a as V,m as q,c as F,M as w,g as y,N as E,h as r,l as a,L as g,p as j,H as k,u,w as d,o as m,v,k as C,n as z}from"./index-BH0nlDnw.js";function A(o){let e,l,n;function t(i,f){return i[4]?K:J}let s=t(o),c=s(o);return{c(){e=u("div"),e.innerHTML='<div class="icon"><i class="ri-error-warning-line"></i></div> <div class="content txt-bold"><p>Invalid or expired verification token.</p></div>',l=v(),c.c(),n=g(),d(e,"class","alert alert-danger")},m(i,f){a(i,e,f),a(i,l,f),c.m(i,f),a(i,n,f)},p(i,f){s===(s=t(i))&&c?c.p(i,f):(c.d(1),c=s(i),c&&(c.c(),c.m(n.parentNode,n)))},d(i){i&&(r(e),r(l),r(n)),c.d(i)}}}function B(o){let e,l,n,t,s;return{c(){e=u("div"),e.innerHTML='<div class="icon"><i class="ri-checkbox-circle-line"></i></div> <div class="content txt-bold"><p>Please check your email for the new verification link.</p></div>',l=v(),n=u("button"),n.textContent="Close",d(e,"class","alert alert-success"),d(n,"type","button"),d(n,"class","btn btn-transparent btn-block")},m(c,i){a(c,e,i),a(c,l,i),a(c,n,i),t||(s=m(n,"click",o[8]),t=!0)},p:k,d(c){c&&(r(e),r(l),r(n)),t=!1,s()}}}function D(o){let e,l,n,t,s;return{c(){e=u("div"),e.innerHTML='<div class="icon"><i class="ri-checkbox-circle-line"></i></div> <div class="content txt-bold"><p>Successfully verified email address.</p></div>',l=v(),n=u("button"),n.textContent="Close",d(e,"class","alert alert-success"),d(n,"type","button"),d(n,"class","btn btn-transparent btn-block")},m(c,i){a(c,e,i),a(c,l,i),a(c,n,i),t||(s=m(n,"click",o[7]),t=!0)},p:k,d(c){c&&(r(e),r(l),r(n)),t=!1,s()}}}function G(o){let e;return{c(){e=u("div"),e.innerHTML='<div class="loader loader-lg"><em>Please wait...</em></div>',d(e,"class","txt-center")},m(l,n){a(l,e,n)},p:k,d(l){l&&r(e)}}}function J(o){let e,l,n;return{c(){e=u("button"),e.textContent="Close",d(e,"type","button"),d(e,"class","btn btn-transparent btn-block")},m(t,s){a(t,e,s),l||(n=m(e,"click",o[9]),l=!0)},p:k,d(t){t&&r(e),l=!1,n()}}}function K(o){let e,l,n,t;return{c(){e=u("button"),l=u("span"),l.textContent="Resend",d(l,"class","txt"),d(e,"type","button"),d(e,"class","btn btn-transparent btn-block"),e.disabled=o[3],C(e,"btn-loading",o[3])},m(s,c){a(s,e,c),z(e,l),n||(t=m(e,"click",o[5]),n=!0)},p(s,c){c&8&&(e.disabled=s[3]),c&8&&C(e,"btn-loading",s[3])},d(s){s&&r(e),n=!1,t()}}}function O(o){let e;function l(s,c){return s[1]?G:s[0]?D:s[2]?B:A}let n=l(o),t=n(o);return{c(){t.c(),e=g()},m(s,c){t.m(s,c),a(s,e,c)},p(s,c){n===(n=l(s))&&t?t.p(s,c):(t.d(1),t=n(s),t&&(t.c(),t.m(e.parentNode,e)))},d(s){s&&r(e),t.d(s)}}}function Q(o){let e,l;return e=new I({props:{nobranding:!0,$$slots:{default:[O]},$$scope:{ctx:o}}}),{c(){F(e.$$.fragment)},m(n,t){q(e,n,t),l=!0},p(n,[t]){const s={};t&2079&&(s.$$scope={dirty:t,ctx:n}),e.$set(s)},i(n){l||(V(e.$$.fragment,n),l=!0)},o(n){S(e.$$.fragment,n),l=!1},d(n){N(e,n)}}}function U(o,e,l){let n,{params:t}=e,s=!1,c=!1,i=!1,f=!1;x();async function x(){if(c)return;l(1,c=!0);const p=new w("../");try{const b=y(t==null?void 0:t.token);await p.collection(b.collectionId).confirmVerification(t==null?void 0:t.token),l(0,s=!0)}catch{l(0,s=!1)}l(1,c=!1)}async function T(){const p=y(t==null?void 0:t.token);if(f||!p.collectionId||!p.email)return;l(3,f=!0);const b=new w("../");try{const _=y(t==null?void 0:t.token);await b.collection(_.collectionId).requestVerification(_.email),l(2,i=!0)}catch(_){j.error(_),l(2,i=!1)}l(3,f=!1)}const h=()=>window.close(),H=()=>window.close(),L=()=>window.close();return o.$$set=p=>{"params"in p&&l(6,t=p.params)},o.$$.update=()=>{o.$$.dirty&64&&l(4,n=(t==null?void 0:t.token)&&E(t.token))},[s,c,i,f,n,T,t,h,H,L]}class X extends M{constructor(e){super(),P(this,e,U,Q,R,{params:6})}}export{X as default};
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
import{S as L,i as W,s as y,F as D,d as R,t as J,a as N,m as T,c as j,J as M,f as G,h as b,j as O,k as H,l as w,n as c,o as z,E as Q,q as U,G as V,u as _,A as P,v as h,w as f,p as I,K as X,r as Y,I as Z,z as q}from"./index-rRnVk674.js";function K(r){let e,n,s;return{c(){e=P("for "),n=_("strong"),s=P(r[3]),f(n,"class","txt-nowrap")},m(l,t){w(l,e,t),w(l,n,t),c(n,s)},p(l,t){t&8&&Z(s,l[3])},d(l){l&&(b(e),b(n))}}}function x(r){let e,n,s,l,t,i,p,d;return{c(){e=_("label"),n=P("New password"),l=h(),t=_("input"),f(e,"for",s=r[8]),f(t,"type","password"),f(t,"id",i=r[8]),t.required=!0,t.autofocus=!0},m(u,a){w(u,e,a),c(e,n),w(u,l,a),w(u,t,a),q(t,r[0]),t.focus(),p||(d=z(t,"input",r[6]),p=!0)},p(u,a){a&256&&s!==(s=u[8])&&f(e,"for",s),a&256&&i!==(i=u[8])&&f(t,"id",i),a&1&&t.value!==u[0]&&q(t,u[0])},d(u){u&&(b(e),b(l),b(t)),p=!1,d()}}}function ee(r){let e,n,s,l,t,i,p,d;return{c(){e=_("label"),n=P("New password confirm"),l=h(),t=_("input"),f(e,"for",s=r[8]),f(t,"type","password"),f(t,"id",i=r[8]),t.required=!0},m(u,a){w(u,e,a),c(e,n),w(u,l,a),w(u,t,a),q(t,r[1]),p||(d=z(t,"input",r[7]),p=!0)},p(u,a){a&256&&s!==(s=u[8])&&f(e,"for",s),a&256&&i!==(i=u[8])&&f(t,"id",i),a&2&&t.value!==u[1]&&q(t,u[1])},d(u){u&&(b(e),b(l),b(t)),p=!1,d()}}}function te(r){let e,n,s,l,t,i,p,d,u,a,g,S,C,v,k,F,A,m=r[3]&&K(r);return i=new G({props:{class:"form-field required",name:"password",$$slots:{default:[x,({uniqueId:o})=>({8:o}),({uniqueId:o})=>o?256:0]},$$scope:{ctx:r}}}),d=new G({props:{class:"form-field required",name:"passwordConfirm",$$slots:{default:[ee,({uniqueId:o})=>({8:o}),({uniqueId:o})=>o?256:0]},$$scope:{ctx:r}}}),{c(){e=_("form"),n=_("div"),s=_("h4"),l=P(`Reset your superuser password
|
||||
import{S as L,i as W,s as y,F as D,d as R,t as J,a as N,m as T,c as j,J as M,f as G,h as b,j as O,k as H,l as w,n as c,o as z,E as Q,q as U,G as V,u as _,A as P,v as h,w as f,p as I,K as X,r as Y,I as Z,z as q}from"./index-BH0nlDnw.js";function K(r){let e,n,s;return{c(){e=P("for "),n=_("strong"),s=P(r[3]),f(n,"class","txt-nowrap")},m(l,t){w(l,e,t),w(l,n,t),c(n,s)},p(l,t){t&8&&Z(s,l[3])},d(l){l&&(b(e),b(n))}}}function x(r){let e,n,s,l,t,i,p,d;return{c(){e=_("label"),n=P("New password"),l=h(),t=_("input"),f(e,"for",s=r[8]),f(t,"type","password"),f(t,"id",i=r[8]),t.required=!0,t.autofocus=!0},m(u,a){w(u,e,a),c(e,n),w(u,l,a),w(u,t,a),q(t,r[0]),t.focus(),p||(d=z(t,"input",r[6]),p=!0)},p(u,a){a&256&&s!==(s=u[8])&&f(e,"for",s),a&256&&i!==(i=u[8])&&f(t,"id",i),a&1&&t.value!==u[0]&&q(t,u[0])},d(u){u&&(b(e),b(l),b(t)),p=!1,d()}}}function ee(r){let e,n,s,l,t,i,p,d;return{c(){e=_("label"),n=P("New password confirm"),l=h(),t=_("input"),f(e,"for",s=r[8]),f(t,"type","password"),f(t,"id",i=r[8]),t.required=!0},m(u,a){w(u,e,a),c(e,n),w(u,l,a),w(u,t,a),q(t,r[1]),p||(d=z(t,"input",r[7]),p=!0)},p(u,a){a&256&&s!==(s=u[8])&&f(e,"for",s),a&256&&i!==(i=u[8])&&f(t,"id",i),a&2&&t.value!==u[1]&&q(t,u[1])},d(u){u&&(b(e),b(l),b(t)),p=!1,d()}}}function te(r){let e,n,s,l,t,i,p,d,u,a,g,S,C,v,k,F,A,m=r[3]&&K(r);return i=new G({props:{class:"form-field required",name:"password",$$slots:{default:[x,({uniqueId:o})=>({8:o}),({uniqueId:o})=>o?256:0]},$$scope:{ctx:r}}}),d=new G({props:{class:"form-field required",name:"passwordConfirm",$$slots:{default:[ee,({uniqueId:o})=>({8:o}),({uniqueId:o})=>o?256:0]},$$scope:{ctx:r}}}),{c(){e=_("form"),n=_("div"),s=_("h4"),l=P(`Reset your superuser password
|
||||
`),m&&m.c(),t=h(),j(i.$$.fragment),p=h(),j(d.$$.fragment),u=h(),a=_("button"),g=_("span"),g.textContent="Set new password",S=h(),C=_("div"),v=_("a"),v.textContent="Back to login",f(s,"class","m-b-xs"),f(n,"class","content txt-center m-b-sm"),f(g,"class","txt"),f(a,"type","submit"),f(a,"class","btn btn-lg btn-block"),a.disabled=r[2],H(a,"btn-loading",r[2]),f(e,"class","m-b-base"),f(v,"href","/login"),f(v,"class","link-hint"),f(C,"class","content txt-center")},m(o,$){w(o,e,$),c(e,n),c(n,s),c(s,l),m&&m.m(s,null),c(e,t),T(i,e,null),c(e,p),T(d,e,null),c(e,u),c(e,a),c(a,g),w(o,S,$),w(o,C,$),c(C,v),k=!0,F||(A=[z(e,"submit",U(r[4])),Q(V.call(null,v))],F=!0)},p(o,$){o[3]?m?m.p(o,$):(m=K(o),m.c(),m.m(s,null)):m&&(m.d(1),m=null);const B={};$&769&&(B.$$scope={dirty:$,ctx:o}),i.$set(B);const E={};$&770&&(E.$$scope={dirty:$,ctx:o}),d.$set(E),(!k||$&4)&&(a.disabled=o[2]),(!k||$&4)&&H(a,"btn-loading",o[2])},i(o){k||(N(i.$$.fragment,o),N(d.$$.fragment,o),k=!0)},o(o){J(i.$$.fragment,o),J(d.$$.fragment,o),k=!1},d(o){o&&(b(e),b(S),b(C)),m&&m.d(),R(i),R(d),F=!1,O(A)}}}function se(r){let e,n;return e=new D({props:{$$slots:{default:[te]},$$scope:{ctx:r}}}),{c(){j(e.$$.fragment)},m(s,l){T(e,s,l),n=!0},p(s,[l]){const t={};l&527&&(t.$$scope={dirty:l,ctx:s}),e.$set(t)},i(s){n||(N(e.$$.fragment,s),n=!0)},o(s){J(e.$$.fragment,s),n=!1},d(s){R(e,s)}}}function le(r,e,n){let s,{params:l}=e,t="",i="",p=!1;async function d(){if(!p){n(2,p=!0);try{await I.collection("_superusers").confirmPasswordReset(l==null?void 0:l.token,t,i),X("Successfully set a new superuser password."),Y("/")}catch(g){I.error(g)}n(2,p=!1)}}function u(){t=this.value,n(0,t)}function a(){i=this.value,n(1,i)}return r.$$set=g=>{"params"in g&&n(5,l=g.params)},r.$$.update=()=>{r.$$.dirty&32&&n(3,s=M.getJWTPayload(l==null?void 0:l.token).email||"")},[t,i,p,s,d,l,u,a]}class ae extends L{constructor(e){super(),W(this,e,le,se,y,{params:5})}}export{ae as default};
|
||||
+1
-1
@@ -1 +1 @@
|
||||
import{S as M,i as T,s as z,F as A,d as E,t as w,a as y,m as H,c as L,h as g,C as B,D,l as k,n as d,E as G,G as I,v,u as m,w as p,p as C,H as F,I as N,A as h,f as j,k as P,o as R,q as J,z as S}from"./index-rRnVk674.js";function K(u){let e,s,n,l,t,r,c,_,i,a,b,f;return l=new j({props:{class:"form-field required",name:"email",$$slots:{default:[Q,({uniqueId:o})=>({5:o}),({uniqueId:o})=>o?32:0]},$$scope:{ctx:u}}}),{c(){e=m("form"),s=m("div"),s.innerHTML='<h4 class="m-b-xs">Forgotten superuser password</h4> <p>Enter the email associated with your account and we’ll send you a recovery link:</p>',n=v(),L(l.$$.fragment),t=v(),r=m("button"),c=m("i"),_=v(),i=m("span"),i.textContent="Send recovery link",p(s,"class","content txt-center m-b-sm"),p(c,"class","ri-mail-send-line"),p(i,"class","txt"),p(r,"type","submit"),p(r,"class","btn btn-lg btn-block"),r.disabled=u[1],P(r,"btn-loading",u[1]),p(e,"class","m-b-base")},m(o,$){k(o,e,$),d(e,s),d(e,n),H(l,e,null),d(e,t),d(e,r),d(r,c),d(r,_),d(r,i),a=!0,b||(f=R(e,"submit",J(u[3])),b=!0)},p(o,$){const q={};$&97&&(q.$$scope={dirty:$,ctx:o}),l.$set(q),(!a||$&2)&&(r.disabled=o[1]),(!a||$&2)&&P(r,"btn-loading",o[1])},i(o){a||(y(l.$$.fragment,o),a=!0)},o(o){w(l.$$.fragment,o),a=!1},d(o){o&&g(e),E(l),b=!1,f()}}}function O(u){let e,s,n,l,t,r,c,_,i;return{c(){e=m("div"),s=m("div"),s.innerHTML='<i class="ri-checkbox-circle-line"></i>',n=v(),l=m("div"),t=m("p"),r=h("Check "),c=m("strong"),_=h(u[0]),i=h(" for the recovery link."),p(s,"class","icon"),p(c,"class","txt-nowrap"),p(l,"class","content"),p(e,"class","alert alert-success")},m(a,b){k(a,e,b),d(e,s),d(e,n),d(e,l),d(l,t),d(t,r),d(t,c),d(c,_),d(t,i)},p(a,b){b&1&&N(_,a[0])},i:F,o:F,d(a){a&&g(e)}}}function Q(u){let e,s,n,l,t,r,c,_;return{c(){e=m("label"),s=h("Email"),l=v(),t=m("input"),p(e,"for",n=u[5]),p(t,"type","email"),p(t,"id",r=u[5]),t.required=!0,t.autofocus=!0},m(i,a){k(i,e,a),d(e,s),k(i,l,a),k(i,t,a),S(t,u[0]),t.focus(),c||(_=R(t,"input",u[4]),c=!0)},p(i,a){a&32&&n!==(n=i[5])&&p(e,"for",n),a&32&&r!==(r=i[5])&&p(t,"id",r),a&1&&t.value!==i[0]&&S(t,i[0])},d(i){i&&(g(e),g(l),g(t)),c=!1,_()}}}function U(u){let e,s,n,l,t,r,c,_;const i=[O,K],a=[];function b(f,o){return f[2]?0:1}return e=b(u),s=a[e]=i[e](u),{c(){s.c(),n=v(),l=m("div"),t=m("a"),t.textContent="Back to login",p(t,"href","/login"),p(t,"class","link-hint"),p(l,"class","content txt-center")},m(f,o){a[e].m(f,o),k(f,n,o),k(f,l,o),d(l,t),r=!0,c||(_=G(I.call(null,t)),c=!0)},p(f,o){let $=e;e=b(f),e===$?a[e].p(f,o):(B(),w(a[$],1,1,()=>{a[$]=null}),D(),s=a[e],s?s.p(f,o):(s=a[e]=i[e](f),s.c()),y(s,1),s.m(n.parentNode,n))},i(f){r||(y(s),r=!0)},o(f){w(s),r=!1},d(f){f&&(g(n),g(l)),a[e].d(f),c=!1,_()}}}function V(u){let e,s;return e=new A({props:{$$slots:{default:[U]},$$scope:{ctx:u}}}),{c(){L(e.$$.fragment)},m(n,l){H(e,n,l),s=!0},p(n,[l]){const t={};l&71&&(t.$$scope={dirty:l,ctx:n}),e.$set(t)},i(n){s||(y(e.$$.fragment,n),s=!0)},o(n){w(e.$$.fragment,n),s=!1},d(n){E(e,n)}}}function W(u,e,s){let n="",l=!1,t=!1;async function r(){if(!l){s(1,l=!0);try{await C.collection("_superusers").requestPasswordReset(n),s(2,t=!0)}catch(_){C.error(_)}s(1,l=!1)}}function c(){n=this.value,s(0,n)}return[n,l,t,r,c]}class Y extends M{constructor(e){super(),T(this,e,W,V,z,{})}}export{Y as default};
|
||||
import{S as M,i as T,s as z,F as A,d as E,t as w,a as y,m as H,c as L,h as g,C as B,D,l as k,n as d,E as G,G as I,v,u as m,w as p,p as C,H as F,I as N,A as h,f as j,k as P,o as R,q as J,z as S}from"./index-BH0nlDnw.js";function K(u){let e,s,n,l,t,r,c,_,i,a,b,f;return l=new j({props:{class:"form-field required",name:"email",$$slots:{default:[Q,({uniqueId:o})=>({5:o}),({uniqueId:o})=>o?32:0]},$$scope:{ctx:u}}}),{c(){e=m("form"),s=m("div"),s.innerHTML='<h4 class="m-b-xs">Forgotten superuser password</h4> <p>Enter the email associated with your account and we’ll send you a recovery link:</p>',n=v(),L(l.$$.fragment),t=v(),r=m("button"),c=m("i"),_=v(),i=m("span"),i.textContent="Send recovery link",p(s,"class","content txt-center m-b-sm"),p(c,"class","ri-mail-send-line"),p(i,"class","txt"),p(r,"type","submit"),p(r,"class","btn btn-lg btn-block"),r.disabled=u[1],P(r,"btn-loading",u[1]),p(e,"class","m-b-base")},m(o,$){k(o,e,$),d(e,s),d(e,n),H(l,e,null),d(e,t),d(e,r),d(r,c),d(r,_),d(r,i),a=!0,b||(f=R(e,"submit",J(u[3])),b=!0)},p(o,$){const q={};$&97&&(q.$$scope={dirty:$,ctx:o}),l.$set(q),(!a||$&2)&&(r.disabled=o[1]),(!a||$&2)&&P(r,"btn-loading",o[1])},i(o){a||(y(l.$$.fragment,o),a=!0)},o(o){w(l.$$.fragment,o),a=!1},d(o){o&&g(e),E(l),b=!1,f()}}}function O(u){let e,s,n,l,t,r,c,_,i;return{c(){e=m("div"),s=m("div"),s.innerHTML='<i class="ri-checkbox-circle-line"></i>',n=v(),l=m("div"),t=m("p"),r=h("Check "),c=m("strong"),_=h(u[0]),i=h(" for the recovery link."),p(s,"class","icon"),p(c,"class","txt-nowrap"),p(l,"class","content"),p(e,"class","alert alert-success")},m(a,b){k(a,e,b),d(e,s),d(e,n),d(e,l),d(l,t),d(t,r),d(t,c),d(c,_),d(t,i)},p(a,b){b&1&&N(_,a[0])},i:F,o:F,d(a){a&&g(e)}}}function Q(u){let e,s,n,l,t,r,c,_;return{c(){e=m("label"),s=h("Email"),l=v(),t=m("input"),p(e,"for",n=u[5]),p(t,"type","email"),p(t,"id",r=u[5]),t.required=!0,t.autofocus=!0},m(i,a){k(i,e,a),d(e,s),k(i,l,a),k(i,t,a),S(t,u[0]),t.focus(),c||(_=R(t,"input",u[4]),c=!0)},p(i,a){a&32&&n!==(n=i[5])&&p(e,"for",n),a&32&&r!==(r=i[5])&&p(t,"id",r),a&1&&t.value!==i[0]&&S(t,i[0])},d(i){i&&(g(e),g(l),g(t)),c=!1,_()}}}function U(u){let e,s,n,l,t,r,c,_;const i=[O,K],a=[];function b(f,o){return f[2]?0:1}return e=b(u),s=a[e]=i[e](u),{c(){s.c(),n=v(),l=m("div"),t=m("a"),t.textContent="Back to login",p(t,"href","/login"),p(t,"class","link-hint"),p(l,"class","content txt-center")},m(f,o){a[e].m(f,o),k(f,n,o),k(f,l,o),d(l,t),r=!0,c||(_=G(I.call(null,t)),c=!0)},p(f,o){let $=e;e=b(f),e===$?a[e].p(f,o):(B(),w(a[$],1,1,()=>{a[$]=null}),D(),s=a[e],s?s.p(f,o):(s=a[e]=i[e](f),s.c()),y(s,1),s.m(n.parentNode,n))},i(f){r||(y(s),r=!0)},o(f){w(s),r=!1},d(f){f&&(g(n),g(l)),a[e].d(f),c=!1,_()}}}function V(u){let e,s;return e=new A({props:{$$slots:{default:[U]},$$scope:{ctx:u}}}),{c(){L(e.$$.fragment)},m(n,l){H(e,n,l),s=!0},p(n,[l]){const t={};l&71&&(t.$$scope={dirty:l,ctx:n}),e.$set(t)},i(n){s||(y(e.$$.fragment,n),s=!0)},o(n){w(e.$$.fragment,n),s=!1},d(n){E(e,n)}}}function W(u,e,s){let n="",l=!1,t=!1;async function r(){if(!l){s(1,l=!0);try{await C.collection("_superusers").requestPasswordReset(n),s(2,t=!0)}catch(_){C.error(_)}s(1,l=!1)}}function c(){n=this.value,s(0,n)}return[n,l,t,r,c]}class Y extends M{constructor(e){super(),T(this,e,W,V,z,{})}}export{Y as default};
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{S as se,i as ne,s as oe,X as H,h as b,t as X,a as V,I as Z,Z as ee,_ as ye,C as te,$ as Te,D as le,l as v,n as u,u as p,v as S,A as D,w as k,k as L,o as ae,W as Ee,d as G,m as Q,c as x,V as Ce,Y as fe,J as qe,p as Oe,a0 as pe}from"./index-rRnVk674.js";function me(o,t,e){const n=o.slice();return n[4]=t[e],n}function _e(o,t,e){const n=o.slice();return n[4]=t[e],n}function he(o,t){let e,n=t[4].code+"",d,c,r,a;function f(){return t[3](t[4])}return{key:o,first:null,c(){e=p("button"),d=D(n),c=S(),k(e,"class","tab-item"),L(e,"active",t[1]===t[4].code),this.first=e},m(g,y){v(g,e,y),u(e,d),u(e,c),r||(a=ae(e,"click",f),r=!0)},p(g,y){t=g,y&4&&n!==(n=t[4].code+"")&&Z(d,n),y&6&&L(e,"active",t[1]===t[4].code)},d(g){g&&b(e),r=!1,a()}}}function be(o,t){let e,n,d,c;return n=new Ee({props:{content:t[4].body}}),{key:o,first:null,c(){e=p("div"),x(n.$$.fragment),d=S(),k(e,"class","tab-item"),L(e,"active",t[1]===t[4].code),this.first=e},m(r,a){v(r,e,a),Q(n,e,null),u(e,d),c=!0},p(r,a){t=r;const f={};a&4&&(f.content=t[4].body),n.$set(f),(!c||a&6)&&L(e,"active",t[1]===t[4].code)},i(r){c||(V(n.$$.fragment,r),c=!0)},o(r){X(n.$$.fragment,r),c=!1},d(r){r&&b(e),G(n)}}}function Ae(o){let t,e,n,d,c,r,a,f=o[0].name+"",g,y,F,q,J,W,U,O,A,T,C,R=[],M=new Map,j,N,h=[],K=new Map,E,P=H(o[2]);const B=l=>l[4].code;for(let l=0;l<P.length;l+=1){let s=_e(o,P,l),_=B(s);M.set(_,R[l]=he(_,s))}let m=H(o[2]);const Y=l=>l[4].code;for(let l=0;l<m.length;l+=1){let s=me(o,m,l),_=Y(s);K.set(_,h[l]=be(_,s))}return{c(){t=p("div"),e=p("strong"),e.textContent="POST",n=S(),d=p("div"),c=p("p"),r=D("/api/collections/"),a=p("strong"),g=D(f),y=D("/confirm-password-reset"),F=S(),q=p("div"),q.textContent="Body Parameters",J=S(),W=p("table"),W.innerHTML='<thead><tr><th>Param</th> <th>Type</th> <th width="50%">Description</th></tr></thead> <tbody><tr><td><div class="inline-flex"><span class="label label-success">Required</span> <span>token</span></div></td> <td><span class="label">String</span></td> <td>The token from the password reset request email.</td></tr> <tr><td><div class="inline-flex"><span class="label label-success">Required</span> <span>password</span></div></td> <td><span class="label">String</span></td> <td>The new password to set.</td></tr> <tr><td><div class="inline-flex"><span class="label label-success">Required</span> <span>passwordConfirm</span></div></td> <td><span class="label">String</span></td> <td>The new password confirmation.</td></tr></tbody>',U=S(),O=p("div"),O.textContent="Responses",A=S(),T=p("div"),C=p("div");for(let l=0;l<R.length;l+=1)R[l].c();j=S(),N=p("div");for(let l=0;l<h.length;l+=1)h[l].c();k(e,"class","label label-primary"),k(d,"class","content"),k(t,"class","alert alert-success"),k(q,"class","section-title"),k(W,"class","table-compact table-border m-b-base"),k(O,"class","section-title"),k(C,"class","tabs-header compact combined left"),k(N,"class","tabs-content"),k(T,"class","tabs")},m(l,s){v(l,t,s),u(t,e),u(t,n),u(t,d),u(d,c),u(c,r),u(c,a),u(a,g),u(c,y),v(l,F,s),v(l,q,s),v(l,J,s),v(l,W,s),v(l,U,s),v(l,O,s),v(l,A,s),v(l,T,s),u(T,C);for(let _=0;_<R.length;_+=1)R[_]&&R[_].m(C,null);u(T,j),u(T,N);for(let _=0;_<h.length;_+=1)h[_]&&h[_].m(N,null);E=!0},p(l,[s]){(!E||s&1)&&f!==(f=l[0].name+"")&&Z(g,f),s&6&&(P=H(l[2]),R=ee(R,s,B,1,l,P,M,C,ye,he,null,_e)),s&6&&(m=H(l[2]),te(),h=ee(h,s,Y,1,l,m,K,N,Te,be,null,me),le())},i(l){if(!E){for(let s=0;s<m.length;s+=1)V(h[s]);E=!0}},o(l){for(let s=0;s<h.length;s+=1)X(h[s]);E=!1},d(l){l&&(b(t),b(F),b(q),b(J),b(W),b(U),b(O),b(A),b(T));for(let s=0;s<R.length;s+=1)R[s].d();for(let s=0;s<h.length;s+=1)h[s].d()}}}function We(o,t,e){let{collection:n}=t,d=204,c=[];const r=a=>e(1,d=a.code);return o.$$set=a=>{"collection"in a&&e(0,n=a.collection)},e(2,c=[{code:204,body:"null"},{code:400,body:`
|
||||
import{S as se,i as ne,s as oe,X as H,h as b,t as X,a as V,I as Z,Z as ee,_ as ye,C as te,$ as Te,D as le,l as v,n as u,u as p,v as S,A as D,w as k,k as L,o as ae,W as Ee,d as G,m as Q,c as x,V as Ce,Y as fe,J as qe,p as Oe,a0 as pe}from"./index-BH0nlDnw.js";function me(o,t,e){const n=o.slice();return n[4]=t[e],n}function _e(o,t,e){const n=o.slice();return n[4]=t[e],n}function he(o,t){let e,n=t[4].code+"",d,c,r,a;function f(){return t[3](t[4])}return{key:o,first:null,c(){e=p("button"),d=D(n),c=S(),k(e,"class","tab-item"),L(e,"active",t[1]===t[4].code),this.first=e},m(g,y){v(g,e,y),u(e,d),u(e,c),r||(a=ae(e,"click",f),r=!0)},p(g,y){t=g,y&4&&n!==(n=t[4].code+"")&&Z(d,n),y&6&&L(e,"active",t[1]===t[4].code)},d(g){g&&b(e),r=!1,a()}}}function be(o,t){let e,n,d,c;return n=new Ee({props:{content:t[4].body}}),{key:o,first:null,c(){e=p("div"),x(n.$$.fragment),d=S(),k(e,"class","tab-item"),L(e,"active",t[1]===t[4].code),this.first=e},m(r,a){v(r,e,a),Q(n,e,null),u(e,d),c=!0},p(r,a){t=r;const f={};a&4&&(f.content=t[4].body),n.$set(f),(!c||a&6)&&L(e,"active",t[1]===t[4].code)},i(r){c||(V(n.$$.fragment,r),c=!0)},o(r){X(n.$$.fragment,r),c=!1},d(r){r&&b(e),G(n)}}}function Ae(o){let t,e,n,d,c,r,a,f=o[0].name+"",g,y,F,q,J,W,U,O,A,T,C,R=[],M=new Map,j,N,h=[],K=new Map,E,P=H(o[2]);const B=l=>l[4].code;for(let l=0;l<P.length;l+=1){let s=_e(o,P,l),_=B(s);M.set(_,R[l]=he(_,s))}let m=H(o[2]);const Y=l=>l[4].code;for(let l=0;l<m.length;l+=1){let s=me(o,m,l),_=Y(s);K.set(_,h[l]=be(_,s))}return{c(){t=p("div"),e=p("strong"),e.textContent="POST",n=S(),d=p("div"),c=p("p"),r=D("/api/collections/"),a=p("strong"),g=D(f),y=D("/confirm-password-reset"),F=S(),q=p("div"),q.textContent="Body Parameters",J=S(),W=p("table"),W.innerHTML='<thead><tr><th>Param</th> <th>Type</th> <th width="50%">Description</th></tr></thead> <tbody><tr><td><div class="inline-flex"><span class="label label-success">Required</span> <span>token</span></div></td> <td><span class="label">String</span></td> <td>The token from the password reset request email.</td></tr> <tr><td><div class="inline-flex"><span class="label label-success">Required</span> <span>password</span></div></td> <td><span class="label">String</span></td> <td>The new password to set.</td></tr> <tr><td><div class="inline-flex"><span class="label label-success">Required</span> <span>passwordConfirm</span></div></td> <td><span class="label">String</span></td> <td>The new password confirmation.</td></tr></tbody>',U=S(),O=p("div"),O.textContent="Responses",A=S(),T=p("div"),C=p("div");for(let l=0;l<R.length;l+=1)R[l].c();j=S(),N=p("div");for(let l=0;l<h.length;l+=1)h[l].c();k(e,"class","label label-primary"),k(d,"class","content"),k(t,"class","alert alert-success"),k(q,"class","section-title"),k(W,"class","table-compact table-border m-b-base"),k(O,"class","section-title"),k(C,"class","tabs-header compact combined left"),k(N,"class","tabs-content"),k(T,"class","tabs")},m(l,s){v(l,t,s),u(t,e),u(t,n),u(t,d),u(d,c),u(c,r),u(c,a),u(a,g),u(c,y),v(l,F,s),v(l,q,s),v(l,J,s),v(l,W,s),v(l,U,s),v(l,O,s),v(l,A,s),v(l,T,s),u(T,C);for(let _=0;_<R.length;_+=1)R[_]&&R[_].m(C,null);u(T,j),u(T,N);for(let _=0;_<h.length;_+=1)h[_]&&h[_].m(N,null);E=!0},p(l,[s]){(!E||s&1)&&f!==(f=l[0].name+"")&&Z(g,f),s&6&&(P=H(l[2]),R=ee(R,s,B,1,l,P,M,C,ye,he,null,_e)),s&6&&(m=H(l[2]),te(),h=ee(h,s,Y,1,l,m,K,N,Te,be,null,me),le())},i(l){if(!E){for(let s=0;s<m.length;s+=1)V(h[s]);E=!0}},o(l){for(let s=0;s<h.length;s+=1)X(h[s]);E=!1},d(l){l&&(b(t),b(F),b(q),b(J),b(W),b(U),b(O),b(A),b(T));for(let s=0;s<R.length;s+=1)R[s].d();for(let s=0;s<h.length;s+=1)h[s].d()}}}function We(o,t,e){let{collection:n}=t,d=204,c=[];const r=a=>e(1,d=a.code);return o.$$set=a=>{"collection"in a&&e(0,n=a.collection)},e(2,c=[{code:204,body:"null"},{code:400,body:`
|
||||
{
|
||||
"status": 400,
|
||||
"message": "An error occurred while validating the submitted data.",
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{S as re,i as ae,s as be,V as pe,W as ue,J as P,h as s,d as se,t as ne,a as ie,I as me,l as n,n as y,m as ce,u as p,A as I,v as a,c as le,w as u,p as de}from"./index-rRnVk674.js";function he(o){var B,U,W,A,L,H,T,q,J,M,j,N;let i,m,c=o[0].name+"",b,d,k,h,D,f,_,l,S,$,w,g,C,v,E,r,R;return l=new pe({props:{js:`
|
||||
import{S as re,i as ae,s as be,V as pe,W as ue,J as P,h as s,d as se,t as ne,a as ie,I as me,l as n,n as y,m as ce,u as p,A as I,v as a,c as le,w as u,p as de}from"./index-BH0nlDnw.js";function he(o){var B,U,W,A,L,H,T,q,J,M,j,N;let i,m,c=o[0].name+"",b,d,k,h,D,f,_,l,S,$,w,g,C,v,E,r,R;return l=new pe({props:{js:`
|
||||
import PocketBase from 'pocketbase';
|
||||
|
||||
const pb = new PocketBase('${o[1]}');
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{S as $t,i as Mt,s as St,V as Ot,X as se,W as Tt,h as d,d as ge,t as _e,a as he,I as ee,Z as Je,_ as bt,C as qt,$ as Rt,D as Ht,l as o,n as a,m as we,u as s,A as _,v as f,c as Ce,w as k,J as ye,p as Pt,k as Te,o as Lt,H as te}from"./index-rRnVk674.js";import{F as Dt}from"./FieldsQueryParam-BEgqkb0I.js";function mt(r,e,t){const n=r.slice();return n[10]=e[t],n}function _t(r,e,t){const n=r.slice();return n[10]=e[t],n}function ht(r,e,t){const n=r.slice();return n[15]=e[t],n}function yt(r){let e;return{c(){e=s("p"),e.innerHTML=`<em>Note that in case of a password change all previously issued tokens for the current record
|
||||
import{S as $t,i as Mt,s as St,V as Ot,X as se,W as Tt,h as d,d as ge,t as _e,a as he,I as ee,Z as Je,_ as bt,C as qt,$ as Rt,D as Ht,l as o,n as a,m as we,u as s,A as _,v as f,c as Ce,w as k,J as ye,p as Pt,k as Te,o as Lt,H as te}from"./index-BH0nlDnw.js";import{F as Dt}from"./FieldsQueryParam-DQVKTiQb.js";function mt(r,e,t){const n=r.slice();return n[10]=e[t],n}function _t(r,e,t){const n=r.slice();return n[10]=e[t],n}function ht(r,e,t){const n=r.slice();return n[15]=e[t],n}function yt(r){let e;return{c(){e=s("p"),e.innerHTML=`<em>Note that in case of a password change all previously issued tokens for the current record
|
||||
will be automatically invalidated and if you want your user to remain signed in you need to
|
||||
reauthenticate manually after the update call.</em>`},m(t,n){o(t,e,n)},d(t){t&&d(e)}}}function kt(r){let e;return{c(){e=s("p"),e.innerHTML="Requires superuser <code>Authorization:TOKEN</code> header",k(e,"class","txt-hint txt-sm txt-right")},m(t,n){o(t,e,n)},d(t){t&&d(e)}}}function vt(r){let e,t,n,b,p,c,u,m,S,T,H,P,$,M,q,L,J,j,O,R,D,v,g,w;function x(h,C){var le,W,ne;return C&1&&(m=null),m==null&&(m=!!((ne=(W=(le=h[0])==null?void 0:le.fields)==null?void 0:W.find(zt))!=null&&ne.required)),m?Bt:Ft}let Q=x(r,-1),B=Q(r);return{c(){e=s("tr"),e.innerHTML='<td colspan="3" class="txt-hint txt-bold">Auth specific fields</td>',t=f(),n=s("tr"),n.innerHTML=`<td><div class="inline-flex"><span class="label label-warning">Optional</span> <span>email</span></div></td> <td><span class="label">String</span></td> <td>The auth record email address.
|
||||
<br/>
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{S as le,i as ne,s as ie,X as F,h as b,t as j,a as U,I as Y,Z as x,_ as Te,C as ee,$ as Ce,D as te,l as h,n as u,u as m,v as y,A as M,w as v,k as K,o as oe,W as qe,d as z,m as G,c as Q,V as Ve,Y as fe,J as Ae,p as Ie,a0 as ue}from"./index-rRnVk674.js";function de(s,t,e){const o=s.slice();return o[4]=t[e],o}function me(s,t,e){const o=s.slice();return o[4]=t[e],o}function pe(s,t){let e,o=t[4].code+"",f,c,r,a;function d(){return t[3](t[4])}return{key:s,first:null,c(){e=m("button"),f=M(o),c=y(),v(e,"class","tab-item"),K(e,"active",t[1]===t[4].code),this.first=e},m(g,C){h(g,e,C),u(e,f),u(e,c),r||(a=oe(e,"click",d),r=!0)},p(g,C){t=g,C&4&&o!==(o=t[4].code+"")&&Y(f,o),C&6&&K(e,"active",t[1]===t[4].code)},d(g){g&&b(e),r=!1,a()}}}function _e(s,t){let e,o,f,c;return o=new qe({props:{content:t[4].body}}),{key:s,first:null,c(){e=m("div"),Q(o.$$.fragment),f=y(),v(e,"class","tab-item"),K(e,"active",t[1]===t[4].code),this.first=e},m(r,a){h(r,e,a),G(o,e,null),u(e,f),c=!0},p(r,a){t=r;const d={};a&4&&(d.content=t[4].body),o.$set(d),(!c||a&6)&&K(e,"active",t[1]===t[4].code)},i(r){c||(U(o.$$.fragment,r),c=!0)},o(r){j(o.$$.fragment,r),c=!1},d(r){r&&b(e),z(o)}}}function Pe(s){let t,e,o,f,c,r,a,d=s[0].name+"",g,C,D,P,L,R,B,O,N,q,V,$=[],J=new Map,H,I,p=[],T=new Map,A,_=F(s[2]);const X=l=>l[4].code;for(let l=0;l<_.length;l+=1){let i=me(s,_,l),n=X(i);J.set(n,$[l]=pe(n,i))}let E=F(s[2]);const W=l=>l[4].code;for(let l=0;l<E.length;l+=1){let i=de(s,E,l),n=W(i);T.set(n,p[l]=_e(n,i))}return{c(){t=m("div"),e=m("strong"),e.textContent="POST",o=y(),f=m("div"),c=m("p"),r=M("/api/collections/"),a=m("strong"),g=M(d),C=M("/confirm-verification"),D=y(),P=m("div"),P.textContent="Body Parameters",L=y(),R=m("table"),R.innerHTML='<thead><tr><th>Param</th> <th>Type</th> <th width="50%">Description</th></tr></thead> <tbody><tr><td><div class="inline-flex"><span class="label label-success">Required</span> <span>token</span></div></td> <td><span class="label">String</span></td> <td>The token from the verification request email.</td></tr></tbody>',B=y(),O=m("div"),O.textContent="Responses",N=y(),q=m("div"),V=m("div");for(let l=0;l<$.length;l+=1)$[l].c();H=y(),I=m("div");for(let l=0;l<p.length;l+=1)p[l].c();v(e,"class","label label-primary"),v(f,"class","content"),v(t,"class","alert alert-success"),v(P,"class","section-title"),v(R,"class","table-compact table-border m-b-base"),v(O,"class","section-title"),v(V,"class","tabs-header compact combined left"),v(I,"class","tabs-content"),v(q,"class","tabs")},m(l,i){h(l,t,i),u(t,e),u(t,o),u(t,f),u(f,c),u(c,r),u(c,a),u(a,g),u(c,C),h(l,D,i),h(l,P,i),h(l,L,i),h(l,R,i),h(l,B,i),h(l,O,i),h(l,N,i),h(l,q,i),u(q,V);for(let n=0;n<$.length;n+=1)$[n]&&$[n].m(V,null);u(q,H),u(q,I);for(let n=0;n<p.length;n+=1)p[n]&&p[n].m(I,null);A=!0},p(l,[i]){(!A||i&1)&&d!==(d=l[0].name+"")&&Y(g,d),i&6&&(_=F(l[2]),$=x($,i,X,1,l,_,J,V,Te,pe,null,me)),i&6&&(E=F(l[2]),ee(),p=x(p,i,W,1,l,E,T,I,Ce,_e,null,de),te())},i(l){if(!A){for(let i=0;i<E.length;i+=1)U(p[i]);A=!0}},o(l){for(let i=0;i<p.length;i+=1)j(p[i]);A=!1},d(l){l&&(b(t),b(D),b(P),b(L),b(R),b(B),b(O),b(N),b(q));for(let i=0;i<$.length;i+=1)$[i].d();for(let i=0;i<p.length;i+=1)p[i].d()}}}function Re(s,t,e){let{collection:o}=t,f=204,c=[];const r=a=>e(1,f=a.code);return s.$$set=a=>{"collection"in a&&e(0,o=a.collection)},e(2,c=[{code:204,body:"null"},{code:400,body:`
|
||||
import{S as le,i as ne,s as ie,X as F,h as b,t as j,a as U,I as Y,Z as x,_ as Te,C as ee,$ as Ce,D as te,l as h,n as u,u as m,v as y,A as M,w as v,k as K,o as oe,W as qe,d as z,m as G,c as Q,V as Ve,Y as fe,J as Ae,p as Ie,a0 as ue}from"./index-BH0nlDnw.js";function de(s,t,e){const o=s.slice();return o[4]=t[e],o}function me(s,t,e){const o=s.slice();return o[4]=t[e],o}function pe(s,t){let e,o=t[4].code+"",f,c,r,a;function d(){return t[3](t[4])}return{key:s,first:null,c(){e=m("button"),f=M(o),c=y(),v(e,"class","tab-item"),K(e,"active",t[1]===t[4].code),this.first=e},m(g,C){h(g,e,C),u(e,f),u(e,c),r||(a=oe(e,"click",d),r=!0)},p(g,C){t=g,C&4&&o!==(o=t[4].code+"")&&Y(f,o),C&6&&K(e,"active",t[1]===t[4].code)},d(g){g&&b(e),r=!1,a()}}}function _e(s,t){let e,o,f,c;return o=new qe({props:{content:t[4].body}}),{key:s,first:null,c(){e=m("div"),Q(o.$$.fragment),f=y(),v(e,"class","tab-item"),K(e,"active",t[1]===t[4].code),this.first=e},m(r,a){h(r,e,a),G(o,e,null),u(e,f),c=!0},p(r,a){t=r;const d={};a&4&&(d.content=t[4].body),o.$set(d),(!c||a&6)&&K(e,"active",t[1]===t[4].code)},i(r){c||(U(o.$$.fragment,r),c=!0)},o(r){j(o.$$.fragment,r),c=!1},d(r){r&&b(e),z(o)}}}function Pe(s){let t,e,o,f,c,r,a,d=s[0].name+"",g,C,D,P,L,R,B,O,N,q,V,$=[],J=new Map,H,I,p=[],T=new Map,A,_=F(s[2]);const X=l=>l[4].code;for(let l=0;l<_.length;l+=1){let i=me(s,_,l),n=X(i);J.set(n,$[l]=pe(n,i))}let E=F(s[2]);const W=l=>l[4].code;for(let l=0;l<E.length;l+=1){let i=de(s,E,l),n=W(i);T.set(n,p[l]=_e(n,i))}return{c(){t=m("div"),e=m("strong"),e.textContent="POST",o=y(),f=m("div"),c=m("p"),r=M("/api/collections/"),a=m("strong"),g=M(d),C=M("/confirm-verification"),D=y(),P=m("div"),P.textContent="Body Parameters",L=y(),R=m("table"),R.innerHTML='<thead><tr><th>Param</th> <th>Type</th> <th width="50%">Description</th></tr></thead> <tbody><tr><td><div class="inline-flex"><span class="label label-success">Required</span> <span>token</span></div></td> <td><span class="label">String</span></td> <td>The token from the verification request email.</td></tr></tbody>',B=y(),O=m("div"),O.textContent="Responses",N=y(),q=m("div"),V=m("div");for(let l=0;l<$.length;l+=1)$[l].c();H=y(),I=m("div");for(let l=0;l<p.length;l+=1)p[l].c();v(e,"class","label label-primary"),v(f,"class","content"),v(t,"class","alert alert-success"),v(P,"class","section-title"),v(R,"class","table-compact table-border m-b-base"),v(O,"class","section-title"),v(V,"class","tabs-header compact combined left"),v(I,"class","tabs-content"),v(q,"class","tabs")},m(l,i){h(l,t,i),u(t,e),u(t,o),u(t,f),u(f,c),u(c,r),u(c,a),u(a,g),u(c,C),h(l,D,i),h(l,P,i),h(l,L,i),h(l,R,i),h(l,B,i),h(l,O,i),h(l,N,i),h(l,q,i),u(q,V);for(let n=0;n<$.length;n+=1)$[n]&&$[n].m(V,null);u(q,H),u(q,I);for(let n=0;n<p.length;n+=1)p[n]&&p[n].m(I,null);A=!0},p(l,[i]){(!A||i&1)&&d!==(d=l[0].name+"")&&Y(g,d),i&6&&(_=F(l[2]),$=x($,i,X,1,l,_,J,V,Te,pe,null,me)),i&6&&(E=F(l[2]),ee(),p=x(p,i,W,1,l,E,T,I,Ce,_e,null,de),te())},i(l){if(!A){for(let i=0;i<E.length;i+=1)U(p[i]);A=!0}},o(l){for(let i=0;i<p.length;i+=1)j(p[i]);A=!1},d(l){l&&(b(t),b(D),b(P),b(L),b(R),b(B),b(O),b(N),b(q));for(let i=0;i<$.length;i+=1)$[i].d();for(let i=0;i<p.length;i+=1)p[i].d()}}}function Re(s,t,e){let{collection:o}=t,f=204,c=[];const r=a=>e(1,f=a.code);return s.$$set=a=>{"collection"in a&&e(0,o=a.collection)},e(2,c=[{code:204,body:"null"},{code:400,body:`
|
||||
{
|
||||
"status": 400,
|
||||
"message": "An error occurred while validating the submitted data.",
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{S as lt,i as st,s as nt,V as at,W as tt,X as K,h as r,d as W,t as V,a as j,I as ve,Z as Ge,_ as ot,C as it,$ as rt,D as dt,l as d,n as l,m as X,u as a,A as _,v as b,c as Z,w as m,J as Ke,p as ct,k as Y,o as pt}from"./index-rRnVk674.js";import{F as ut}from"./FieldsQueryParam-BEgqkb0I.js";function We(o,s,n){const i=o.slice();return i[6]=s[n],i}function Xe(o,s,n){const i=o.slice();return i[6]=s[n],i}function Ze(o){let s;return{c(){s=a("p"),s.innerHTML="Requires superuser <code>Authorization:TOKEN</code> header",m(s,"class","txt-hint txt-sm txt-right")},m(n,i){d(n,s,i)},d(n){n&&r(s)}}}function Ye(o,s){let n,i,v;function p(){return s[5](s[6])}return{key:o,first:null,c(){n=a("button"),n.textContent=`${s[6].code} `,m(n,"class","tab-item"),Y(n,"active",s[2]===s[6].code),this.first=n},m(c,f){d(c,n,f),i||(v=pt(n,"click",p),i=!0)},p(c,f){s=c,f&20&&Y(n,"active",s[2]===s[6].code)},d(c){c&&r(n),i=!1,v()}}}function et(o,s){let n,i,v,p;return i=new tt({props:{content:s[6].body}}),{key:o,first:null,c(){n=a("div"),Z(i.$$.fragment),v=b(),m(n,"class","tab-item"),Y(n,"active",s[2]===s[6].code),this.first=n},m(c,f){d(c,n,f),X(i,n,null),l(n,v),p=!0},p(c,f){s=c,(!p||f&20)&&Y(n,"active",s[2]===s[6].code)},i(c){p||(j(i.$$.fragment,c),p=!0)},o(c){V(i.$$.fragment,c),p=!1},d(c){c&&r(n),W(i)}}}function ft(o){var Je,Ne;let s,n,i=o[0].name+"",v,p,c,f,w,C,ee,J=o[0].name+"",te,$e,le,F,se,B,ne,$,N,ye,Q,T,we,ae,z=o[0].name+"",oe,Ce,ie,Fe,re,I,de,S,ce,x,pe,R,ue,Re,M,D,fe,De,be,Oe,h,Pe,E,Te,Ee,Ae,me,Be,_e,Ie,Se,xe,he,Me,qe,A,ke,q,ge,O,H,y=[],He=new Map,Le,L,k=[],Ue=new Map,P;F=new at({props:{js:`
|
||||
import{S as lt,i as st,s as nt,V as at,W as tt,X as K,h as r,d as W,t as V,a as j,I as ve,Z as Ge,_ as ot,C as it,$ as rt,D as dt,l as d,n as l,m as X,u as a,A as _,v as b,c as Z,w as m,J as Ke,p as ct,k as Y,o as pt}from"./index-BH0nlDnw.js";import{F as ut}from"./FieldsQueryParam-DQVKTiQb.js";function We(o,s,n){const i=o.slice();return i[6]=s[n],i}function Xe(o,s,n){const i=o.slice();return i[6]=s[n],i}function Ze(o){let s;return{c(){s=a("p"),s.innerHTML="Requires superuser <code>Authorization:TOKEN</code> header",m(s,"class","txt-hint txt-sm txt-right")},m(n,i){d(n,s,i)},d(n){n&&r(s)}}}function Ye(o,s){let n,i,v;function p(){return s[5](s[6])}return{key:o,first:null,c(){n=a("button"),n.textContent=`${s[6].code} `,m(n,"class","tab-item"),Y(n,"active",s[2]===s[6].code),this.first=n},m(c,f){d(c,n,f),i||(v=pt(n,"click",p),i=!0)},p(c,f){s=c,f&20&&Y(n,"active",s[2]===s[6].code)},d(c){c&&r(n),i=!1,v()}}}function et(o,s){let n,i,v,p;return i=new tt({props:{content:s[6].body}}),{key:o,first:null,c(){n=a("div"),Z(i.$$.fragment),v=b(),m(n,"class","tab-item"),Y(n,"active",s[2]===s[6].code),this.first=n},m(c,f){d(c,n,f),X(i,n,null),l(n,v),p=!0},p(c,f){s=c,(!p||f&20)&&Y(n,"active",s[2]===s[6].code)},i(c){p||(j(i.$$.fragment,c),p=!0)},o(c){V(i.$$.fragment,c),p=!1},d(c){c&&r(n),W(i)}}}function ft(o){var Je,Ne;let s,n,i=o[0].name+"",v,p,c,f,w,C,ee,J=o[0].name+"",te,$e,le,F,se,B,ne,$,N,ye,Q,T,we,ae,z=o[0].name+"",oe,Ce,ie,Fe,re,I,de,S,ce,x,pe,R,ue,Re,M,D,fe,De,be,Oe,h,Pe,E,Te,Ee,Ae,me,Be,_e,Ie,Se,xe,he,Me,qe,A,ke,q,ge,O,H,y=[],He=new Map,Le,L,k=[],Ue=new Map,P;F=new at({props:{js:`
|
||||
import PocketBase from 'pocketbase';
|
||||
|
||||
const pb = new PocketBase('${o[3]}');
|
||||
Loaded 100 of 105 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user