mirror of
https://github.com/pocketbase/pocketbase.git
synced 2026-09-20 13:30:50 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f2eb295fa2 | ||
|
|
d11a9f9d99 | ||
|
|
bbd7f4e4ae | ||
|
|
b0a5bce4c4 | ||
|
|
9234cbf0d1 | ||
|
|
6bf5eccfa7 | ||
|
|
8bbd0c2d77 | ||
|
|
2af60a85c5 | ||
|
|
56e53e885c | ||
|
|
3115f08d4a | ||
|
|
0b9a646d41 | ||
|
|
5f8cce3558 | ||
|
|
3da2c00f32 | ||
|
|
352ee72740 | ||
|
|
98510103c3 | ||
|
|
25c044a3a2 | ||
|
|
0536c779d5 | ||
|
|
b1da83e516 | ||
|
|
6b5d7b216b | ||
|
|
26d6a98355 | ||
|
|
4abc018d7c | ||
|
|
f0a9cbf31b | ||
|
|
d08da7594a | ||
|
|
c2d6530065 | ||
|
|
94c4d4ec65 | ||
|
|
be7ec34516 | ||
|
|
27cb36ffd7 | ||
|
|
e7af58efac | ||
|
|
ab51b3c038 | ||
|
|
5773f46fea | ||
|
|
4d5b7cc1d0 | ||
|
|
7286f34104 | ||
|
|
4399a6c1ab | ||
|
|
e89603497f | ||
|
|
abb6bcd6de | ||
|
|
5604fe672e | ||
|
|
7825baab13 | ||
|
|
68b9d0e403 | ||
|
|
85232ed6e4 | ||
|
|
d76d4089cf | ||
|
|
2e5f8bff63 | ||
|
|
90d896e1cc | ||
|
|
c13d83adb1 | ||
|
|
9b73295a7c | ||
|
|
3c6ce2de74 | ||
|
|
63b89533a9 | ||
|
|
779059eca3 | ||
|
|
9abdadf0dc | ||
|
|
6500b8c518 | ||
|
|
91f1ca273d | ||
|
|
6e739fd33d | ||
|
|
2525f29c1c | ||
|
|
1dc5e061b8 | ||
|
|
09d7f6a7c3 | ||
|
|
1775585b68 | ||
|
|
f4e6c5edee | ||
|
|
94b11bf2c3 | ||
|
|
ddb8c88a37 | ||
|
|
0f5411d81c | ||
|
|
423d234da1 | ||
|
|
6184b31d82 | ||
|
|
63a9d045a1 |
@@ -26,9 +26,9 @@ jobs:
|
||||
node-version: 20.17.0
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: '>=1.24.8'
|
||||
go-version: '>=1.25.6'
|
||||
|
||||
# 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.
|
||||
|
||||
+100
-1
@@ -1,3 +1,102 @@
|
||||
## v0.36.0
|
||||
|
||||
- List query and API rules optimizations:
|
||||
- Removed unnecessary correlated subquery expression when using back-relations via single `relation` field.
|
||||
- Replaced `DISTINCT` with `GROUP BY id` when rows deduplication is needed and when deemed safe.
|
||||
_This should help with having a more stable and predictable performance even if the collection records are on the larger side._
|
||||
|
||||
For some queries and data sets the above 2 optimizations have shown significant improvements but if you notice a performance degradation after upgrading,
|
||||
please open a Q&A discussion with export of your collections structure and the problematic request so that it can be analyzed.
|
||||
|
||||
- Added [`strftime(format, timevalue, modifiers...)`](http://localhost:5173/docs/api-rules-and-filters/#strftimeformat-time-value-modifiers-) date formatting filter and API rules function.
|
||||
It works similarly to the [SQLite `strftime` builtin function](https://sqlite.org/lang_datefunc.html)
|
||||
with the main difference that NULL results will be normalized for consistency with the non-nullable PocketBase `text` and `date` fields.
|
||||
Multi-match expressions are also supported and works the same as if the collection field is referenced, for example:
|
||||
```js
|
||||
// requires ANY/AT-LEAST-ONE-OF multiRel records to have "created" date matching the formatted string "2026-01"
|
||||
strftime('%Y-%m', multiRel.created) ?= '2026-01'
|
||||
|
||||
// requires ALL multiRel records to have "created" date matching the formatted string "2026-01"
|
||||
strftime('%Y-%m', multiRel.created) = '2026-01'
|
||||
```
|
||||
|
||||
- ⚠️ Minor changes to the `search.ResolverResult` struct _(mostly used internally)_:
|
||||
- Replaced `NoCoalesce` field with the more explicit `NullFallback` _(`NullFallbackDisabled` is the same as `NoCoalesce:true`)_.
|
||||
- Replaced the expression interface of the `MultiMatchSubQuery` field with the concrete struct type `search.MultiMatchSubquery` to avoid excessive type assertions and allow direct mutations of the field.
|
||||
|
||||
- Updated `modernc.org/sqlite` to v1.44.1 _(SQLite 3.51.1)_.
|
||||
|
||||
- Bumped min Go GitHub action version to 1.25.6 because it comes with some [minor security fixes](https://github.com/golang/go/issues?q=milestone%3AGo1.25.6).
|
||||
|
||||
|
||||
## v0.35.1
|
||||
|
||||
- Updated `modernc.org/sqlite` to v1.43.0 _(query cancellation race fix)_.
|
||||
|
||||
- Other minor UI fixes (normalized relations picker selection and confirmation message when `maxSelect=0/1`, updated node deps).
|
||||
|
||||
|
||||
## v0.35.0
|
||||
|
||||
- Added `nullString()`, `nullInt()`, `nullFloat()`, `nullBool`, `nullArray()`, `nullObject()` JSVM helpers for scanning nullable columns ([#7396](https://github.com/pocketbase/pocketbase/issues/7396)).
|
||||
|
||||
- Store the correct `image/png` as attrs content type when generating a thumb fallback _(e.g. for `webp`)_.
|
||||
|
||||
- Trimmed custom uploaded file name and extension from leftover `.` characters after `filesystem.File` normalization.
|
||||
_This was done to prevent issues with external files sync programs that may have special handling for "invisible" files._
|
||||
|
||||
- Updated `modernc.org/sqlite` _(v1.41.0 includes prepared statements optimization)_ and other minor Go deps.
|
||||
|
||||
|
||||
## v0.34.2
|
||||
|
||||
- Bumped JS SDK to v0.26.5 to fix Safari AbortError detection introduced with the previous release ([#7369](https://github.com/pocketbase/pocketbase/issues/7369)).
|
||||
|
||||
|
||||
## v0.34.1
|
||||
|
||||
- Added missing `:` char to the autocomplete regex ([#7353](https://github.com/pocketbase/pocketbase/pull/7353); thanks @ouvreboite).
|
||||
|
||||
- Added "Copy raw JSON" collection dropdown option ([#7357](https://github.com/pocketbase/pocketbase/issues/7357)).
|
||||
|
||||
- Updated Go deps and JS SDK.
|
||||
|
||||
- Bumped min Go GitHub action version to 1.25.5 because it comes with some [minor security fixes](https://github.com/golang/go/issues?q=milestone%3AGo1.25.5).
|
||||
_The runner action was also updated to `actions/setup-go@v6` since the previous v5 Go source seems [no longer accessible](https://github.com/actions/setup-go/pull/665#issuecomment-3416693714)._
|
||||
|
||||
|
||||
## v0.34.0
|
||||
|
||||
- Added `@request.body.someField:changed` modifier.
|
||||
It could be used when you want to ensure that a body field either wasn't submitted or was submitted with the same value.
|
||||
Or in other words, if you want to disallow a field change the below 2 expressions would be equivalent:
|
||||
```js
|
||||
// (old)
|
||||
(@request.body.someField:isset = false || @request.body.someField = someField)
|
||||
|
||||
// (new)
|
||||
@request.body.someField:changed = false
|
||||
```
|
||||
|
||||
- Added `MailerRecordEvent.Meta["info"]` property for the `OnMailerRecordAuthAlertSend` hook.
|
||||
|
||||
- Updated the backup restore popup with a short info about the performed restore steps.
|
||||
|
||||
- Updated Go deps.
|
||||
|
||||
|
||||
## v0.33.0
|
||||
|
||||
- Added extra `id` characters validation in addition to the user specified regex pattern ([#7312](https://github.com/pocketbase/pocketbase/issues/7312)).
|
||||
_The following special characters are always forbidden: `./\|"'``<>:?*%$\n\r\t\0 `. Common reserved Windows file names such as `aux`, `prn`, `con`, `nul`, `com1-9`, `lpt1-9` are also not allowed._
|
||||
_The list is not exhaustive but it should help minimizing eventual filesystem compatibility issues in case of wildcards or other loose regex patterns._
|
||||
|
||||
- Added `{ALERT_INFO}` placeholder to the auth alert mail template ([#7314](https://github.com/pocketbase/pocketbase/issues/7314)).
|
||||
_⚠️ `mails.SendRecordAuthAlert(app, authRecord, info)` also now accepts a 3rd `info` string argument._
|
||||
|
||||
- Updated Go deps.
|
||||
|
||||
|
||||
## v0.32.0
|
||||
|
||||
- ⚠️ Added extra List/Search API rules checks for the client-side `filter`/`sort` relations.
|
||||
@@ -230,7 +329,7 @@
|
||||
If you are having difficulties adjusting your code, feel free to open a [Q&A discussion](https://github.com/pocketbase/pocketbase/discussions) with the failing/problematic code sample.
|
||||
|
||||
- Added [new `geoPoint` field](https://pocketbase.io/docs/collections/#geopoint) for storing `{"lon":x,"lat":y}` geographic coordinates.
|
||||
In addition, a new [`geoDistance(lonA, lotA, lonB, lotB)` function](htts://pocketbase.io/docs/api-rules-and-filters/#geodistancelona-lata-lonb-latb) was also implemented that could be used to apply an API rule or filter constraint based on the distance (in km) between 2 geo points.
|
||||
In addition, a new [`geoDistance(lonA, lotA, lonB, lotB)` function](https://pocketbase.io/docs/api-rules-and-filters/#geodistancelona-lata-lonb-latb) was also implemented that could be used to apply an API rule or filter constraint based on the distance (in km) between 2 geo points.
|
||||
|
||||
- Updated the `select` field UI to accommodate better larger lists and RTL languages ([#4674](https://github.com/pocketbase/pocketbase/issues/4674)).
|
||||
|
||||
|
||||
@@ -2,6 +2,19 @@
|
||||
> For the most recent versions, please refer to [CHANGELOG.md](./CHANGELOG.md)
|
||||
---
|
||||
|
||||
## v0.22.38
|
||||
|
||||
- (_Backported from v0.36.0_) Bumped min Go GitHub action version to 1.25.6 because it comes with some [minor security fixes](https://github.com/golang/go/issues?q=milestone%3AGo1.25.6).
|
||||
|
||||
|
||||
## v0.22.37
|
||||
|
||||
- (_Backported from v0.34.1_) - Added missing `:` char to the autocomplete regex ([#7353](https://github.com/pocketbase/pocketbase/pull/7353)).
|
||||
|
||||
- (_Backported from v0.34.1_) Bumped min Go GitHub action version to 1.25.5 because it comes with some [minor security fixes](https://github.com/golang/go/issues?q=milestone%3AGo1.25.5).
|
||||
_The runner action was also updated to `actions/setup-go@v6` since the previous v5 Go source seems [no longer accessible](https://github.com/actions/setup-go/pull/665#issuecomment-3416693714)._
|
||||
|
||||
|
||||
## v0.22.36
|
||||
|
||||
- (_Backported from v0.30.2_) Bumped min Go GitHub action version to 1.24.8 since it comes with some [minor security fixes](https://github.com/golang/go/issues?q=milestone%3AGo1.24.8+label%3ACherryPickApproved).
|
||||
|
||||
@@ -234,12 +234,12 @@ func newRateLimiter(maxAllowed int, intervalInSec int64, minDeleteIntervalInSec
|
||||
maxAllowed: maxAllowed,
|
||||
interval: intervalInSec,
|
||||
minDeleteInterval: minDeleteIntervalInSec,
|
||||
clients: map[string]*fixedWindow{},
|
||||
clients: map[string]*rateClient{},
|
||||
}
|
||||
}
|
||||
|
||||
type rateLimiter struct {
|
||||
clients map[string]*fixedWindow
|
||||
clients map[string]*rateClient
|
||||
|
||||
maxAllowed int
|
||||
interval int64
|
||||
@@ -250,7 +250,7 @@ type rateLimiter struct {
|
||||
}
|
||||
|
||||
//nolint:unused
|
||||
func (rt *rateLimiter) getClient(key string) (*fixedWindow, bool) {
|
||||
func (rt *rateLimiter) getClient(key string) (*rateClient, bool) {
|
||||
rt.RLock()
|
||||
client, ok := rt.clients[key]
|
||||
rt.RUnlock()
|
||||
@@ -269,7 +269,7 @@ func (rt *rateLimiter) isAllowed(key string) bool {
|
||||
// check again in case the client was added by another request
|
||||
client, ok = rt.clients[key]
|
||||
if !ok {
|
||||
client = newFixedWindow(rt.maxAllowed, rt.interval)
|
||||
client = newRateClient(rt.maxAllowed, rt.interval)
|
||||
rt.clients[key] = client
|
||||
}
|
||||
rt.Unlock()
|
||||
@@ -295,7 +295,7 @@ func (rt *rateLimiter) clean() {
|
||||
//
|
||||
// @todo remove after https://github.com/golang/go/issues/20135
|
||||
if rt.totalDeleted >= 300 {
|
||||
shrunk := make(map[string]*fixedWindow, len(rt.clients))
|
||||
shrunk := make(map[string]*rateClient, len(rt.clients))
|
||||
for k, v := range rt.clients {
|
||||
shrunk[k] = v
|
||||
}
|
||||
@@ -304,14 +304,20 @@ func (rt *rateLimiter) clean() {
|
||||
}
|
||||
}
|
||||
|
||||
func newFixedWindow(maxAllowed int, intervalInSec int64) *fixedWindow {
|
||||
return &fixedWindow{
|
||||
func newRateClient(maxAllowed int, intervalInSec int64) *rateClient {
|
||||
return &rateClient{
|
||||
maxAllowed: maxAllowed,
|
||||
interval: intervalInSec,
|
||||
}
|
||||
}
|
||||
|
||||
type fixedWindow struct {
|
||||
// @todo evaluate swiching to a more traditional fixed window or sliding window counter
|
||||
// implementations since some users complained that it is not intuitive (see #7329).
|
||||
//
|
||||
// rateClient is a mixture of token bucket and fixed window rate limit strategies
|
||||
// that refills the allowance only after at least "interval" seconds
|
||||
// has elapsed since the last request.
|
||||
type rateClient struct {
|
||||
// use plain Mutex instead of RWMutex since the operations are expected
|
||||
// to be mostly writes (e.g. consume()) and it should perform better
|
||||
sync.Mutex
|
||||
@@ -324,18 +330,18 @@ type fixedWindow struct {
|
||||
|
||||
// hasExpired checks whether it has been at least minElapsed seconds since the lastConsume time.
|
||||
// (usually used to perform periodic cleanup of staled instances).
|
||||
func (l *fixedWindow) hasExpired(relativeNow int64, minElapsed int64) bool {
|
||||
func (l *rateClient) hasExpired(relativeNow int64, minElapsed int64) bool {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
return relativeNow-l.lastConsume > minElapsed
|
||||
}
|
||||
|
||||
// consume decrease the current window allowance with 1 (if not exhausted already).
|
||||
// consume decreases the current allowance with 1 (if not exhausted already).
|
||||
//
|
||||
// It returns false if the allowance has been already exhausted and the user
|
||||
// has to wait until it resets back to its maxAllowed value.
|
||||
func (l *fixedWindow) consume() bool {
|
||||
func (l *rateClient) consume() bool {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
|
||||
+10
-5
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/pocketbase/pocketbase/tools/routine"
|
||||
"github.com/pocketbase/pocketbase/tools/search"
|
||||
"github.com/pocketbase/pocketbase/tools/security"
|
||||
"github.com/pocketbase/pocketbase/tools/types"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -579,13 +580,17 @@ func execAfterSuccessTx(checkTx bool, app core.App, fn func() error) error {
|
||||
const maxAuthOrigins = 5
|
||||
|
||||
func authAlert(e *core.RequestEvent, authRecord *core.Record) error {
|
||||
// generating fingerprint
|
||||
// generate fingerprint
|
||||
// ---
|
||||
ip := e.RealIP()
|
||||
|
||||
userAgent := e.Request.UserAgent()
|
||||
if len(userAgent) > 300 {
|
||||
userAgent = userAgent[:300]
|
||||
if len(userAgent) > 200 {
|
||||
userAgent = userAgent[:200] + "..."
|
||||
}
|
||||
fingerprint := security.MD5(e.RealIP() + userAgent)
|
||||
|
||||
fingerprint := security.MD5(ip + userAgent)
|
||||
alertInfo := fmt.Sprintf("%s - %s %s", types.NowDateTime().String(), ip, userAgent)
|
||||
// ---
|
||||
|
||||
origins, err := e.App.FindAllAuthOriginsByRecord(authRecord)
|
||||
@@ -625,7 +630,7 @@ func authAlert(e *core.RequestEvent, authRecord *core.Record) error {
|
||||
})
|
||||
|
||||
routine.FireAndForget(func() {
|
||||
err := mails.SendRecordAuthAlert(e.App, authRecord)
|
||||
err := mails.SendRecordAuthAlert(e.App, authRecord, alertInfo)
|
||||
timer.Stop()
|
||||
mailSent <- err
|
||||
})
|
||||
|
||||
@@ -2,11 +2,12 @@ package core
|
||||
|
||||
// Common settings placeholder tokens
|
||||
const (
|
||||
EmailPlaceholderAppName string = "{APP_NAME}"
|
||||
EmailPlaceholderAppURL string = "{APP_URL}"
|
||||
EmailPlaceholderToken string = "{TOKEN}"
|
||||
EmailPlaceholderOTP string = "{OTP}"
|
||||
EmailPlaceholderOTPId string = "{OTP_ID}"
|
||||
EmailPlaceholderAppName string = "{APP_NAME}"
|
||||
EmailPlaceholderAppURL string = "{APP_URL}"
|
||||
EmailPlaceholderToken string = "{TOKEN}"
|
||||
EmailPlaceholderOTP string = "{OTP}"
|
||||
EmailPlaceholderOTPId string = "{OTP_ID}"
|
||||
EmailPlaceholderAlertInfo string = "{ALERT_INFO}"
|
||||
)
|
||||
|
||||
var defaultVerificationTemplate = EmailTemplate{
|
||||
@@ -65,9 +66,10 @@ var defaultOTPTemplate = EmailTemplate{
|
||||
var defaultAuthAlertTemplate = EmailTemplate{
|
||||
Subject: "Login from a new location",
|
||||
Body: `<p>Hello,</p>
|
||||
<p>We noticed a login to your ` + EmailPlaceholderAppName + ` account from a new location.</p>
|
||||
<p>If this was you, you may disregard this email.</p>
|
||||
<p>We noticed a login to your ` + EmailPlaceholderAppName + ` account from a new location:</p>
|
||||
<p><em>` + EmailPlaceholderAlertInfo + `</em></p>
|
||||
<p><strong>If this wasn't you, you should immediately change your ` + EmailPlaceholderAppName + ` account password to revoke access from all other locations.</strong></p>
|
||||
<p>If this was you, you may disregard this email.</p>
|
||||
<p>
|
||||
Thanks,<br/>
|
||||
` + EmailPlaceholderAppName + ` team
|
||||
|
||||
@@ -489,7 +489,7 @@ func (validator *collectionValidator) checkRule(value any) error {
|
||||
return nil // nothing to check
|
||||
}
|
||||
|
||||
r := NewRecordFieldResolver(validator.app, validator.new, nil, true)
|
||||
r := NewRecordFieldResolver(validator.app, validator.new, &RequestInfo{}, true)
|
||||
_, err := search.FilterData(vStr).BuildExpr(r)
|
||||
if err != nil {
|
||||
return validation.NewError("validation_invalid_rule", "Invalid rule. Raw error: "+err.Error())
|
||||
|
||||
@@ -319,8 +319,8 @@ func TestCollectionValidate(t *testing.T) {
|
||||
c.ListRule = types.Pointer("!invalid")
|
||||
c.ViewRule = types.Pointer("missing = 123")
|
||||
c.CreateRule = types.Pointer("id = 123 && missing = 456")
|
||||
c.UpdateRule = types.Pointer("(id = 123")
|
||||
c.DeleteRule = types.Pointer("missing = 123")
|
||||
c.UpdateRule = types.Pointer("@request.body.missing:changed = false")
|
||||
c.DeleteRule = types.Pointer("(id=123")
|
||||
return c, nil
|
||||
},
|
||||
expectedErrors: []string{"listRule", "viewRule", "createRule", "updateRule", "deleteRule"},
|
||||
@@ -333,7 +333,7 @@ func TestCollectionValidate(t *testing.T) {
|
||||
c.ListRule = types.Pointer("")
|
||||
c.ViewRule = types.Pointer("f1 = 123")
|
||||
c.CreateRule = types.Pointer("id = 123 && f1 = 456")
|
||||
c.UpdateRule = types.Pointer("(id = 123)")
|
||||
c.UpdateRule = types.Pointer("(id = 123 && @request.body.f1:changed = false)")
|
||||
c.DeleteRule = types.Pointer("f1 = 123")
|
||||
return c, nil
|
||||
},
|
||||
|
||||
+39
-14
@@ -31,6 +31,22 @@ var (
|
||||
_ RecordInterceptor = (*TextField)(nil)
|
||||
)
|
||||
|
||||
var forbiddenPKCharacters = []string{
|
||||
".", "/", `\`, "|", `"`, "'", "`",
|
||||
"<", ">", ":", "?", "*", "%", "$",
|
||||
"\000", "\t", "\n", "\r", " ",
|
||||
}
|
||||
|
||||
// (see largestReservedPKLength)
|
||||
var caseInsensitiveReservedPKs = []string{
|
||||
// reserved Windows files names
|
||||
"CON", "PRN", "AUX", "NUL",
|
||||
"COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
|
||||
"LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
|
||||
}
|
||||
|
||||
const largestReservedPKLength = 4
|
||||
|
||||
// TextField defines "text" type field for storing any string value.
|
||||
//
|
||||
// The respective zero record field value is empty string.
|
||||
@@ -155,8 +171,6 @@ func (f *TextField) PrepareValue(record *Record, raw any) (any, error) {
|
||||
return cast.ToString(raw), nil
|
||||
}
|
||||
|
||||
var forbiddenPKChars = []string{"/", "\\"}
|
||||
|
||||
// ValidateValue implements [Field.ValidateValue] interface method.
|
||||
func (f *TextField) ValidateValue(ctx context.Context, app App, record *Record) error {
|
||||
newVal, ok := record.GetRaw(f.Name).(string)
|
||||
@@ -178,15 +192,6 @@ func (f *TextField) ValidateValue(ctx context.Context, app App, record *Record)
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
// disallow PK special characters no matter of the Pattern validator to minimize
|
||||
// side-effects when the primary key is used for example in a directory path
|
||||
for _, c := range forbiddenPKChars {
|
||||
if strings.Contains(newVal, c) {
|
||||
return validation.NewError("validation_pk_forbidden", "The record primary key contains forbidden characters.").
|
||||
SetParams(map[string]any{"forbidden": c})
|
||||
}
|
||||
}
|
||||
|
||||
// this technically shouldn't be necessarily but again to
|
||||
// minimize misuse of the Pattern validator that could cause
|
||||
// side-effects on some platforms check for duplicates in a case-insensitive manner
|
||||
@@ -226,7 +231,7 @@ func (f *TextField) ValidatePlainValue(value string) error {
|
||||
length := len([]rune(value))
|
||||
|
||||
if f.Min > 0 && length < f.Min {
|
||||
return validation.NewError("validation_min_text_constraint", "Must be at least {{.min}} character(s)").
|
||||
return validation.NewError("validation_min_text_constraint", "Must be at least {{.min}} character(s).").
|
||||
SetParams(map[string]any{"min": f.Min})
|
||||
}
|
||||
|
||||
@@ -236,14 +241,34 @@ func (f *TextField) ValidatePlainValue(value string) error {
|
||||
}
|
||||
|
||||
if max > 0 && length > max {
|
||||
return validation.NewError("validation_max_text_constraint", "Must be no more than {{.max}} character(s)").
|
||||
return validation.NewError("validation_max_text_constraint", "Must be no more than {{.max}} character(s).").
|
||||
SetParams(map[string]any{"max": max})
|
||||
}
|
||||
|
||||
if f.Pattern != "" {
|
||||
match, _ := regexp.MatchString(f.Pattern, value)
|
||||
if !match {
|
||||
return validation.NewError("validation_invalid_format", "Invalid value format")
|
||||
return validation.NewError("validation_invalid_format", "Invalid value format.")
|
||||
}
|
||||
}
|
||||
|
||||
// additional primary key checks to minimize eventual filesystem compatibility issues
|
||||
// because the primary key is often used as a file/directory name
|
||||
if f.PrimaryKey && f.Pattern != defaultLowercaseRecordIdPattern {
|
||||
for _, ch := range forbiddenPKCharacters {
|
||||
if strings.Contains(value, ch) {
|
||||
return validation.NewError("validation_forbidden_pk_character", "'{{.ch}}' is not a valid primary key character.").
|
||||
SetParams(map[string]any{"ch": ch})
|
||||
}
|
||||
}
|
||||
|
||||
if largestReservedPKLength >= length {
|
||||
for _, reserved := range caseInsensitiveReservedPKs {
|
||||
if strings.EqualFold(value, reserved) {
|
||||
return validation.NewError("validation_reserved_pk", "The primary key '{{.reserved}}' is reserved and cannot be used.").
|
||||
SetParams(map[string]any{"reserved": reserved})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+94
-4
@@ -129,7 +129,7 @@ func TestTextFieldValidateValue(t *testing.T) {
|
||||
&core.TextField{Name: "test", PrimaryKey: false},
|
||||
func() *core.Record {
|
||||
record := core.NewRecord(collection)
|
||||
record.SetRaw("test", "/")
|
||||
record.SetRaw("test", "abc/")
|
||||
return record
|
||||
},
|
||||
false,
|
||||
@@ -139,7 +139,37 @@ func TestTextFieldValidateValue(t *testing.T) {
|
||||
&core.TextField{Name: "test", PrimaryKey: false},
|
||||
func() *core.Record {
|
||||
record := core.NewRecord(collection)
|
||||
record.SetRaw("test", "\\")
|
||||
record.SetRaw("test", "abc\\")
|
||||
return record
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"special forbidden character . (non-primaryKey)",
|
||||
&core.TextField{Name: "test", PrimaryKey: false},
|
||||
func() *core.Record {
|
||||
record := core.NewRecord(collection)
|
||||
record.SetRaw("test", "abc.")
|
||||
return record
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"special forbidden character ' ' (non-primaryKey)",
|
||||
&core.TextField{Name: "test", PrimaryKey: false},
|
||||
func() *core.Record {
|
||||
record := core.NewRecord(collection)
|
||||
record.SetRaw("test", "ab c")
|
||||
return record
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"special forbidden character * (non-primaryKey)",
|
||||
&core.TextField{Name: "test", PrimaryKey: false},
|
||||
func() *core.Record {
|
||||
record := core.NewRecord(collection)
|
||||
record.SetRaw("test", "abc*")
|
||||
return record
|
||||
},
|
||||
false,
|
||||
@@ -149,7 +179,7 @@ func TestTextFieldValidateValue(t *testing.T) {
|
||||
&core.TextField{Name: "test", PrimaryKey: true},
|
||||
func() *core.Record {
|
||||
record := core.NewRecord(collection)
|
||||
record.SetRaw("test", "/")
|
||||
record.SetRaw("test", "abc/")
|
||||
return record
|
||||
},
|
||||
true,
|
||||
@@ -159,11 +189,71 @@ func TestTextFieldValidateValue(t *testing.T) {
|
||||
&core.TextField{Name: "test", PrimaryKey: true},
|
||||
func() *core.Record {
|
||||
record := core.NewRecord(collection)
|
||||
record.SetRaw("test", "\\")
|
||||
record.SetRaw("test", "abc\\")
|
||||
return record
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"special forbidden character . (primaryKey)",
|
||||
&core.TextField{Name: "test", PrimaryKey: true},
|
||||
func() *core.Record {
|
||||
record := core.NewRecord(collection)
|
||||
record.SetRaw("test", "abc.")
|
||||
return record
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"special forbidden character ' ' (primaryKey)",
|
||||
&core.TextField{Name: "test", PrimaryKey: true},
|
||||
func() *core.Record {
|
||||
record := core.NewRecord(collection)
|
||||
record.SetRaw("test", "ab c")
|
||||
return record
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"special forbidden character * (primaryKey; used in the realtime events too)",
|
||||
&core.TextField{Name: "test", PrimaryKey: true},
|
||||
func() *core.Record {
|
||||
record := core.NewRecord(collection)
|
||||
record.SetRaw("test", "abc*")
|
||||
return record
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"reserved pk literal (non-primaryKey)",
|
||||
&core.TextField{Name: "test", PrimaryKey: false},
|
||||
func() *core.Record {
|
||||
record := core.NewRecord(collection)
|
||||
record.SetRaw("test", "aUx")
|
||||
return record
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"reserved pk literal (primaryKey)",
|
||||
&core.TextField{Name: "test", PrimaryKey: true},
|
||||
func() *core.Record {
|
||||
record := core.NewRecord(collection)
|
||||
record.SetRaw("test", "aUx")
|
||||
return record
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"reserved pk literal (non-exact match, primaryKey)",
|
||||
&core.TextField{Name: "test", PrimaryKey: true},
|
||||
func() *core.Record {
|
||||
record := core.NewRecord(collection)
|
||||
record.SetRaw("test", "aUx-")
|
||||
return record
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"zero field value (primaryKey)",
|
||||
&core.TextField{Name: "test", PrimaryKey: true},
|
||||
|
||||
+104
-23
@@ -9,6 +9,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/tools/inflector"
|
||||
"github.com/pocketbase/pocketbase/tools/search"
|
||||
"github.com/pocketbase/pocketbase/tools/security"
|
||||
"github.com/pocketbase/pocketbase/tools/types"
|
||||
@@ -17,10 +18,11 @@ import (
|
||||
|
||||
// filter modifiers
|
||||
const (
|
||||
eachModifier string = "each"
|
||||
issetModifier string = "isset"
|
||||
lengthModifier string = "length"
|
||||
lowerModifier string = "lower"
|
||||
eachModifier string = "each"
|
||||
issetModifier string = "isset"
|
||||
lengthModifier string = "length"
|
||||
lowerModifier string = "lower"
|
||||
changedModifier string = "changed"
|
||||
)
|
||||
|
||||
// ensure that `search.FieldResolver` interface is implemented
|
||||
@@ -46,7 +48,7 @@ type RecordFieldResolver struct {
|
||||
requestInfo *RequestInfo
|
||||
staticRequestInfo map[string]any
|
||||
allowedFields []string
|
||||
joins []*join
|
||||
joins []*search.Join
|
||||
allowHiddenFields bool
|
||||
// ---
|
||||
listRuleJoins map[string]*Collection // tableAlias->collection
|
||||
@@ -86,7 +88,7 @@ func NewRecordFieldResolver(
|
||||
baseCollection: baseCollection,
|
||||
requestInfo: requestInfo,
|
||||
allowHiddenFields: allowHiddenFields, // note: it is not based only on the requestInfo.auth since it could be used by a non-request internal method
|
||||
joins: []*join{},
|
||||
joins: []*search.Join{},
|
||||
allowedFields: []string{
|
||||
`^\w+[\w\.\:]*$`,
|
||||
`^\@request\.context$`,
|
||||
@@ -127,12 +129,12 @@ func NewRecordFieldResolver(
|
||||
// resolved fields (eg. dynamically joining relations).
|
||||
func (r *RecordFieldResolver) UpdateQuery(query *dbx.SelectQuery) error {
|
||||
if len(r.joins) > 0 {
|
||||
query.Distinct(true)
|
||||
r.updateQueryWithDeduplicateConstraint(query)
|
||||
|
||||
for _, join := range r.joins {
|
||||
query.LeftJoin(
|
||||
(join.tableName + " " + join.tableAlias),
|
||||
join.on,
|
||||
(join.TableName + " " + join.TableAlias),
|
||||
join.On,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -156,11 +158,11 @@ func (r *RecordFieldResolver) updateQueryWithCollectionListRule(c *Collection, t
|
||||
}
|
||||
|
||||
cloneR := *r
|
||||
cloneR.joins = []*join{}
|
||||
cloneR.joins = []*search.Join{}
|
||||
cloneR.baseCollection = c
|
||||
cloneR.baseCollectionAlias = tableAlias
|
||||
cloneR.allowHiddenFields = true
|
||||
cloneR.joinAliasSuffix = security.PseudorandomString(6)
|
||||
cloneR.joinAliasSuffix = security.PseudorandomString(8)
|
||||
|
||||
expr, err := search.FilterData(*c.ListRule).BuildExpr(&cloneR)
|
||||
if err != nil {
|
||||
@@ -170,12 +172,12 @@ func (r *RecordFieldResolver) updateQueryWithCollectionListRule(c *Collection, t
|
||||
query.AndWhere(expr)
|
||||
|
||||
if len(cloneR.joins) > 0 {
|
||||
query.Distinct(true)
|
||||
r.updateQueryWithDeduplicateConstraint(query)
|
||||
|
||||
for _, j := range cloneR.joins {
|
||||
query.LeftJoin(
|
||||
(j.tableName + " " + j.tableAlias),
|
||||
j.on,
|
||||
(j.TableName + " " + j.TableAlias),
|
||||
j.On,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -183,6 +185,72 @@ func (r *RecordFieldResolver) updateQueryWithCollectionListRule(c *Collection, t
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *RecordFieldResolver) updateQueryWithDeduplicateConstraint(query *dbx.SelectQuery) {
|
||||
info := query.Info()
|
||||
|
||||
if info.Distinct {
|
||||
return
|
||||
}
|
||||
|
||||
// already has the group by registered
|
||||
var groupByCol = r.baseCollection.Name
|
||||
if r.baseCollectionAlias != "" {
|
||||
groupByCol = r.baseCollectionAlias
|
||||
}
|
||||
groupByCol += ".id"
|
||||
if len(info.GroupBy) > 0 && info.GroupBy[0] == groupByCol {
|
||||
return
|
||||
}
|
||||
|
||||
// when deemed safe (GROUP BY could have different execution order compared to DISTINCT),
|
||||
// prefer GROUP BY to deduplicate only on the id field instead of all columns
|
||||
// so that the size of a single row wouldn't matter that much
|
||||
if preferGroupBy(info, groupByCol) {
|
||||
query.GroupBy(groupByCol)
|
||||
} else {
|
||||
query.Distinct(true)
|
||||
}
|
||||
}
|
||||
|
||||
func preferGroupBy(info *dbx.QueryInfo, fullUnquotedGroupByCol string) bool {
|
||||
if len(info.GroupBy) != 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
if info.Having != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// dbx fallbacks to * if not set
|
||||
if len(info.Selects) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
if len(info.Selects) != 1 {
|
||||
return false
|
||||
}
|
||||
|
||||
identifier := info.Selects[0]
|
||||
|
||||
if identifier == "*" || identifier == fullUnquotedGroupByCol {
|
||||
return true
|
||||
}
|
||||
|
||||
// try again as direct col match in an unquoted column format
|
||||
identifier = inflector.Columnify(identifier)
|
||||
if identifier == fullUnquotedGroupByCol {
|
||||
return true
|
||||
}
|
||||
|
||||
// remains table.* to check
|
||||
// (aliased columns for now are ignored as they could be represented by expressions)
|
||||
if !strings.HasSuffix(identifier, ".*") {
|
||||
return false
|
||||
}
|
||||
|
||||
return strings.HasPrefix(fullUnquotedGroupByCol, strings.TrimSuffix(identifier, "*"))
|
||||
}
|
||||
|
||||
// Resolve implements `search.FieldResolver` interface.
|
||||
//
|
||||
// Example of some resolvable fieldName formats:
|
||||
@@ -235,7 +303,7 @@ func (r *RecordFieldResolver) resolveStaticRequestField(path ...string) (*search
|
||||
|
||||
switch v := resultVal.(type) {
|
||||
case nil:
|
||||
return &search.ResolverResult{Identifier: "NULL"}, nil
|
||||
// no further processing is needed...
|
||||
case string:
|
||||
// check if it is a number field and explicitly try to cast to
|
||||
// float in case of a numeric string value was used
|
||||
@@ -265,8 +333,20 @@ func (r *RecordFieldResolver) resolveStaticRequestField(path ...string) (*search
|
||||
resultVal = val
|
||||
}
|
||||
|
||||
placeholder := "f" + security.PseudorandomString(8)
|
||||
// unsupported modifier
|
||||
// @todo consider deprecating with the introduction of filter functions
|
||||
if modifier != "" && modifier != lowerModifier {
|
||||
return nil, fmt.Errorf("invalid modifier sequence %s:%s", lastProp, modifier)
|
||||
}
|
||||
|
||||
// no need to wrap as placeholder if we already know that it is null
|
||||
if resultVal == nil {
|
||||
return &search.ResolverResult{Identifier: "NULL"}, nil
|
||||
}
|
||||
|
||||
placeholder := "f" + security.PseudorandomString(10)
|
||||
|
||||
// @todo consider deprecating with the introduction of filter functions
|
||||
if modifier == lowerModifier {
|
||||
return &search.ResolverResult{
|
||||
Identifier: "LOWER({:" + placeholder + "})",
|
||||
@@ -289,10 +369,10 @@ func (r *RecordFieldResolver) loadCollection(collectionNameOrId string) (*Collec
|
||||
}
|
||||
|
||||
func (r *RecordFieldResolver) registerJoin(tableName string, tableAlias string, on dbx.Expression) error {
|
||||
newJoin := &join{
|
||||
tableName: tableName,
|
||||
tableAlias: tableAlias,
|
||||
on: on,
|
||||
newJoin := &search.Join{
|
||||
TableName: tableName,
|
||||
TableAlias: tableAlias,
|
||||
On: on,
|
||||
}
|
||||
|
||||
// (see updateQueryWithCollectionListRule)
|
||||
@@ -309,13 +389,13 @@ func (r *RecordFieldResolver) registerJoin(tableName string, tableAlias string,
|
||||
if r.listRuleJoins == nil {
|
||||
r.listRuleJoins = map[string]*Collection{}
|
||||
}
|
||||
r.listRuleJoins[newJoin.tableAlias] = c
|
||||
r.listRuleJoins[newJoin.TableAlias] = c
|
||||
}
|
||||
}
|
||||
|
||||
// replace existing join
|
||||
for i, j := range r.joins {
|
||||
if j.tableAlias == newJoin.tableAlias {
|
||||
if j.TableAlias == newJoin.TableAlias {
|
||||
r.joins[i] = newJoin
|
||||
return nil
|
||||
}
|
||||
@@ -463,7 +543,8 @@ func splitModifier(combined string) (string, string, error) {
|
||||
case issetModifier,
|
||||
eachModifier,
|
||||
lengthModifier,
|
||||
lowerModifier:
|
||||
lowerModifier,
|
||||
changedModifier:
|
||||
return parts[0], parts[1], nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
)
|
||||
|
||||
var _ dbx.Expression = (*multiMatchSubquery)(nil)
|
||||
|
||||
// join defines the specification for a single SQL JOIN clause.
|
||||
type join struct {
|
||||
tableName string
|
||||
tableAlias string
|
||||
on dbx.Expression
|
||||
}
|
||||
|
||||
// multiMatchSubquery defines a record multi-match subquery expression.
|
||||
type multiMatchSubquery struct {
|
||||
baseTableAlias string
|
||||
fromTableName string
|
||||
fromTableAlias string
|
||||
valueIdentifier string
|
||||
joins []*join
|
||||
params dbx.Params
|
||||
}
|
||||
|
||||
// Build converts the expression into a SQL fragment.
|
||||
//
|
||||
// Implements [dbx.Expression] interface.
|
||||
func (m *multiMatchSubquery) Build(db *dbx.DB, params dbx.Params) string {
|
||||
if m.baseTableAlias == "" || m.fromTableName == "" || m.fromTableAlias == "" {
|
||||
return "0=1"
|
||||
}
|
||||
|
||||
if params == nil {
|
||||
params = m.params
|
||||
} else {
|
||||
// merge by updating the parent params
|
||||
for k, v := range m.params {
|
||||
params[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
var mergedJoins strings.Builder
|
||||
for i, j := range m.joins {
|
||||
if i > 0 {
|
||||
mergedJoins.WriteString(" ")
|
||||
}
|
||||
mergedJoins.WriteString("LEFT JOIN ")
|
||||
mergedJoins.WriteString(db.QuoteTableName(j.tableName))
|
||||
mergedJoins.WriteString(" ")
|
||||
mergedJoins.WriteString(db.QuoteTableName(j.tableAlias))
|
||||
if j.on != nil {
|
||||
mergedJoins.WriteString(" ON ")
|
||||
mergedJoins.WriteString(j.on.Build(db, params))
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Sprintf(
|
||||
`SELECT %s as [[multiMatchValue]] FROM %s %s %s WHERE %s = %s`,
|
||||
db.QuoteColumnName(m.valueIdentifier),
|
||||
db.QuoteTableName(m.fromTableName),
|
||||
db.QuoteTableName(m.fromTableAlias),
|
||||
mergedJoins.String(),
|
||||
db.QuoteColumnName(m.fromTableAlias+".id"),
|
||||
db.QuoteColumnName(m.baseTableAlias+".id"),
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
)
|
||||
|
||||
var _ dbx.Expression = (*replaceWithExpression)(nil)
|
||||
|
||||
// replaceWithExpression defines a custom expression that will replace
|
||||
// a placeholder identifier found in "old" with the result of "new".
|
||||
type replaceWithExpression struct {
|
||||
placeholder string
|
||||
old dbx.Expression
|
||||
new dbx.Expression
|
||||
}
|
||||
|
||||
// Build converts the expression into a SQL fragment.
|
||||
//
|
||||
// Implements [dbx.Expression] interface.
|
||||
func (e *replaceWithExpression) Build(db *dbx.DB, params dbx.Params) string {
|
||||
if e.placeholder == "" || e.old == nil || e.new == nil {
|
||||
return "0=1"
|
||||
}
|
||||
|
||||
oldResult := e.old.Build(db, params)
|
||||
newResult := e.new.Build(db, params)
|
||||
|
||||
return strings.ReplaceAll(oldResult, e.placeholder, newResult)
|
||||
}
|
||||
@@ -49,13 +49,13 @@ type runner struct {
|
||||
|
||||
// shared processing state
|
||||
// ---------------------------------------------------------------
|
||||
activeProps []string // holds the active props that remains to be processed
|
||||
activeCollectionName string // the last used collection name
|
||||
activeTableAlias string // the last used table alias
|
||||
nullifyMisingField bool // indicating whether to return null on missing field or return an error
|
||||
withMultiMatch bool // indicates whether to attach a multiMatchSubquery condition to the ResolverResult
|
||||
multiMatchActiveTableAlias string // the last used multi-match table alias
|
||||
multiMatch *multiMatchSubquery // the multi-match subquery expression generated from the fieldName
|
||||
activeProps []string // holds the active props that remains to be processed
|
||||
activeCollectionName string // the last used collection name
|
||||
activeTableAlias string // the last used table alias
|
||||
nullifyMisingField bool // indicating whether to return null on missing field or return an error
|
||||
withMultiMatch bool // indicates whether to attach a MultiMatchSubquery condition to the ResolverResult
|
||||
multiMatchActiveTableAlias string // the last used multi-match table alias
|
||||
multiMatch *search.MultiMatchSubquery // the multi-match subquery expression generated from the fieldName
|
||||
}
|
||||
|
||||
func (r *runner) run() (*search.ResolverResult, error) {
|
||||
@@ -80,6 +80,7 @@ func (r *runner) run() (*search.ResolverResult, error) {
|
||||
}
|
||||
|
||||
if r.activeProps[0] == "@request" {
|
||||
// @todo consider returning an error instead?
|
||||
if r.resolver.requestInfo == nil {
|
||||
return &search.ResolverResult{Identifier: "NULL"}, nil
|
||||
}
|
||||
@@ -88,7 +89,9 @@ func (r *runner) run() (*search.ResolverResult, error) {
|
||||
return r.processRequestAuthField()
|
||||
}
|
||||
|
||||
if strings.HasPrefix(r.fieldName, "@request.body.") && len(r.activeProps) > 2 {
|
||||
totalProps := len(r.activeProps)
|
||||
|
||||
if strings.HasPrefix(r.fieldName, "@request.body.") && totalProps > 2 {
|
||||
name, modifier, err := splitModifier(r.activeProps[2])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -100,23 +103,21 @@ func (r *runner) run() (*search.ResolverResult, error) {
|
||||
}
|
||||
|
||||
// check for body relation field
|
||||
if bodyField.Type() == FieldTypeRelation && len(r.activeProps) > 3 {
|
||||
return r.processRequestInfoRelationField(bodyField)
|
||||
if bodyField.Type() == FieldTypeRelation && totalProps > 3 {
|
||||
return r.processRequestBodyRelationField(bodyField)
|
||||
}
|
||||
|
||||
// check for body arrayble fields ":each" modifier
|
||||
if modifier == eachModifier && len(r.activeProps) == 3 {
|
||||
return r.processRequestInfoEachModifier(bodyField)
|
||||
}
|
||||
|
||||
// check for body arrayble fields ":length" modifier
|
||||
if modifier == lengthModifier && len(r.activeProps) == 3 {
|
||||
return r.processRequestInfoLengthModifier(bodyField)
|
||||
}
|
||||
|
||||
// check for body arrayble fields ":lower" modifier
|
||||
if modifier == lowerModifier && len(r.activeProps) == 3 {
|
||||
return r.processRequestInfoLowerModifier(bodyField)
|
||||
if totalProps == 3 { // aka. last prop
|
||||
switch modifier {
|
||||
case eachModifier:
|
||||
return r.processRequestBodyEachModifier(bodyField)
|
||||
case lengthModifier:
|
||||
return r.processRequestBodyLengthModifier(bodyField)
|
||||
case lowerModifier:
|
||||
return r.processRequestBodyLowerModifier(bodyField)
|
||||
case changedModifier:
|
||||
return r.processRequestBodyChangedModifier(bodyField)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,13 +144,13 @@ func (r *runner) prepare() {
|
||||
r.nullifyMisingField = r.activeProps[0] == "@request"
|
||||
|
||||
// prepare a multi-match subquery
|
||||
r.multiMatch = &multiMatchSubquery{
|
||||
baseTableAlias: r.activeTableAlias,
|
||||
params: dbx.Params{},
|
||||
r.multiMatch = &search.MultiMatchSubquery{
|
||||
TargetTableAlias: r.activeTableAlias,
|
||||
Params: dbx.Params{},
|
||||
}
|
||||
r.multiMatch.fromTableName = inflector.Columnify(r.activeCollectionName)
|
||||
r.multiMatch.fromTableAlias = "__mm_" + r.activeTableAlias
|
||||
r.multiMatchActiveTableAlias = r.multiMatch.fromTableAlias
|
||||
r.multiMatch.FromTableName = inflector.Columnify(r.activeCollectionName)
|
||||
r.multiMatch.FromTableAlias = "__mm_" + r.activeTableAlias
|
||||
r.multiMatchActiveTableAlias = r.multiMatch.FromTableAlias
|
||||
r.withMultiMatch = false
|
||||
}
|
||||
|
||||
@@ -184,9 +185,9 @@ func (r *runner) processCollectionField() (*search.ResolverResult, error) {
|
||||
|
||||
// join the collection to the multi-match subquery
|
||||
r.multiMatchActiveTableAlias = "__mm_" + r.activeTableAlias
|
||||
r.multiMatch.joins = append(r.multiMatch.joins, &join{
|
||||
tableName: inflector.Columnify(collection.Name),
|
||||
tableAlias: r.multiMatchActiveTableAlias,
|
||||
r.multiMatch.Joins = append(r.multiMatch.Joins, &search.Join{
|
||||
TableName: inflector.Columnify(collection.Name),
|
||||
TableAlias: r.multiMatchActiveTableAlias,
|
||||
})
|
||||
|
||||
// leave only the collection fields
|
||||
@@ -229,12 +230,12 @@ func (r *runner) processRequestAuthField() (*search.ResolverResult, error) {
|
||||
|
||||
// join the auth collection to the multi-match subquery
|
||||
r.multiMatchActiveTableAlias = "__mm_" + r.activeTableAlias
|
||||
r.multiMatch.joins = append(
|
||||
r.multiMatch.joins,
|
||||
&join{
|
||||
tableName: inflector.Columnify(r.activeCollectionName),
|
||||
tableAlias: r.multiMatchActiveTableAlias,
|
||||
on: dbx.HashExp{
|
||||
r.multiMatch.Joins = append(
|
||||
r.multiMatch.Joins,
|
||||
&search.Join{
|
||||
TableName: inflector.Columnify(r.activeCollectionName),
|
||||
TableAlias: r.multiMatchActiveTableAlias,
|
||||
On: dbx.HashExp{
|
||||
(r.multiMatchActiveTableAlias + ".id"): r.resolver.requestInfo.Auth.Id,
|
||||
},
|
||||
},
|
||||
@@ -271,10 +272,37 @@ func toSlice(value any) []any {
|
||||
return result
|
||||
}
|
||||
|
||||
func (r *runner) processRequestInfoLowerModifier(bodyField Field) (*search.ResolverResult, error) {
|
||||
func (r *runner) processRequestBodyChangedModifier(bodyField Field) (*search.ResolverResult, error) {
|
||||
name := bodyField.GetName()
|
||||
|
||||
alias := search.FilterData(fmt.Sprintf("@request.body.%s:isset = true && @request.body.%s != %s", name, name, name))
|
||||
|
||||
aliasExpr, err := alias.BuildExpr(r.resolver)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
placeholder := "@changed@" + name + security.PseudorandomString(8)
|
||||
|
||||
result := &search.ResolverResult{
|
||||
Identifier: placeholder,
|
||||
NullFallback: search.NullFallbackDisabled,
|
||||
AfterBuild: func(expr dbx.Expression) dbx.Expression {
|
||||
return &replaceWithExpression{
|
||||
placeholder: placeholder,
|
||||
old: expr,
|
||||
new: aliasExpr,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *runner) processRequestBodyLowerModifier(bodyField Field) (*search.ResolverResult, error) {
|
||||
rawValue := cast.ToString(r.resolver.requestInfo.Body[bodyField.GetName()])
|
||||
|
||||
placeholder := "infoLower" + bodyField.GetName() + security.PseudorandomString(6)
|
||||
placeholder := "infoLower" + bodyField.GetName() + security.PseudorandomString(8)
|
||||
|
||||
result := &search.ResolverResult{
|
||||
Identifier: "LOWER({:" + placeholder + "})",
|
||||
@@ -284,7 +312,7 @@ func (r *runner) processRequestInfoLowerModifier(bodyField Field) (*search.Resol
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *runner) processRequestInfoLengthModifier(bodyField Field) (*search.ResolverResult, error) {
|
||||
func (r *runner) processRequestBodyLengthModifier(bodyField Field) (*search.ResolverResult, error) {
|
||||
if _, ok := bodyField.(MultiValuer); !ok {
|
||||
return nil, fmt.Errorf("field %q doesn't support multivalue operations", bodyField.GetName())
|
||||
}
|
||||
@@ -298,7 +326,7 @@ func (r *runner) processRequestInfoLengthModifier(bodyField Field) (*search.Reso
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *runner) processRequestInfoEachModifier(bodyField Field) (*search.ResolverResult, error) {
|
||||
func (r *runner) processRequestBodyEachModifier(bodyField Field) (*search.ResolverResult, error) {
|
||||
multiValuer, ok := bodyField.(MultiValuer)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("field %q doesn't support multivalue operations", bodyField.GetName())
|
||||
@@ -310,7 +338,7 @@ func (r *runner) processRequestInfoEachModifier(bodyField Field) (*search.Resolv
|
||||
return nil, fmt.Errorf("cannot serialize the data for field %q", r.activeProps[2])
|
||||
}
|
||||
|
||||
placeholder := "dataEach" + security.PseudorandomString(6)
|
||||
placeholder := "dataEach" + security.PseudorandomString(8)
|
||||
cleanFieldName := inflector.Columnify(bodyField.GetName())
|
||||
jeTable := fmt.Sprintf("json_each({:%s})", placeholder)
|
||||
jeAlias := "__dataEach_je_" + cleanFieldName + r.resolver.joinAliasSuffix
|
||||
@@ -334,12 +362,12 @@ func (r *runner) processRequestInfoEachModifier(bodyField Field) (*search.Resolv
|
||||
jeTable2 := fmt.Sprintf("json_each({:%s})", placeholder2)
|
||||
jeAlias2 := "__mm_" + jeAlias
|
||||
|
||||
r.multiMatch.joins = append(r.multiMatch.joins, &join{
|
||||
tableName: jeTable2,
|
||||
tableAlias: jeAlias2,
|
||||
r.multiMatch.Joins = append(r.multiMatch.Joins, &search.Join{
|
||||
TableName: jeTable2,
|
||||
TableAlias: jeAlias2,
|
||||
})
|
||||
r.multiMatch.params[placeholder2] = bodyItemsRaw
|
||||
r.multiMatch.valueIdentifier = fmt.Sprintf("[[%s.value]]", jeAlias2)
|
||||
r.multiMatch.Params[placeholder2] = bodyItemsRaw
|
||||
r.multiMatch.ValueIdentifier = fmt.Sprintf("[[%s.value]]", jeAlias2)
|
||||
|
||||
result.MultiMatchSubQuery = r.multiMatch
|
||||
}
|
||||
@@ -347,7 +375,7 @@ func (r *runner) processRequestInfoEachModifier(bodyField Field) (*search.Resolv
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *runner) processRequestInfoRelationField(bodyField Field) (*search.ResolverResult, error) {
|
||||
func (r *runner) processRequestBodyRelationField(bodyField Field) (*search.ResolverResult, error) {
|
||||
relField, ok := bodyField.(*RelationField)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("failed to initialize data relation field %q", bodyField.GetName())
|
||||
@@ -388,12 +416,12 @@ func (r *runner) processRequestInfoRelationField(bodyField Field) (*search.Resol
|
||||
|
||||
// join the data rel collection to the multi-match subquery
|
||||
r.multiMatchActiveTableAlias = "__mm_" + r.activeTableAlias
|
||||
r.multiMatch.joins = append(
|
||||
r.multiMatch.joins,
|
||||
&join{
|
||||
tableName: r.activeCollectionName,
|
||||
tableAlias: r.multiMatchActiveTableAlias,
|
||||
on: dbx.In(
|
||||
r.multiMatch.Joins = append(
|
||||
r.multiMatch.Joins,
|
||||
&search.Join{
|
||||
TableName: r.activeCollectionName,
|
||||
TableAlias: r.multiMatchActiveTableAlias,
|
||||
On: dbx.In(
|
||||
fmt.Sprintf("[[%s.id]]", r.multiMatchActiveTableAlias),
|
||||
list.ToInterfaceSlice(dataRelIds)...,
|
||||
),
|
||||
@@ -449,12 +477,12 @@ func (r *runner) processActiveProps() (*search.ResolverResult, error) {
|
||||
jsonPathStr := jsonPath.String()
|
||||
|
||||
result := &search.ResolverResult{
|
||||
NoCoalesce: true,
|
||||
Identifier: dbutils.JSONExtract(r.activeTableAlias+"."+inflector.Columnify(prop), jsonPathStr),
|
||||
NullFallback: search.NullFallbackDisabled,
|
||||
Identifier: dbutils.JSONExtract(r.activeTableAlias+"."+inflector.Columnify(prop), jsonPathStr),
|
||||
}
|
||||
|
||||
if r.withMultiMatch {
|
||||
r.multiMatch.valueIdentifier = dbutils.JSONExtract(r.multiMatchActiveTableAlias+"."+inflector.Columnify(prop), jsonPathStr)
|
||||
r.multiMatch.ValueIdentifier = dbutils.JSONExtract(r.multiMatchActiveTableAlias+"."+inflector.Columnify(prop), jsonPathStr)
|
||||
result.MultiMatchSubQuery = r.multiMatch
|
||||
}
|
||||
|
||||
@@ -519,15 +547,11 @@ func (r *runner) processActiveProps() (*search.ResolverResult, error) {
|
||||
// ---
|
||||
cleanProp := inflector.Columnify(prop)
|
||||
cleanBackFieldName := inflector.Columnify(backRelField.Name)
|
||||
|
||||
newTableAlias := r.activeTableAlias + "_" + cleanProp + r.resolver.joinAliasSuffix
|
||||
newCollectionName := inflector.Columnify(backCollection.Name)
|
||||
|
||||
isBackRelMultiple := backRelField.IsMultiple()
|
||||
if !isBackRelMultiple {
|
||||
// additionally check if the rel field has a single column unique index
|
||||
_, hasUniqueIndex := dbutils.FindSingleColumnUniqueIndex(backCollection.Indexes, backRelField.Name)
|
||||
isBackRelMultiple = !hasUniqueIndex
|
||||
}
|
||||
|
||||
if !isBackRelMultiple {
|
||||
err := r.resolver.registerJoin(
|
||||
@@ -564,27 +588,32 @@ func (r *runner) processActiveProps() (*search.ResolverResult, error) {
|
||||
// ---
|
||||
if isBackRelMultiple {
|
||||
r.withMultiMatch = true // enable multimatch if not already
|
||||
} else if !r.withMultiMatch {
|
||||
// additionally check if the rel field has a single column unique index;
|
||||
// if not - apply a multi-match check
|
||||
_, hasUniqueIndex := dbutils.FindSingleColumnUniqueIndex(backCollection.Indexes, backRelField.Name)
|
||||
r.withMultiMatch = !hasUniqueIndex
|
||||
}
|
||||
|
||||
newTableAlias2 := r.multiMatchActiveTableAlias + "_" + cleanProp + r.resolver.joinAliasSuffix
|
||||
|
||||
if !isBackRelMultiple {
|
||||
r.multiMatch.joins = append(
|
||||
r.multiMatch.joins,
|
||||
&join{
|
||||
tableName: newCollectionName,
|
||||
tableAlias: newTableAlias2,
|
||||
on: dbx.NewExp(fmt.Sprintf("[[%s.%s]] = [[%s.id]]", newTableAlias2, cleanBackFieldName, r.multiMatchActiveTableAlias)),
|
||||
r.multiMatch.Joins = append(
|
||||
r.multiMatch.Joins,
|
||||
&search.Join{
|
||||
TableName: newCollectionName,
|
||||
TableAlias: newTableAlias2,
|
||||
On: dbx.NewExp(fmt.Sprintf("[[%s.%s]] = [[%s.id]]", newTableAlias2, cleanBackFieldName, r.multiMatchActiveTableAlias)),
|
||||
},
|
||||
)
|
||||
} else {
|
||||
jeAlias2 := "__je_" + newTableAlias2
|
||||
r.multiMatch.joins = append(
|
||||
r.multiMatch.joins,
|
||||
&join{
|
||||
tableName: newCollectionName,
|
||||
tableAlias: newTableAlias2,
|
||||
on: dbx.NewExp(fmt.Sprintf(
|
||||
r.multiMatch.Joins = append(
|
||||
r.multiMatch.Joins,
|
||||
&search.Join{
|
||||
TableName: newCollectionName,
|
||||
TableAlias: newTableAlias2,
|
||||
On: dbx.NewExp(fmt.Sprintf(
|
||||
"[[%s.id]] IN (SELECT [[%s.value]] FROM %s {{%s}})",
|
||||
r.multiMatchActiveTableAlias,
|
||||
jeAlias2,
|
||||
@@ -673,26 +702,26 @@ func (r *runner) processActiveProps() (*search.ResolverResult, error) {
|
||||
prefixedFieldName2 := r.multiMatchActiveTableAlias + "." + cleanFieldName
|
||||
|
||||
if !relField.IsMultiple() {
|
||||
r.multiMatch.joins = append(
|
||||
r.multiMatch.joins,
|
||||
&join{
|
||||
tableName: inflector.Columnify(newCollectionName),
|
||||
tableAlias: newTableAlias2,
|
||||
on: dbx.NewExp(fmt.Sprintf("[[%s.id]] = [[%s]]", newTableAlias2, prefixedFieldName2)),
|
||||
r.multiMatch.Joins = append(
|
||||
r.multiMatch.Joins,
|
||||
&search.Join{
|
||||
TableName: inflector.Columnify(newCollectionName),
|
||||
TableAlias: newTableAlias2,
|
||||
On: dbx.NewExp(fmt.Sprintf("[[%s.id]] = [[%s]]", newTableAlias2, prefixedFieldName2)),
|
||||
},
|
||||
)
|
||||
} else {
|
||||
jeAlias2 := r.multiMatchActiveTableAlias + "_" + cleanFieldName + "_je"
|
||||
r.multiMatch.joins = append(
|
||||
r.multiMatch.joins,
|
||||
&join{
|
||||
tableName: dbutils.JSONEach(prefixedFieldName2),
|
||||
tableAlias: jeAlias2,
|
||||
r.multiMatch.Joins = append(
|
||||
r.multiMatch.Joins,
|
||||
&search.Join{
|
||||
TableName: dbutils.JSONEach(prefixedFieldName2),
|
||||
TableAlias: jeAlias2,
|
||||
},
|
||||
&join{
|
||||
tableName: inflector.Columnify(newCollectionName),
|
||||
tableAlias: newTableAlias2,
|
||||
on: dbx.NewExp(fmt.Sprintf("[[%s.id]] = [[%s.value]]", newTableAlias2, jeAlias2)),
|
||||
&search.Join{
|
||||
TableName: inflector.Columnify(newCollectionName),
|
||||
TableAlias: newTableAlias2,
|
||||
On: dbx.NewExp(fmt.Sprintf("[[%s.id]] = [[%s.value]]", newTableAlias2, jeAlias2)),
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -737,7 +766,7 @@ func (r *runner) finalizeActivePropsProcessing(collection *Collection, prop stri
|
||||
|
||||
if r.withMultiMatch {
|
||||
jePair2 := r.multiMatchActiveTableAlias + "." + cleanFieldName
|
||||
r.multiMatch.valueIdentifier = dbutils.JSONArrayLength(jePair2)
|
||||
r.multiMatch.ValueIdentifier = dbutils.JSONArrayLength(jePair2)
|
||||
result.MultiMatchSubQuery = r.multiMatch
|
||||
}
|
||||
|
||||
@@ -767,11 +796,11 @@ func (r *runner) finalizeActivePropsProcessing(collection *Collection, prop stri
|
||||
jePair2 := r.multiMatchActiveTableAlias + "." + cleanFieldName
|
||||
jeAlias2 := "__je_" + r.multiMatchActiveTableAlias + "_" + cleanFieldName + r.resolver.joinAliasSuffix
|
||||
|
||||
r.multiMatch.joins = append(r.multiMatch.joins, &join{
|
||||
tableName: dbutils.JSONEach(jePair2),
|
||||
tableAlias: jeAlias2,
|
||||
r.multiMatch.Joins = append(r.multiMatch.Joins, &search.Join{
|
||||
TableName: dbutils.JSONEach(jePair2),
|
||||
TableAlias: jeAlias2,
|
||||
})
|
||||
r.multiMatch.valueIdentifier = fmt.Sprintf("[[%s.value]]", jeAlias2)
|
||||
r.multiMatch.ValueIdentifier = fmt.Sprintf("[[%s.value]]", jeAlias2)
|
||||
|
||||
result.MultiMatchSubQuery = r.multiMatch
|
||||
}
|
||||
@@ -786,7 +815,7 @@ func (r *runner) finalizeActivePropsProcessing(collection *Collection, prop stri
|
||||
}
|
||||
|
||||
if r.withMultiMatch {
|
||||
r.multiMatch.valueIdentifier = "[[" + r.multiMatchActiveTableAlias + "." + cleanFieldName + "]]"
|
||||
r.multiMatch.ValueIdentifier = "[[" + r.multiMatchActiveTableAlias + "." + cleanFieldName + "]]"
|
||||
result.MultiMatchSubQuery = r.multiMatch
|
||||
}
|
||||
|
||||
@@ -805,10 +834,10 @@ func (r *runner) finalizeActivePropsProcessing(collection *Collection, prop stri
|
||||
// stored as json work correctly when compared to their SQL equivalent
|
||||
// (https://github.com/pocketbase/pocketbase/issues/4068)
|
||||
if field.Type() == FieldTypeJSON {
|
||||
result.NoCoalesce = true
|
||||
result.NullFallback = search.NullFallbackDisabled
|
||||
result.Identifier = dbutils.JSONExtract(r.activeTableAlias+"."+cleanFieldName, "")
|
||||
if r.withMultiMatch {
|
||||
r.multiMatch.valueIdentifier = dbutils.JSONExtract(r.multiMatchActiveTableAlias+"."+cleanFieldName, "")
|
||||
r.multiMatch.ValueIdentifier = dbutils.JSONExtract(r.multiMatchActiveTableAlias+"."+cleanFieldName, "")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -816,7 +845,7 @@ func (r *runner) finalizeActivePropsProcessing(collection *Collection, prop stri
|
||||
if modifier == lowerModifier {
|
||||
result.Identifier = "LOWER(" + result.Identifier + ")"
|
||||
if r.withMultiMatch {
|
||||
r.multiMatch.valueIdentifier = "LOWER(" + r.multiMatch.valueIdentifier + ")"
|
||||
r.multiMatch.ValueIdentifier = "LOWER(" + r.multiMatch.ValueIdentifier + ")"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/go-ozzo/ozzo-validation/v4/is"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
"github.com/pocketbase/pocketbase/mails"
|
||||
"github.com/pocketbase/pocketbase/tools/types"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -109,7 +110,8 @@ func (form *TestEmailSend) Submit() error {
|
||||
case TestTemplateOTP:
|
||||
return mails.SendRecordOTP(form.app, record, "_PB_TEST_OTP_ID_", "123456")
|
||||
case TestTemplateAuthAlert:
|
||||
return mails.SendRecordAuthAlert(form.app, record)
|
||||
testEvent := types.NowDateTime().String() + " - TEST_IP TEST_USER_AGENT"
|
||||
return mails.SendRecordAuthAlert(form.app, record, testEvent)
|
||||
default:
|
||||
return errors.New("unknown template " + form.Template)
|
||||
}
|
||||
|
||||
@@ -5,24 +5,24 @@ go 1.24.0
|
||||
require (
|
||||
github.com/disintegration/imaging v1.6.2
|
||||
github.com/domodwyer/mailyak/v3 v3.6.2
|
||||
github.com/dop251/goja v0.0.0-20251008123653-cf18d89f3cf6
|
||||
github.com/dop251/goja_nodejs v0.0.0-20250409162600-f7acab6894b0
|
||||
github.com/dop251/goja v0.0.0-20251201205617-2bb4c724c0f9
|
||||
github.com/dop251/goja_nodejs v0.0.0-20251015164255-5e94316bedaf
|
||||
github.com/fatih/color v1.18.0
|
||||
github.com/fsnotify/fsnotify v1.7.0
|
||||
github.com/gabriel-vasile/mimetype v1.4.10
|
||||
github.com/gabriel-vasile/mimetype v1.4.12
|
||||
github.com/ganigeorgiev/fexpr v0.5.0
|
||||
github.com/go-ozzo/ozzo-validation/v4 v4.3.0
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0
|
||||
github.com/pocketbase/dbx v1.11.0
|
||||
github.com/pocketbase/tygoja v0.0.0-20250812183945-97ffe055281f
|
||||
github.com/spf13/cast v1.10.0
|
||||
github.com/spf13/cobra v1.10.1
|
||||
golang.org/x/crypto v0.43.0
|
||||
golang.org/x/image v0.32.0
|
||||
golang.org/x/net v0.46.0
|
||||
golang.org/x/oauth2 v0.32.0
|
||||
golang.org/x/sync v0.17.0
|
||||
modernc.org/sqlite v1.40.0
|
||||
github.com/spf13/cobra v1.10.2
|
||||
golang.org/x/crypto v0.47.0
|
||||
golang.org/x/image v0.35.0
|
||||
golang.org/x/net v0.49.0
|
||||
golang.org/x/oauth2 v0.34.0
|
||||
golang.org/x/sync v0.19.0
|
||||
modernc.org/sqlite v1.44.1
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -39,12 +39,12 @@ require (
|
||||
github.com/ncruces/go-strftime v1.0.0 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
golang.org/x/exp v0.0.0-20251017212417-90e834f514db // indirect
|
||||
golang.org/x/mod v0.29.0 // indirect
|
||||
golang.org/x/sys v0.37.0 // indirect
|
||||
golang.org/x/text v0.30.0 // indirect
|
||||
golang.org/x/tools v0.38.0 // indirect
|
||||
modernc.org/libc v1.66.10 // indirect
|
||||
golang.org/x/exp v0.0.0-20260112195511-716be5621a96 // indirect
|
||||
golang.org/x/mod v0.32.0 // indirect
|
||||
golang.org/x/sys v0.40.0 // indirect
|
||||
golang.org/x/text v0.33.0 // indirect
|
||||
golang.org/x/tools v0.41.0 // indirect
|
||||
modernc.org/libc v1.67.6 // indirect
|
||||
modernc.org/mathutil v1.7.1 // indirect
|
||||
modernc.org/memory v1.11.0 // indirect
|
||||
)
|
||||
|
||||
@@ -14,10 +14,10 @@ github.com/domodwyer/mailyak/v3 v3.6.2 h1:x3tGMsyFhTCaxp6ycgR0FE/bu5QiNp+hetUuCO
|
||||
github.com/domodwyer/mailyak/v3 v3.6.2/go.mod h1:lOm/u9CyCVWHeaAmHIdF4RiKVxKUT/H5XX10lIKAL6c=
|
||||
github.com/dop251/base64dec v0.0.0-20231022112746-c6c9f9a96217 h1:16iT9CBDOniJwFGPI41MbUDfEk74hFaKTqudrX8kenY=
|
||||
github.com/dop251/base64dec v0.0.0-20231022112746-c6c9f9a96217/go.mod h1:eIb+f24U+eWQCIsj9D/ah+MD9UP+wdxuqzsdLD+mhGM=
|
||||
github.com/dop251/goja v0.0.0-20251008123653-cf18d89f3cf6 h1:6dE1TmjqkY6tehR4A67gDNhvDtuZ54ocu7ab4K9o540=
|
||||
github.com/dop251/goja v0.0.0-20251008123653-cf18d89f3cf6/go.mod h1:MxLav0peU43GgvwVgNbLAj1s/bSGboKkhuULvq/7hx4=
|
||||
github.com/dop251/goja_nodejs v0.0.0-20250409162600-f7acab6894b0 h1:fuHXpEVTTk7TilRdfGRLHpiTD6tnT0ihEowCfWjlFvw=
|
||||
github.com/dop251/goja_nodejs v0.0.0-20250409162600-f7acab6894b0/go.mod h1:Tb7Xxye4LX7cT3i8YLvmPMGCV92IOi4CDZvm/V8ylc0=
|
||||
github.com/dop251/goja v0.0.0-20251201205617-2bb4c724c0f9 h1:3uSSOd6mVlwcX3k5OYOpiDqFgRmaE2dBfLvVIFWWHrw=
|
||||
github.com/dop251/goja v0.0.0-20251201205617-2bb4c724c0f9/go.mod h1:MxLav0peU43GgvwVgNbLAj1s/bSGboKkhuULvq/7hx4=
|
||||
github.com/dop251/goja_nodejs v0.0.0-20251015164255-5e94316bedaf h1:gbmvliZnCut4NjaPSNOQlfqBoZ9C5Dpf72mHMMYhgVE=
|
||||
github.com/dop251/goja_nodejs v0.0.0-20251015164255-5e94316bedaf/go.mod h1:Tb7Xxye4LX7cT3i8YLvmPMGCV92IOi4CDZvm/V8ylc0=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||
@@ -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.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||
github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw=
|
||||
github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||
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=
|
||||
@@ -45,6 +45,8 @@ github.com/google/pprof v0.0.0-20251007162407-5df77e3f7d1d h1:KJIErDwbSHjnp/SGzE
|
||||
github.com/google/pprof v0.0.0-20251007162407-5df77e3f7d1d/go.mod h1:I6V7YzU0XDpsHqbsyrghnFZLO1gwK6NPTNvmetQIk9U=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
@@ -70,61 +72,63 @@ github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/f
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
|
||||
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
|
||||
github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
|
||||
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
|
||||
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
|
||||
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
|
||||
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
|
||||
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
|
||||
golang.org/x/exp v0.0.0-20251017212417-90e834f514db h1:by6IehL4BH5k3e3SJmcoNbOobMey2SLpAF79iPOEBvw=
|
||||
golang.org/x/exp v0.0.0-20251017212417-90e834f514db/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
|
||||
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
||||
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
||||
golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU=
|
||||
golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.32.0 h1:6lZQWq75h7L5IWNk0r+SCpUJ6tUVd3v4ZHnbRKLkUDQ=
|
||||
golang.org/x/image v0.32.0/go.mod h1:/R37rrQmKXtO6tYXAjtDLwQgFLHmhW+V6ayXlxzP2Pc=
|
||||
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
|
||||
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
|
||||
golang.org/x/image v0.35.0 h1:LKjiHdgMtO8z7Fh18nGY6KDcoEtVfsgLDPeLyguqb7I=
|
||||
golang.org/x/image v0.35.0/go.mod h1:MwPLTVgvxSASsxdLzKrl8BRFuyqMyGhLwmC+TO1Sybk=
|
||||
golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c=
|
||||
golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
|
||||
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
|
||||
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
|
||||
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
||||
golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
|
||||
golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
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.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
|
||||
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
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.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
|
||||
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
|
||||
golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc=
|
||||
golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg=
|
||||
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=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
modernc.org/cc/v4 v4.26.5 h1:xM3bX7Mve6G8K8b+T11ReenJOT+BmVqQj0FY5T4+5Y4=
|
||||
modernc.org/cc/v4 v4.26.5/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
||||
modernc.org/ccgo/v4 v4.28.1 h1:wPKYn5EC/mYTqBO373jKjvX2n+3+aK7+sICCv4Fjy1A=
|
||||
modernc.org/ccgo/v4 v4.28.1/go.mod h1:uD+4RnfrVgE6ec9NGguUNdhqzNIeeomeXf6CL0GTE5Q=
|
||||
modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis=
|
||||
modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
||||
modernc.org/ccgo/v4 v4.30.1 h1:4r4U1J6Fhj98NKfSjnPUN7Ze2c6MnAdL0hWw6+LrJpc=
|
||||
modernc.org/ccgo/v4 v4.30.1/go.mod h1:bIOeI1JL54Utlxn+LwrFyjCx2n2RDiYEaJVSrgdrRfM=
|
||||
modernc.org/fileutil v1.3.40 h1:ZGMswMNc9JOCrcrakF1HrvmergNLAmxOPjizirpfqBA=
|
||||
modernc.org/fileutil v1.3.40/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
|
||||
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
|
||||
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
|
||||
modernc.org/gc/v3 v3.1.1 h1:k8T3gkXWY9sEiytKhcgyiZ2L0DTyCQ/nvX+LoCljoRE=
|
||||
modernc.org/gc/v3 v3.1.1/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY=
|
||||
modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
|
||||
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
|
||||
modernc.org/libc v1.66.10 h1:yZkb3YeLx4oynyR+iUsXsybsX4Ubx7MQlSYEw4yj59A=
|
||||
modernc.org/libc v1.66.10/go.mod h1:8vGSEwvoUoltr4dlywvHqjtAqHBaw0j1jI7iFBTAr2I=
|
||||
modernc.org/libc v1.67.6 h1:eVOQvpModVLKOdT+LvBPjdQqfrZq+pC39BygcT+E7OI=
|
||||
modernc.org/libc v1.67.6/go.mod h1:JAhxUVlolfYDErnwiqaLvUqc8nfb2r6S6slAgZOnaiE=
|
||||
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
|
||||
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
|
||||
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
|
||||
@@ -133,8 +137,8 @@ modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
|
||||
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
|
||||
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
|
||||
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
|
||||
modernc.org/sqlite v1.40.0 h1:bNWEDlYhNPAUdUdBzjAvn8icAs/2gaKlj4vM+tQ6KdQ=
|
||||
modernc.org/sqlite v1.40.0/go.mod h1:9fjQZ0mB1LLP0GYrp39oOJXx/I2sxEnZtzCmEQIKvGE=
|
||||
modernc.org/sqlite v1.44.1 h1:qybx/rNpfQipX/t47OxbHmkkJuv2JWifCMH8SVUiDas=
|
||||
modernc.org/sqlite v1.44.1/go.mod h1:CzbrU2lSB1DKUusvwGz7rqEKIq+NUd8GWuBBZDs9/nA=
|
||||
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
|
||||
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
|
||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||
|
||||
+9
-2
@@ -12,10 +12,14 @@ import (
|
||||
)
|
||||
|
||||
// SendRecordAuthAlert sends a new device login alert to the specified auth record.
|
||||
func SendRecordAuthAlert(app core.App, authRecord *core.Record) error {
|
||||
func SendRecordAuthAlert(app core.App, authRecord *core.Record, info string) error {
|
||||
mailClient := app.NewMailClient()
|
||||
|
||||
subject, body, err := resolveEmailTemplate(app, authRecord, authRecord.Collection().AuthAlert.EmailTemplate, nil)
|
||||
info = html.EscapeString(info)
|
||||
|
||||
subject, body, err := resolveEmailTemplate(app, authRecord, authRecord.Collection().AuthAlert.EmailTemplate, map[string]any{
|
||||
core.EmailPlaceholderAlertInfo: info,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -35,6 +39,9 @@ func SendRecordAuthAlert(app core.App, authRecord *core.Record) error {
|
||||
event.Mailer = mailClient
|
||||
event.Message = message
|
||||
event.Record = authRecord
|
||||
event.Meta = map[string]any{
|
||||
"info": info,
|
||||
}
|
||||
|
||||
return app.OnMailerRecordAuthAlertSend().Trigger(event, func(e *core.MailerRecordEvent) error {
|
||||
return e.Mailer.Send(e.Message)
|
||||
|
||||
@@ -15,12 +15,14 @@ func TestSendRecordAuthAlert(t *testing.T) {
|
||||
testApp, _ := tests.NewTestApp()
|
||||
defer testApp.Cleanup()
|
||||
|
||||
info := "<p>test_info</p>"
|
||||
|
||||
user, _ := testApp.FindFirstRecordByData("users", "email", "test@example.com")
|
||||
|
||||
// to test that it is escaped
|
||||
user.Set("name", "<p>"+user.GetString("name")+"</p>")
|
||||
|
||||
err := mails.SendRecordAuthAlert(testApp, user)
|
||||
err := mails.SendRecordAuthAlert(testApp, user, info)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -34,6 +36,7 @@ func TestSendRecordAuthAlert(t *testing.T) {
|
||||
"login to your " + testApp.Settings().Meta.AppName + " account from a new location",
|
||||
"If this was you",
|
||||
"If this wasn't you",
|
||||
html.EscapeString(info),
|
||||
}
|
||||
for _, part := range expectedParts {
|
||||
if !strings.Contains(testApp.TestMailer.LastMessage().HTML, part) {
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
)
|
||||
|
||||
const oldAuthAlertTemplate = `<p>Hello,</p>
|
||||
<p>We noticed a login to your {APP_NAME} account from a new location.</p>
|
||||
<p>If this was you, you may disregard this email.</p>
|
||||
<p><strong>If this wasn't you, you should immediately change your {APP_NAME} account password to revoke access from all other locations.</strong></p>
|
||||
<p>
|
||||
Thanks,<br/>
|
||||
{APP_NAME} team
|
||||
</p>`
|
||||
|
||||
func init() {
|
||||
core.SystemMigrations.Register(func(txApp core.App) error {
|
||||
collections, err := txApp.FindAllCollections(core.CollectionTypeAuth)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newTemplate := core.NewAuthCollection("up").AuthAlert.EmailTemplate.Body
|
||||
|
||||
for _, c := range collections {
|
||||
if c.AuthAlert.EmailTemplate.Body != oldAuthAlertTemplate {
|
||||
continue
|
||||
}
|
||||
|
||||
c.AuthAlert.EmailTemplate.Body = newTemplate
|
||||
|
||||
err = txApp.Save(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}, func(txApp core.App) error {
|
||||
collections, err := txApp.FindAllCollections(core.CollectionTypeAuth)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newTemplate := core.NewAuthCollection("down").AuthAlert.EmailTemplate.Body
|
||||
|
||||
for _, c := range collections {
|
||||
if c.AuthAlert.EmailTemplate.Body != newTemplate {
|
||||
continue
|
||||
}
|
||||
|
||||
c.AuthAlert.EmailTemplate.Body = oldAuthAlertTemplate
|
||||
|
||||
err = txApp.Save(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
expectedDriverVersion = "v1.40.0"
|
||||
expectedLibcVersion = "v1.66.10"
|
||||
expectedDriverVersion = "v1.44.1"
|
||||
expectedLibcVersion = "v1.67.6"
|
||||
|
||||
// ModerncDepsCheckHookId is the id of the hook that performs the modernc.org/* deps checks.
|
||||
// It could be used for removing/unbinding the hook if you don't want the checks.
|
||||
|
||||
+46
-6
@@ -431,6 +431,32 @@ func baseBinds(vm *goja.Runtime) {
|
||||
return instanceValue
|
||||
})
|
||||
|
||||
// nullable helpers usually used as DynamicModel shape values
|
||||
vm.Set("nullString", func() *string {
|
||||
var v string
|
||||
return &v
|
||||
})
|
||||
vm.Set("nullFloat", func() *float64 {
|
||||
var v float64
|
||||
return &v
|
||||
})
|
||||
vm.Set("nullInt", func() *int64 {
|
||||
var v int64
|
||||
return &v
|
||||
})
|
||||
vm.Set("nullBool", func() *bool {
|
||||
var v bool
|
||||
return &v
|
||||
})
|
||||
vm.Set("nullArray", func() *types.JSONArray[any] {
|
||||
var v types.JSONArray[any]
|
||||
return &v
|
||||
})
|
||||
vm.Set("nullObject", func() *types.JSONMap[any] {
|
||||
var v types.JSONMap[any]
|
||||
return &v
|
||||
})
|
||||
|
||||
vm.Set("Record", func(call goja.ConstructorCall) *goja.Object {
|
||||
var instance *core.Record
|
||||
|
||||
@@ -663,6 +689,7 @@ func mailsBinds(vm *goja.Runtime) {
|
||||
obj.Set("sendRecordVerification", mails.SendRecordVerification)
|
||||
obj.Set("sendRecordChangeEmail", mails.SendRecordChangeEmail)
|
||||
obj.Set("sendRecordOTP", mails.SendRecordOTP)
|
||||
obj.Set("sendRecordAuthAlert", mails.SendRecordAuthAlert)
|
||||
}
|
||||
|
||||
func securityBinds(vm *goja.Runtime) {
|
||||
@@ -1099,12 +1126,19 @@ var cachedDynamicModelStructs = store.New[string, reflect.Type](nil)
|
||||
// on the specified "shape".
|
||||
//
|
||||
// The "shape" values are used as defaults and could be of type:
|
||||
// - int (ex. 0)
|
||||
// - float (ex. -0)
|
||||
// - string (ex. "")
|
||||
// - bool (ex. false)
|
||||
// - slice (ex. [])
|
||||
// - map (ex. map[string]any{})
|
||||
//
|
||||
// - int64 (ex.: 0)
|
||||
// - *int64 (ex.: nullInt())
|
||||
// - float64 (ex.: -0)
|
||||
// - *float64 (ex.: nullFloat())
|
||||
// - string (ex.: "")
|
||||
// - *string (ex.: nullString())
|
||||
// - bool (ex.: false)
|
||||
// - *bool (ex.: nullBool())
|
||||
// - slice/arr (ex.: [])
|
||||
// - *slice/arr (ex.: nullArray())
|
||||
// - map (ex.: {})
|
||||
// - *map (ex.: nullObject())
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
@@ -1140,6 +1174,9 @@ func newDynamicModel(shape map[string]any) any {
|
||||
newV.Scan(raw)
|
||||
v = newV
|
||||
vt = reflect.TypeOf(newV)
|
||||
case reflect.Pointer:
|
||||
// for pointers always fallback to nil as their default value
|
||||
v = nil
|
||||
}
|
||||
|
||||
hash.WriteString(k)
|
||||
@@ -1168,6 +1205,9 @@ func newDynamicModel(shape map[string]any) any {
|
||||
|
||||
// load default values into the new model
|
||||
for i, item := range info {
|
||||
if item.value == nil {
|
||||
continue
|
||||
}
|
||||
elem.Field(i).Set(reflect.ValueOf(item.value))
|
||||
}
|
||||
|
||||
|
||||
+83
-33
@@ -46,7 +46,7 @@ func TestBaseBindsCount(t *testing.T) {
|
||||
vm := goja.New()
|
||||
baseBinds(vm)
|
||||
|
||||
testBindsCount(vm, "this", 35, t)
|
||||
testBindsCount(vm, "this", 41, t)
|
||||
}
|
||||
|
||||
func TestBaseBindsSleep(t *testing.T) {
|
||||
@@ -795,7 +795,7 @@ func TestMailsBindsCount(t *testing.T) {
|
||||
vm := goja.New()
|
||||
mailsBinds(vm)
|
||||
|
||||
testBindsCount(vm, "$mails", 4, t)
|
||||
testBindsCount(vm, "$mails", 5, t)
|
||||
}
|
||||
|
||||
func TestMailsBinds(t *testing.T) {
|
||||
@@ -833,6 +833,11 @@ func TestMailsBinds(t *testing.T) {
|
||||
if (!$app.testMailer.lastMessage().html.includes("test_otp_pass")) {
|
||||
throw new Error("Expected record OTP email, got:" + JSON.stringify($app.testMailer.lastMessage()))
|
||||
}
|
||||
|
||||
$mails.sendRecordAuthAlert($app, record, "test_alert_info");
|
||||
if (!$app.testMailer.lastMessage().html.includes("test_alert_info")) {
|
||||
throw new Error("Expected record OTP email, got:" + JSON.stringify($app.testMailer.lastMessage()))
|
||||
}
|
||||
`)
|
||||
if vmErr != nil {
|
||||
t.Fatal(vmErr)
|
||||
@@ -1157,44 +1162,89 @@ func TestLoadingDynamicModel(t *testing.T) {
|
||||
|
||||
_, err := vm.RunString(`
|
||||
let result = new DynamicModel({
|
||||
text: "",
|
||||
bool: false,
|
||||
number: 0,
|
||||
select_many: [],
|
||||
json: [],
|
||||
// custom map-like field
|
||||
obj: {},
|
||||
string: "",
|
||||
nullString: nullString(),
|
||||
nullStringEmpty: nullString(),
|
||||
|
||||
bool: false,
|
||||
nullBool: nullBool(),
|
||||
nullBoolEmpty: nullBool(),
|
||||
|
||||
int: 0,
|
||||
nullInt: nullInt(),
|
||||
nullIntEmpty: nullInt(),
|
||||
|
||||
float: -0,
|
||||
nullFloat: nullFloat(),
|
||||
nullFloatEmpty: nullFloat(),
|
||||
|
||||
array: [],
|
||||
nullArray: nullArray(),
|
||||
nullArrayEmpty: nullArray(),
|
||||
|
||||
object: {},
|
||||
nullObject: nullObject(),
|
||||
nullObjectEmpty: nullObject(),
|
||||
})
|
||||
|
||||
const expectations = {
|
||||
"string": "a",
|
||||
"nullString": "b",
|
||||
"nullStringEmpty": null,
|
||||
|
||||
"bool": false,
|
||||
"nullBool": true,
|
||||
"nullBoolEmpty": null,
|
||||
|
||||
"int": 1,
|
||||
"nullInt": 2,
|
||||
"nullIntEmpty": null,
|
||||
|
||||
"float": 1.1,
|
||||
"nullFloat": 1.2,
|
||||
"nullFloatEmpty": null,
|
||||
|
||||
"array": [1,2],
|
||||
"nullArray": [3,4],
|
||||
"nullArrayEmpty": null,
|
||||
|
||||
"object": {a:1},
|
||||
"nullObject": {a:2},
|
||||
"nullObjectEmpty": null,
|
||||
};
|
||||
|
||||
// constuct dummy SELECT column value literals based on the expectations
|
||||
const selectColumns = [];
|
||||
for (const col in expectations) {
|
||||
const val = expectations[col]
|
||||
|
||||
if (val === null) {
|
||||
selectColumns.push("null as [[" + col + "]]")
|
||||
} else if (typeof val === "string") {
|
||||
selectColumns.push("'" + val + "' as [[" + col + "]]")
|
||||
} else if (typeof val === "object") {
|
||||
selectColumns.push("'" + JSON.stringify(val) + "' as [[" + col + "]]")
|
||||
} else {
|
||||
selectColumns.push(val + " as [[" + col + "]]")
|
||||
}
|
||||
}
|
||||
|
||||
$app.db()
|
||||
.select("text", "bool", "number", "select_many", "json", "('{\"test\": 1}') as obj")
|
||||
.from("demo1")
|
||||
.where($dbx.hashExp({"id": "84nmscqy84lsi1t"}))
|
||||
.limit(1)
|
||||
.newQuery("SELECT " + selectColumns.join(", "))
|
||||
.one(result)
|
||||
|
||||
if (result.text != "test") {
|
||||
throw new Error('Expected text "test", got ' + result.text);
|
||||
}
|
||||
for (const col in expectations) {
|
||||
let expVal = expectations[col];
|
||||
let resVal = result[col];
|
||||
|
||||
if (result.bool != true) {
|
||||
throw new Error('Expected bool true, got ' + result.bool);
|
||||
}
|
||||
if (expVal !== null && typeof expVal === "object") {
|
||||
expVal = JSON.stringify(expVal)
|
||||
resVal = JSON.stringify(resVal)
|
||||
}
|
||||
|
||||
if (result.number != 123456) {
|
||||
throw new Error('Expected number 123456, got ' + result.number);
|
||||
}
|
||||
|
||||
if (result.select_many.length != 2 || result.select_many[0] != "optionB" || result.select_many[1] != "optionC") {
|
||||
throw new Error('Expected select_many ["optionB", "optionC"], got ' + result.select_many);
|
||||
}
|
||||
|
||||
if (result.json.length != 3 || result.json[0] != 1 || result.json[1] != 2 || result.json[2] != 3) {
|
||||
throw new Error('Expected json [1, 2, 3], got ' + result.json);
|
||||
}
|
||||
|
||||
if (result.obj.get("test") != 1) {
|
||||
throw new Error('Expected obj.get("test") 1, got ' + JSON.stringify(result.obj));
|
||||
if (expVal != resVal) {
|
||||
throw new Error("Expected '" + col + "' value " + expVal + ", got " + resVal);
|
||||
}
|
||||
}
|
||||
`)
|
||||
if err != nil {
|
||||
|
||||
+3266
-3172
File diff suppressed because it is too large
Load Diff
@@ -259,27 +259,78 @@ declare function arrayOf<T>(model: T): Array<T>;
|
||||
*
|
||||
* Caveats:
|
||||
* - In order to use 0 as double/float initialization number you have to negate it (` + "`-0`" + `).
|
||||
* - You need to use lowerCamelCase when accessing the model fields (e.g. ` + "`model.roles`" + ` and not ` + "`model.Roles`" + `).
|
||||
* - You need to use lowerCamelCase when accessing the model fields (e.g. ` + "`model.roles`" + ` and not ` + "`model.Roles`" + ` even if in the model shape and in the DB table the column is capitalized).
|
||||
* - Objects are loaded into types.JSONMap, meaning that they need to be accessed with ` + "`get(key)`" + ` (e.g. ` + "`model.meta.get('something')`" + `).
|
||||
* - For describing nullable types you can use the ` + "`null*()`" + ` helpers - ` + "`nullString()`" + `, ` + "`nullInt()`" + `, ` + "`nullFloat()`" + `, ` + "`nullBool()`" + `, ` + "`nullArray()`" + `, ` + "`nullObject()`" + `.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ` + "```" + `js
|
||||
* const model = new DynamicModel({
|
||||
* name: ""
|
||||
* age: 0, // int64
|
||||
* totalSpent: -0, // float64
|
||||
* active: false,
|
||||
* Roles: [], // maps to "Roles" in the DB/JSON but the prop would be accessible via "model.roles"
|
||||
* meta: {}
|
||||
* name: "" // or nullString() if nullable
|
||||
* age: 0, // or nullInt() if nullable
|
||||
* totalSpent: -0, // or nullFloat() if nullable
|
||||
* active: false, // or nullBool() if nullable
|
||||
* Roles: [], // or nullArray() if nullable; maps to "Roles" in the DB/JSON but the prop would be accessible via "model.roles"
|
||||
* meta: {}, // or nullObject() if nullable
|
||||
* })
|
||||
* ` + "```" + `
|
||||
*
|
||||
* @group PocketBase
|
||||
*/
|
||||
declare class DynamicModel {
|
||||
[key: string]: any;
|
||||
constructor(shape?: { [key:string]: any })
|
||||
}
|
||||
|
||||
/**
|
||||
* nullString creates an empty Go string pointer usually used for
|
||||
* describing a **nullable** ` + "`DynamicModel`" + ` string value.
|
||||
*
|
||||
* @group PocketBase
|
||||
*/
|
||||
declare function nullString(): string;
|
||||
|
||||
/**
|
||||
* nullInt creates an empty Go int64 pointer usually used for
|
||||
* describing a **nullable** ` + "`DynamicModel`" + ` int value.
|
||||
*
|
||||
* @group PocketBase
|
||||
*/
|
||||
declare function nullInt(): number;
|
||||
|
||||
/**
|
||||
* nullFloat creates an empty Go float64 pointer usually used for
|
||||
* describing a **nullable** ` + "`DynamicModel`" + ` float value.
|
||||
*
|
||||
* @group PocketBase
|
||||
*/
|
||||
declare function nullFloat(): number;
|
||||
|
||||
/**
|
||||
* nullBool creates an empty Go bool pointer usually used for
|
||||
* describing a **nullable** ` + "`DynamicModel`" + ` bool value.
|
||||
*
|
||||
* @group PocketBase
|
||||
*/
|
||||
declare function nullBool(): boolean;
|
||||
|
||||
/**
|
||||
* nullArray creates an empty Go types.JSONArray pointer usually used for
|
||||
* describing a **nullable** ` + "`DynamicModel`" + ` JSON array value.
|
||||
*
|
||||
* @group PocketBase
|
||||
*/
|
||||
declare function nullArray(): Array<any>;
|
||||
|
||||
/**
|
||||
* nullObject creates an empty Go types.JSONMap pointer usually used for
|
||||
* describing a **nullable** ` + "`DynamicModel`" + ` JSON object value.
|
||||
*
|
||||
* @group PocketBase
|
||||
*/
|
||||
declare function nullObject(): { get(key:string):any; set(key:string,value:any):void };
|
||||
|
||||
interface Context extends context.Context{} // merge
|
||||
/**
|
||||
* Context creates a new empty Go context.Context.
|
||||
@@ -788,6 +839,7 @@ declare namespace $mails {
|
||||
let sendRecordVerification: mails.sendRecordVerification
|
||||
let sendRecordChangeEmail: mails.sendRecordChangeEmail
|
||||
let sendRecordOTP: mails.sendRecordOTP
|
||||
let sendRecordAuthAlert: mails.sendRecordAuthAlert
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
@@ -377,7 +377,7 @@ func (p *plugin) watchHooks() error {
|
||||
if hooksDirInfo.Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||
watchDir, err = filepath.EvalSymlinks(p.config.HooksDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to resolve hooksDir symink: %w", err)
|
||||
return fmt.Errorf("failed to resolve hooksDir symlink: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ migrate((app) => {
|
||||
const collection = new Collection({
|
||||
"authAlert": {
|
||||
"emailTemplate": {
|
||||
"body": "<p>Hello,</p>\n<p>We noticed a login to your {APP_NAME} account from a new location.</p>\n<p>If this was you, you may disregard this email.</p>\n<p><strong>If this wasn't you, you should immediately change your {APP_NAME} account password to revoke access from all other locations.</strong></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>",
|
||||
"body": "<p>Hello,</p>\n<p>We noticed a login to your {APP_NAME} account from a new location:</p>\n<p><em>{ALERT_INFO}</em></p>\n<p><strong>If this wasn't you, you should immediately change your {APP_NAME} account password to revoke access from all other locations.</strong></p>\n<p>If this was you, you may disregard this email.</p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>",
|
||||
"subject": "Login from a new location"
|
||||
},
|
||||
"enabled": true
|
||||
@@ -205,7 +205,7 @@ func init() {
|
||||
jsonData := ` + "`" + `{
|
||||
"authAlert": {
|
||||
"emailTemplate": {
|
||||
"body": "<p>Hello,</p>\n<p>We noticed a login to your {APP_NAME} account from a new location.</p>\n<p>If this was you, you may disregard this email.</p>\n<p><strong>If this wasn't you, you should immediately change your {APP_NAME} account password to revoke access from all other locations.</strong></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>",
|
||||
"body": "<p>Hello,</p>\n<p>We noticed a login to your {APP_NAME} account from a new location:</p>\n<p><em>{ALERT_INFO}</em></p>\n<p><strong>If this wasn't you, you should immediately change your {APP_NAME} account password to revoke access from all other locations.</strong></p>\n<p>If this was you, you may disregard this email.</p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>",
|
||||
"subject": "Login from a new location"
|
||||
},
|
||||
"enabled": true
|
||||
@@ -470,7 +470,7 @@ migrate((app) => {
|
||||
const collection = new Collection({
|
||||
"authAlert": {
|
||||
"emailTemplate": {
|
||||
"body": "<p>Hello,</p>\n<p>We noticed a login to your {APP_NAME} account from a new location.</p>\n<p>If this was you, you may disregard this email.</p>\n<p><strong>If this wasn't you, you should immediately change your {APP_NAME} account password to revoke access from all other locations.</strong></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>",
|
||||
"body": "<p>Hello,</p>\n<p>We noticed a login to your {APP_NAME} account from a new location:</p>\n<p><em>{ALERT_INFO}</em></p>\n<p><strong>If this wasn't you, you should immediately change your {APP_NAME} account password to revoke access from all other locations.</strong></p>\n<p>If this was you, you may disregard this email.</p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>",
|
||||
"subject": "Login from a new location"
|
||||
},
|
||||
"enabled": true
|
||||
@@ -649,7 +649,7 @@ func init() {
|
||||
jsonData := ` + "`" + `{
|
||||
"authAlert": {
|
||||
"emailTemplate": {
|
||||
"body": "<p>Hello,</p>\n<p>We noticed a login to your {APP_NAME} account from a new location.</p>\n<p>If this was you, you may disregard this email.</p>\n<p><strong>If this wasn't you, you should immediately change your {APP_NAME} account password to revoke access from all other locations.</strong></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>",
|
||||
"body": "<p>Hello,</p>\n<p>We noticed a login to your {APP_NAME} account from a new location:</p>\n<p><em>{ALERT_INFO}</em></p>\n<p><strong>If this wasn't you, you should immediately change your {APP_NAME} account password to revoke access from all other locations.</strong></p>\n<p>If this was you, you may disregard this email.</p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>",
|
||||
"subject": "Login from a new location"
|
||||
},
|
||||
"enabled": true
|
||||
|
||||
Binary file not shown.
@@ -258,7 +258,7 @@ func TestCronStartStop(t *testing.T) {
|
||||
|
||||
c := New()
|
||||
|
||||
c.SetInterval(500 * time.Millisecond)
|
||||
c.SetInterval(250 * time.Millisecond)
|
||||
|
||||
c.Add("test1", "* * * * *", func() {
|
||||
test1++
|
||||
@@ -274,7 +274,7 @@ func TestCronStartStop(t *testing.T) {
|
||||
c.Start()
|
||||
c.Start()
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
time.Sleep(505 * time.Millisecond) // slightly larger to minimize flakiness
|
||||
|
||||
// call twice Stop to ensure that the second stop is no-op
|
||||
c.Stop()
|
||||
@@ -287,10 +287,10 @@ func TestCronStartStop(t *testing.T) {
|
||||
t.Fatalf("Expected %d test2, got %d", expectedCalls, test2)
|
||||
}
|
||||
|
||||
// resume for 2 seconds
|
||||
// resume for 1 seconds
|
||||
c.Start()
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
time.Sleep(1005 * time.Millisecond) // slightly larger to minimize flakiness
|
||||
|
||||
c.Stop()
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package dbutils
|
||||
|
||||
import "regexp"
|
||||
|
||||
// Regexp for columns and tables (the same as the one in dbx).
|
||||
var selectRegex = regexp.MustCompile(`(?i:\s+as\s+|\s+)([\w\-_\.]+)$`)
|
||||
|
||||
// AliasOrIdentifier returns the alias from a column or table identifier.
|
||||
// Returns the identifier unmodified if no alias was found.
|
||||
func AliasOrIdentifier(columnOrTableIdentifier string) string {
|
||||
matches := selectRegex.FindStringSubmatch(columnOrTableIdentifier)
|
||||
|
||||
if len(matches) > 0 && matches[1] != "" {
|
||||
return matches[1]
|
||||
}
|
||||
|
||||
return columnOrTableIdentifier
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package dbutils_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/pocketbase/pocketbase/tools/dbutils"
|
||||
)
|
||||
|
||||
func TestAliasOrIdentifier(t *testing.T) {
|
||||
scenarios := []struct {
|
||||
value string
|
||||
expected string
|
||||
}{
|
||||
{"", ""},
|
||||
{"abc", "abc"},
|
||||
{"abc ", "abc "}, // return unmodified
|
||||
{"abc.def", "abc.def"},
|
||||
{"abc.123 def", "def"},
|
||||
{"abc.123 as def.456", "def.456"},
|
||||
{"(abc) def", "def"},
|
||||
{"(abc) as def", "def"},
|
||||
{"abc def", "def"},
|
||||
{"abc as def", "def"},
|
||||
// technically invalid identifier but consistent with the dbx regex matching
|
||||
{"a b c d", "d"},
|
||||
{"a b c as d", "d"},
|
||||
}
|
||||
|
||||
for _, s := range scenarios {
|
||||
t.Run(s.value, func(t *testing.T) {
|
||||
result := dbutils.AliasOrIdentifier(s.value)
|
||||
|
||||
if result != s.expected {
|
||||
t.Fatalf("Expected\n%v\ngot\n%v", s.expected, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -193,22 +193,32 @@ var extInvalidCharsRegex = regexp.MustCompile(`[^\w\.\*\-\+\=\#]+`)
|
||||
const randomAlphabet = "abcdefghijklmnopqrstuvwxyz0123456789"
|
||||
|
||||
func normalizeName(fr FileReader, name string) string {
|
||||
// cut the name even if it is not multibyte safe to avoid operating on too large strings
|
||||
// ---
|
||||
originalLength := len(name)
|
||||
if originalLength > 300 {
|
||||
name = name[originalLength-300:]
|
||||
}
|
||||
|
||||
// extension
|
||||
// ---
|
||||
originalExt := extractExtension(name)
|
||||
cleanExt := extInvalidCharsRegex.ReplaceAllString(originalExt, "")
|
||||
if cleanExt == "" {
|
||||
cleanExt := "." + strings.Trim(extInvalidCharsRegex.ReplaceAllString(originalExt, ""), ".")
|
||||
if cleanExt == "." {
|
||||
// try to detect the extension from the file content
|
||||
cleanExt, _ = detectExtension(fr)
|
||||
}
|
||||
if extLength := len(cleanExt); extLength > 20 {
|
||||
// keep only the last 20 characters (it is multibyte safe after the regex replace)
|
||||
cleanExt = "." + cleanExt[extLength-20:]
|
||||
cleanExt = "." + strings.Trim(cleanExt[extLength-20:], ".")
|
||||
}
|
||||
|
||||
// name
|
||||
//
|
||||
// note: leading dot is trimmed to prevent various subtle issues with files
|
||||
// sync programs as they sometimes have special handling for "invisible" files
|
||||
// ---
|
||||
cleanName := inflector.Snakecase(strings.TrimSuffix(name, originalExt))
|
||||
cleanName := inflector.Snakecase(strings.Trim(strings.TrimSuffix(name, originalExt), "."))
|
||||
if length := len(cleanName); length < 3 {
|
||||
// the name is too short so we concatenate an additional random part
|
||||
cleanName += security.RandomStringWithAlphabet(10, randomAlphabet)
|
||||
|
||||
@@ -52,8 +52,8 @@ func TestNewFileFromPath(t *testing.T) {
|
||||
}
|
||||
|
||||
// existing file
|
||||
originalName := "image_! noext"
|
||||
normalizedNamePattern := regexp.QuoteMeta("image_noext_") + `\w{10}` + regexp.QuoteMeta(".png")
|
||||
originalName := "image_!@ special"
|
||||
normalizedNamePattern := regexp.QuoteMeta("image_special_") + `\w{10}` + regexp.QuoteMeta(".png")
|
||||
f, err := filesystem.NewFileFromPath(filepath.Join(testDir, originalName))
|
||||
if err != nil {
|
||||
t.Fatalf("Expected nil error, got %v", err)
|
||||
@@ -83,8 +83,8 @@ func TestNewFileFromBytes(t *testing.T) {
|
||||
t.Fatal("Expected error, got nil")
|
||||
}
|
||||
|
||||
originalName := "image_! noext"
|
||||
normalizedNamePattern := regexp.QuoteMeta("image_noext_") + `\w{10}` + regexp.QuoteMeta(".txt")
|
||||
originalName := "image_!@ special"
|
||||
normalizedNamePattern := regexp.QuoteMeta("image_special_") + `\w{10}` + regexp.QuoteMeta(".txt")
|
||||
f, err := filesystem.NewFileFromBytes([]byte("text\n"), originalName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -175,8 +175,8 @@ func TestNewFileFromURLTimeout(t *testing.T) {
|
||||
|
||||
// valid response
|
||||
{
|
||||
originalName := "image_! noext"
|
||||
normalizedNamePattern := regexp.QuoteMeta("image_noext_") + `\w{10}` + regexp.QuoteMeta(".txt")
|
||||
originalName := "image_!@ special"
|
||||
normalizedNamePattern := regexp.QuoteMeta("image_special_") + `\w{10}` + regexp.QuoteMeta(".txt")
|
||||
|
||||
f, err := filesystem.NewFileFromURL(context.Background(), srv.URL+"/"+originalName)
|
||||
if err != nil {
|
||||
@@ -211,10 +211,14 @@ func TestFileNameNormalizations(t *testing.T) {
|
||||
{".png", `^\w{10}_\w{10}\.png$`},
|
||||
{".tar.gz", `^\w{10}_\w{10}\.tar\.gz$`},
|
||||
{"a.tar.gz", `^a\w{10}_\w{10}\.tar\.gz$`},
|
||||
{"....abc", `^\w{10}_\w{10}\.abc$`},
|
||||
{"a.b.c.?.?.?.2", `^a_b_c_\w{10}\.2$`},
|
||||
{"a.b.c.d.tar.gz", `^a_b_c_d_\w{10}\.tar\.gz$`},
|
||||
{"abcd", `^abcd_\w{10}\.txt$`},
|
||||
{"a b! c d . 456", `^a_b_c_d_\w{10}\.456$`}, // normalize spaces
|
||||
{strings.Repeat("a", 101) + "." + strings.Repeat("b", 21), `^a{100}_\w{10}\.b{20}$`}, // name and extension length trim
|
||||
{".abcd.123.", `^abcd_\w{10}\.123$`},
|
||||
{"a b! c d . 456", `^a_b_c_d_\w{10}\.456$`}, // normalize spaces
|
||||
{strings.Repeat("a", 101) + "." + strings.Repeat("b", 21), `^a{100}_\w{10}\.b{20}$`}, // name and extension length cut
|
||||
{"abc" + strings.Repeat("d", 290) + "." + strings.Repeat("b", 9), `^d{100}_\w{10}\.b{9}$`}, // initial total length cut
|
||||
}
|
||||
|
||||
for i, s := range scenarios {
|
||||
@@ -223,7 +227,8 @@ func TestFileNameNormalizations(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if match, err := regexp.Match(s.pattern, []byte(f.Name)); !match {
|
||||
match, err := regexp.Match(s.pattern, []byte(f.Name))
|
||||
if !match {
|
||||
t.Fatalf("Expected Name to match %v, got %q (%v)", s.pattern, f.Name, err)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -536,25 +536,38 @@ func (s *System) CreateThumb(originalKey string, thumbKey, thumbSize string) err
|
||||
}
|
||||
}
|
||||
|
||||
originalContentType := r.ContentType()
|
||||
|
||||
opts := &blob.WriterOptions{
|
||||
ContentType: r.ContentType(),
|
||||
ContentType: originalContentType,
|
||||
}
|
||||
|
||||
// open a thumb storage writer (aka. prepare for upload)
|
||||
w, writerErr := s.bucket.NewWriter(s.ctx, thumbKey, opts)
|
||||
if writerErr != nil {
|
||||
return writerErr
|
||||
}
|
||||
var format imaging.Format
|
||||
|
||||
// try to detect the thumb format based on the original file name
|
||||
// (fallbacks to png on error)
|
||||
format, err := imaging.FormatFromFilename(thumbKey)
|
||||
if err != nil {
|
||||
switch originalContentType {
|
||||
case "image/jpeg":
|
||||
format = imaging.JPEG
|
||||
case "image/gif":
|
||||
format = imaging.GIF
|
||||
case "image/tiff":
|
||||
format = imaging.TIFF
|
||||
case "image/bmp":
|
||||
format = imaging.BMP
|
||||
default:
|
||||
// fallback to PNG (this includes webp!)
|
||||
opts.ContentType = "image/png"
|
||||
format = imaging.PNG
|
||||
}
|
||||
|
||||
// open a thumb storage writer (aka. prepare for upload)
|
||||
w, err := s.bucket.NewWriter(s.ctx, thumbKey, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// thumb encode (aka. upload)
|
||||
if err := imaging.Encode(w, thumbImg, format); err != nil {
|
||||
err = imaging.Encode(w, thumbImg, format)
|
||||
if err != nil {
|
||||
w.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -600,6 +600,7 @@ func TestFileSystemGetReuploadableFile(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
raw, err := io.ReadAll(r)
|
||||
if err != nil {
|
||||
@@ -677,12 +678,13 @@ 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.GetReader(dst)
|
||||
//nolint
|
||||
defer f.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("Missing copied file %q: %v", dst, err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if f.Size() != 73 {
|
||||
t.Fatalf("Expected file size %d, got %d", 73, f.Size())
|
||||
}
|
||||
@@ -709,7 +711,8 @@ func TestFileSystemList(t *testing.T) {
|
||||
"image.jpg",
|
||||
"image.svg",
|
||||
"image.webp",
|
||||
"image_! noext",
|
||||
"image_!@ special",
|
||||
"image_noext",
|
||||
"style.css",
|
||||
"main.js",
|
||||
"main.mjs",
|
||||
@@ -861,6 +864,8 @@ func TestFileSystemCreateThumb(t *testing.T) {
|
||||
{"image.jpg", "thumb.jpg", "100x100", "image/jpeg"},
|
||||
// webp (should produce png)
|
||||
{"image.webp", "thumb.webp", "100x100", "image/png"},
|
||||
// without extension (should extract the mimetype from its stored ContentType)
|
||||
{"image_noext", "image_noext.jpeg", "100x100", "image/jpeg"},
|
||||
}
|
||||
|
||||
for _, s := range scenarios {
|
||||
@@ -884,13 +889,20 @@ func TestFileSystemCreateThumb(t *testing.T) {
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
attrsMimeType := f.ContentType()
|
||||
|
||||
mt, err := mimetype.DetectReader(f)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to detect thumb %s mimetype (%v)", s.thumb, err)
|
||||
}
|
||||
fileMimeType := mt.String()
|
||||
|
||||
if mtStr := mt.String(); mtStr != s.expectedMimeType {
|
||||
t.Fatalf("Expected thumb %s MimeType %q, got %q", s.thumb, s.expectedMimeType, mtStr)
|
||||
if fileMimeType != s.expectedMimeType {
|
||||
t.Fatalf("Expected thumb file %s MimeType %q, got %q", s.thumb, s.expectedMimeType, fileMimeType)
|
||||
}
|
||||
|
||||
if attrsMimeType != s.expectedMimeType {
|
||||
t.Fatalf("Expected thumb attrs %s MimeType %q, got %q", s.thumb, s.expectedMimeType, attrsMimeType)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -975,16 +987,33 @@ func createTestDir(t *testing.T) string {
|
||||
}
|
||||
}
|
||||
|
||||
// no extension and invalid characters
|
||||
// invalid/special characters
|
||||
{
|
||||
file, err := os.OpenFile(filepath.Join(dir, "image_! noext"), os.O_WRONLY|os.O_CREATE, 0644)
|
||||
file, err := os.OpenFile(filepath.Join(dir, "image_!@ special"), os.O_WRONLY|os.O_CREATE, 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_ = png.Encode(file, image.Rect(0, 0, 1, 1)) // tiny 1x1 png
|
||||
imgRect := image.Rect(0, 0, 1, 1) // tiny 1x1 png
|
||||
_ = png.Encode(file, imgRect)
|
||||
file.Close()
|
||||
}
|
||||
|
||||
// no extension
|
||||
{
|
||||
fullPath := filepath.Join(dir, "image_noext")
|
||||
file, err := os.OpenFile(fullPath, os.O_WRONLY|os.O_CREATE, 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
imgRect := image.Rect(0, 0, 1, 1) // tiny 1x1 jpg
|
||||
_ = jpeg.Encode(file, imgRect, nil)
|
||||
file.Close()
|
||||
err = os.WriteFile(fullPath+".attrs", []byte(`{"user.cache_control":"","user.content_disposition":"","user.content_encoding":"","user.content_language":"","user.content_type":"image/jpeg","user.metadata":null}`), 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// css
|
||||
{
|
||||
file, err := os.OpenFile(filepath.Join(dir, "style.css"), os.O_WRONLY|os.O_CREATE, 0644)
|
||||
|
||||
+23
-15
@@ -218,7 +218,7 @@ func buildResolversExpr(
|
||||
expr = dbx.Enclose(dbx.And(expr, mm))
|
||||
} else if left.MultiMatchSubQuery != nil {
|
||||
mm := &manyVsOneExpr{
|
||||
noCoalesce: left.NoCoalesce,
|
||||
nullFallback: left.NullFallback,
|
||||
subQuery: left.MultiMatchSubQuery,
|
||||
op: op,
|
||||
otherOperand: right,
|
||||
@@ -227,7 +227,7 @@ func buildResolversExpr(
|
||||
expr = dbx.Enclose(dbx.And(expr, mm))
|
||||
} else if right.MultiMatchSubQuery != nil {
|
||||
mm := &manyVsOneExpr{
|
||||
noCoalesce: right.NoCoalesce,
|
||||
nullFallback: right.NullFallback,
|
||||
subQuery: right.MultiMatchSubQuery,
|
||||
op: op,
|
||||
otherOperand: left,
|
||||
@@ -326,9 +326,6 @@ func resolveToken(token fexpr.Token, fieldResolver FieldResolver) (*ResolverResu
|
||||
// `COALESCE(a, "") = ""` since the direct match can be accomplished
|
||||
// with a seek while the COALESCE will induce a table scan.
|
||||
func resolveEqualExpr(equal bool, left, right *ResolverResult) dbx.Expression {
|
||||
isLeftEmpty := isEmptyIdentifier(left) || (len(left.Params) == 1 && hasEmptyParamValue(left))
|
||||
isRightEmpty := isEmptyIdentifier(right) || (len(right.Params) == 1 && hasEmptyParamValue(right))
|
||||
|
||||
equalOp := "="
|
||||
nullEqualOp := "IS"
|
||||
concatOp := "OR"
|
||||
@@ -343,16 +340,23 @@ func resolveEqualExpr(equal bool, left, right *ResolverResult) dbx.Expression {
|
||||
nullExpr = "IS NOT NULL"
|
||||
}
|
||||
|
||||
// no coalesce (eg. compare to a json field)
|
||||
// no coalesce fallback (eg. compare to a json field)
|
||||
// a IS b
|
||||
// a IS NOT b
|
||||
if left.NoCoalesce || right.NoCoalesce {
|
||||
if left.NullFallback == NullFallbackDisabled ||
|
||||
right.NullFallback == NullFallbackDisabled {
|
||||
return dbx.NewExp(
|
||||
fmt.Sprintf("%s %s %s", left.Identifier, nullEqualOp, right.Identifier),
|
||||
mergeParams(left.Params, right.Params),
|
||||
)
|
||||
}
|
||||
|
||||
isLeftEmpty := isEmptyIdentifier(left) ||
|
||||
(left.NullFallback == NullFallbackAuto && len(left.Params) == 1 && hasEmptyParamValue(left))
|
||||
|
||||
isRightEmpty := isEmptyIdentifier(right) ||
|
||||
(right.NullFallback == NullFallbackAuto && len(right.Params) == 1 && hasEmptyParamValue(right))
|
||||
|
||||
// both operands are empty
|
||||
if isLeftEmpty && isRightEmpty {
|
||||
return dbx.NewExp(fmt.Sprintf("'' %s ''", equalOp), mergeParams(left.Params, right.Params))
|
||||
@@ -421,6 +425,10 @@ func hasEmptyParamValue(result *ResolverResult) bool {
|
||||
}
|
||||
|
||||
func isKnownNonEmptyIdentifier(result *ResolverResult) bool {
|
||||
if result.NullFallback == NullFallbackEnforced {
|
||||
return false
|
||||
}
|
||||
|
||||
switch strings.ToLower(result.Identifier) {
|
||||
case "1", "0", "false", `true`:
|
||||
return true
|
||||
@@ -631,13 +639,13 @@ func (e *manyVsManyExpr) Build(db *dbx.DB, params dbx.Params) string {
|
||||
|
||||
whereExpr, buildErr := buildResolversExpr(
|
||||
&ResolverResult{
|
||||
NoCoalesce: e.left.NoCoalesce,
|
||||
Identifier: "[[" + lAlias + ".multiMatchValue]]",
|
||||
NullFallback: e.left.NullFallback,
|
||||
Identifier: "[[" + lAlias + ".multiMatchValue]]",
|
||||
},
|
||||
e.op,
|
||||
&ResolverResult{
|
||||
NoCoalesce: e.right.NoCoalesce,
|
||||
Identifier: "[[" + rAlias + ".multiMatchValue]]",
|
||||
NullFallback: e.right.NullFallback,
|
||||
Identifier: "[[" + rAlias + ".multiMatchValue]]",
|
||||
// note: the AfterBuild needs to be handled only once and it
|
||||
// doesn't matter whether it is applied on the left or right subquery operand
|
||||
AfterBuild: dbx.Not, // inverse for the not-exist expression
|
||||
@@ -672,7 +680,7 @@ type manyVsOneExpr struct {
|
||||
subQuery dbx.Expression
|
||||
op fexpr.SignOp
|
||||
inverse bool
|
||||
noCoalesce bool
|
||||
nullFallback NullFallbackPreference
|
||||
}
|
||||
|
||||
// Build converts the expression into a SQL fragment.
|
||||
@@ -686,9 +694,9 @@ func (e *manyVsOneExpr) Build(db *dbx.DB, params dbx.Params) string {
|
||||
alias := "__sm" + security.PseudorandomString(8)
|
||||
|
||||
r1 := &ResolverResult{
|
||||
NoCoalesce: e.noCoalesce,
|
||||
Identifier: "[[" + alias + ".multiMatchValue]]",
|
||||
AfterBuild: dbx.Not, // inverse for the not-exist expression
|
||||
NullFallback: e.nullFallback,
|
||||
Identifier: "[[" + alias + ".multiMatchValue]]",
|
||||
AfterBuild: dbx.Not, // inverse for the not-exist expression
|
||||
}
|
||||
|
||||
r2 := &ResolverResult{
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package search
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
)
|
||||
|
||||
var _ dbx.Expression = (*MultiMatchSubquery)(nil)
|
||||
|
||||
// Join defines common fields required for a single SQL JOIN clause.
|
||||
type Join struct {
|
||||
TableName string
|
||||
TableAlias string
|
||||
On dbx.Expression
|
||||
}
|
||||
|
||||
// MultiMatchSubquery defines a multi-match record subquery expression.
|
||||
type MultiMatchSubquery struct {
|
||||
TargetTableAlias string
|
||||
FromTableName string
|
||||
FromTableAlias string
|
||||
ValueIdentifier string
|
||||
Joins []*Join
|
||||
Params dbx.Params
|
||||
}
|
||||
|
||||
// Build converts the expression into a SQL fragment.
|
||||
//
|
||||
// Implements [dbx.Expression] interface.
|
||||
func (m *MultiMatchSubquery) Build(db *dbx.DB, params dbx.Params) string {
|
||||
if m.TargetTableAlias == "" || m.FromTableName == "" || m.FromTableAlias == "" {
|
||||
return "0=1"
|
||||
}
|
||||
|
||||
if params == nil {
|
||||
params = m.Params
|
||||
} else {
|
||||
// merge by updating the parent params
|
||||
for k, v := range m.Params {
|
||||
params[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
var mergedJoins strings.Builder
|
||||
for i, j := range m.Joins {
|
||||
if i > 0 {
|
||||
mergedJoins.WriteString(" ")
|
||||
}
|
||||
mergedJoins.WriteString("LEFT JOIN ")
|
||||
mergedJoins.WriteString(db.QuoteTableName(j.TableName))
|
||||
mergedJoins.WriteString(" ")
|
||||
mergedJoins.WriteString(db.QuoteTableName(j.TableAlias))
|
||||
if j.On != nil {
|
||||
mergedJoins.WriteString(" ON ")
|
||||
mergedJoins.WriteString(j.On.Build(db, params))
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Sprintf(
|
||||
`SELECT %s as [[multiMatchValue]] FROM %s %s %s WHERE %s = %s`,
|
||||
db.QuoteColumnName(m.ValueIdentifier),
|
||||
db.QuoteTableName(m.FromTableName),
|
||||
db.QuoteTableName(m.FromTableAlias),
|
||||
mergedJoins.String(),
|
||||
db.QuoteColumnName(m.FromTableAlias+".id"),
|
||||
db.QuoteColumnName(m.TargetTableAlias+".id"),
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package search_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/tools/search"
|
||||
)
|
||||
|
||||
func TestMultiMatchSubqueryBuild(t *testing.T) {
|
||||
// create a dummy db
|
||||
sqlDB, err := sql.Open("sqlite", "file::memory:?cache=shared")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
db := dbx.NewFromDB(sqlDB, "sqlite")
|
||||
|
||||
mm := search.MultiMatchSubquery{
|
||||
TargetTableAlias: "test_TargetTableAlias",
|
||||
FromTableName: "test_FromTableName",
|
||||
FromTableAlias: "test_FromTableAlias",
|
||||
ValueIdentifier: "({:mm},{:external})",
|
||||
Joins: []*search.Join{
|
||||
{TableName: "join_table1", TableAlias: "join_alias1"},
|
||||
{TableName: "join_table2", TableAlias: "join_alias2", On: dbx.NewExp("123={:join}", dbx.Params{"join": "test_join"})},
|
||||
},
|
||||
Params: dbx.Params{"mm": "test_mm"},
|
||||
}
|
||||
|
||||
params := dbx.Params{"external": "test_external"}
|
||||
|
||||
result := mm.Build(db, params)
|
||||
|
||||
expectedResult := "SELECT ({:mm},{:external}) as [[multiMatchValue]] FROM `test_FromTableName` `test_FromTableAlias` LEFT JOIN `join_table1` `join_alias1` LEFT JOIN `join_table2` `join_alias2` ON 123={:join} WHERE `test_FromTableAlias`.`id` = `test_TargetTableAlias`.`id`"
|
||||
if expectedResult != result {
|
||||
t.Fatalf("Expected build result\n%v\ngot\n%v", expectedResult, result)
|
||||
}
|
||||
|
||||
// the params from all expressions should be merged in the root
|
||||
rawParams, err := json.Marshal(params)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
expectedParams := []byte(`{"external":"test_external","join":"test_join","mm":"test_mm"}`)
|
||||
if !bytes.Equal(rawParams, expectedParams) {
|
||||
t.Fatalf("Expected final params\n%s\ngot\n%s", expectedParams, rawParams)
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/tools/dbutils"
|
||||
"github.com/pocketbase/pocketbase/tools/inflector"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
@@ -298,13 +299,21 @@ func (s *Provider) Exec(items any) (*Result, error) {
|
||||
countExec := func() error {
|
||||
queryInfo := countQuery.Info()
|
||||
countCol := s.countCol
|
||||
|
||||
if len(queryInfo.From) > 0 {
|
||||
countCol = queryInfo.From[0] + "." + countCol
|
||||
firstFrom := dbutils.AliasOrIdentifier(queryInfo.From[0])
|
||||
countCol = firstFrom + "." + countCol
|
||||
}
|
||||
|
||||
// @todo while currently there is no such use case, evaluate if
|
||||
// wrapping as a subquery would be more suitable for the cases
|
||||
// when there is "Group By" different from the default deduplication one
|
||||
// added by RecordFieldResolver.UpdateQuery
|
||||
|
||||
// note: countQuery is shallow cloned and slice/map in-place modifications should be avoided
|
||||
err := countQuery.Distinct(false).
|
||||
Select("COUNT(DISTINCT [[" + countCol + "]])").
|
||||
GroupBy( /* reset */ ).
|
||||
OrderBy( /* reset */ ).
|
||||
Row(&totalCount)
|
||||
if err != nil {
|
||||
|
||||
@@ -10,15 +10,26 @@ import (
|
||||
"github.com/pocketbase/pocketbase/tools/list"
|
||||
)
|
||||
|
||||
type NullFallbackPreference int
|
||||
|
||||
const (
|
||||
NullFallbackAuto NullFallbackPreference = 0
|
||||
NullFallbackDisabled NullFallbackPreference = 1
|
||||
NullFallbackEnforced NullFallbackPreference = 2
|
||||
)
|
||||
|
||||
// ResolverResult defines a single FieldResolver.Resolve() successfully parsed result.
|
||||
type ResolverResult struct {
|
||||
// Identifier is the plain SQL identifier/column that will be used
|
||||
// in the final db expression as left or right operand.
|
||||
Identifier string
|
||||
|
||||
// NoCoalesce instructs to not use COALESCE or NULL fallbacks
|
||||
// when building the identifier expression.
|
||||
NoCoalesce bool
|
||||
// NullFallback specify the preference for how NULL or empty values
|
||||
// should be resolved (default to "auto").
|
||||
//
|
||||
// Set to NullFallbackDisabled to prevent any COALESCE or NULL fallbacks.
|
||||
// Set to NullFallbackEnforced to prefer COALESCE or NULL fallbacks when needed.
|
||||
NullFallback NullFallbackPreference
|
||||
|
||||
// Params is a map with db placeholder->value pairs that will be added
|
||||
// to the query when building both resolved operands/sides in a single expression.
|
||||
@@ -26,7 +37,7 @@ type ResolverResult struct {
|
||||
|
||||
// MultiMatchSubQuery is an optional sub query expression that will be added
|
||||
// in addition to the combined ResolverResult expression during build.
|
||||
MultiMatchSubQuery dbx.Expression
|
||||
MultiMatchSubQuery *MultiMatchSubquery
|
||||
|
||||
// AfterBuild is an optional function that will be called after building
|
||||
// and combining the result of both resolved operands/sides in a single expression.
|
||||
@@ -103,7 +114,7 @@ func (r *SimpleFieldResolver) Resolve(field string) (*ResolverResult, error) {
|
||||
}
|
||||
|
||||
return &ResolverResult{
|
||||
NoCoalesce: true,
|
||||
NullFallback: NullFallbackDisabled,
|
||||
Identifier: fmt.Sprintf(
|
||||
"JSON_EXTRACT([[%s]], '%s')",
|
||||
inflector.Columnify(parts[0]),
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
package search
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/ganigeorgiev/fexpr"
|
||||
"github.com/pocketbase/dbx"
|
||||
)
|
||||
|
||||
var TokenFunctions = map[string]func(
|
||||
@@ -44,7 +48,7 @@ var TokenFunctions = map[string]func(
|
||||
latB := resolvedArgs[3].Identifier
|
||||
|
||||
return &ResolverResult{
|
||||
NoCoalesce: true,
|
||||
NullFallback: NullFallbackDisabled,
|
||||
Identifier: `(6371 * acos(` +
|
||||
`cos(radians(` + latA + `)) * cos(radians(` + latB + `)) * ` +
|
||||
`cos(radians(` + lonB + `) - radians(` + lonA + `)) + ` +
|
||||
@@ -53,4 +57,139 @@ var TokenFunctions = map[string]func(
|
||||
Params: mergeParams(resolvedArgs[0].Params, resolvedArgs[1].Params, resolvedArgs[2].Params, resolvedArgs[3].Params),
|
||||
}, nil
|
||||
},
|
||||
|
||||
// strftime(format, [timeValue, modifier1, modifier2, ...]) returns
|
||||
// a date string formatted according to the specified format argument.
|
||||
//
|
||||
// It is similar to the builtin SQLite strftime function (https://sqlite.org/lang_datefunc.html)
|
||||
// with the main difference that NULL results will be normalized for
|
||||
// consistency with the non-nullable PocketBase "text" and "date" fields.
|
||||
//
|
||||
// The function accepts 1, 2 or 3+ arguments.
|
||||
//
|
||||
// (1) The first (format) argument must be always a formatting string
|
||||
// with valid substitutions as listed in https://sqlite.org/lang_datefunc.html.
|
||||
//
|
||||
// (2) The second (time-value) argument is optional and must be either a date string, number or collection field identifier
|
||||
// that matches one of the formats listed in https://sqlite.org/lang_datefunc.html#time_values.
|
||||
//
|
||||
// (3+) The remaining (modifiers) optional arguments are expected to be
|
||||
// string literals matching the listed modifiers in https://sqlite.org/lang_datefunc.html#modifiers.
|
||||
//
|
||||
// A multi-match constraint will be also applied in case the time-value
|
||||
// is an identifier as a result of a multi-value relation field.
|
||||
"strftime": func(argTokenResolverFunc func(fexpr.Token) (*ResolverResult, error), args ...fexpr.Token) (*ResolverResult, error) {
|
||||
totalArgs := len(args)
|
||||
|
||||
if totalArgs < 1 {
|
||||
return nil, fmt.Errorf("[strftime] expected at least 1 arguments, got %d", len(args))
|
||||
}
|
||||
|
||||
// limit the number of arguments to prevent abuse
|
||||
if totalArgs > 10 {
|
||||
return nil, fmt.Errorf("[strftime] too many arguments (max allowed 10, got %d)", totalArgs)
|
||||
}
|
||||
|
||||
// format arg
|
||||
// -----------------------------------------------------------
|
||||
if args[0].Type != fexpr.TokenText {
|
||||
return nil, errors.New("[strftime] expects the first argument to be a format string")
|
||||
}
|
||||
|
||||
formatArgResult, err := argTokenResolverFunc(args[0])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("[strftime] failed to resolve format argument: %w", err)
|
||||
}
|
||||
|
||||
// no further arguments
|
||||
if totalArgs == 1 {
|
||||
formatArgResult.NullFallback = NullFallbackEnforced
|
||||
formatArgResult.Identifier = "strftime(" + formatArgResult.Identifier + ")"
|
||||
return formatArgResult, nil
|
||||
}
|
||||
|
||||
// time-value arg
|
||||
// -----------------------------------------------------------
|
||||
allowedTimeValueTokens := []fexpr.TokenType{fexpr.TokenText, fexpr.TokenIdentifier, fexpr.TokenNumber}
|
||||
if !slices.Contains(allowedTimeValueTokens, args[1].Type) {
|
||||
return nil, errors.New("[strftime] expects the second argument to be of a valid time-value type")
|
||||
}
|
||||
|
||||
timeValueArgResult, err := argTokenResolverFunc(args[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("[strftime] failed to resolve time-value argument: %w", err)
|
||||
}
|
||||
|
||||
// modifiers args
|
||||
// -----------------------------------------------------------
|
||||
resolvedModifierArgs := make([]*ResolverResult, totalArgs-2)
|
||||
for i, arg := range args[2:] {
|
||||
if arg.Type != fexpr.TokenText {
|
||||
return nil, fmt.Errorf("[strftime] invalid modifier argument %d - can be only string", i)
|
||||
}
|
||||
|
||||
resolved, err := argTokenResolverFunc(arg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("[strftime] failed to resolve modifier argument %d: %w", i, err)
|
||||
}
|
||||
|
||||
resolvedModifierArgs[i] = resolved
|
||||
}
|
||||
|
||||
// generating new ResolverResult
|
||||
// -----------------------------------------------------------
|
||||
result := &ResolverResult{
|
||||
NullFallback: NullFallbackEnforced,
|
||||
Params: dbx.Params{},
|
||||
}
|
||||
|
||||
identifiers := make([]string, 0, totalArgs)
|
||||
|
||||
identifiers = append(identifiers, formatArgResult.Identifier)
|
||||
if err = concatUniqueParams(result.Params, formatArgResult.Params); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
identifiers = append(identifiers, timeValueArgResult.Identifier)
|
||||
if err = concatUniqueParams(result.Params, timeValueArgResult.Params); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, m := range resolvedModifierArgs {
|
||||
identifiers = append(identifiers, m.Identifier)
|
||||
err = concatUniqueParams(result.Params, m.Params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
result.Identifier = "strftime(" + strings.Join(identifiers, ",") + ")"
|
||||
|
||||
if timeValueArgResult.MultiMatchSubQuery != nil {
|
||||
// replace the regular time-value identifier with the multi-match one
|
||||
identifiers[1] = timeValueArgResult.MultiMatchSubQuery.ValueIdentifier
|
||||
result.MultiMatchSubQuery = timeValueArgResult.MultiMatchSubQuery
|
||||
result.MultiMatchSubQuery.ValueIdentifier = "strftime(" + strings.Join(identifiers, ",") + ")"
|
||||
|
||||
err = concatUniqueParams(result.MultiMatchSubQuery.Params, result.Params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
},
|
||||
}
|
||||
|
||||
func concatUniqueParams(destParams, newParams dbx.Params) error {
|
||||
for k, v := range newParams {
|
||||
found, ok := destParams[k]
|
||||
if ok && v != found {
|
||||
return fmt.Errorf("conflicting param key %s", k)
|
||||
}
|
||||
|
||||
destParams[k] = v
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -116,8 +116,8 @@ func TestTokenFunctionsGeoDistance(t *testing.T) {
|
||||
},
|
||||
baseTokenResolver,
|
||||
&ResolverResult{
|
||||
NoCoalesce: true,
|
||||
Identifier: `(6371 * acos(cos(radians({:latA})) * cos(radians({:latB})) * cos(radians({:lonB}) - radians({:lonA})) + sin(radians({:latA})) * sin(radians({:latB}))))`,
|
||||
NullFallback: NullFallbackDisabled,
|
||||
Identifier: `(6371 * acos(cos(radians({:latA})) * cos(radians({:latB})) * cos(radians({:lonB}) - radians({:lonA})) + sin(radians({:latA})) * sin(radians({:latB}))))`,
|
||||
Params: map[string]any{
|
||||
"lonA": 1,
|
||||
"latA": 2,
|
||||
@@ -137,8 +137,8 @@ func TestTokenFunctionsGeoDistance(t *testing.T) {
|
||||
},
|
||||
baseTokenResolver,
|
||||
&ResolverResult{
|
||||
NoCoalesce: true,
|
||||
Identifier: `(6371 * acos(cos(radians({:latA})) * cos(radians({:latB})) * cos(radians({:lonB}) - radians({:lonA})) + sin(radians({:latA})) * sin(radians({:latB}))))`,
|
||||
NullFallback: NullFallbackDisabled,
|
||||
Identifier: `(6371 * acos(cos(radians({:latA})) * cos(radians({:latB})) * cos(radians({:lonB}) - radians({:lonA})) + sin(radians({:latA})) * sin(radians({:latB}))))`,
|
||||
Params: map[string]any{
|
||||
"lonA": "null",
|
||||
"latA": 2,
|
||||
@@ -209,6 +209,351 @@ func TestTokenFunctionsGeoDistanceExec(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTokenFunctionsStrftime(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testDB, err := createTestDB()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer testDB.Close()
|
||||
|
||||
fn, ok := TokenFunctions["strftime"]
|
||||
if !ok {
|
||||
t.Error("Expected strftime token function to be registered.")
|
||||
}
|
||||
|
||||
baseTokenResolver := func(t fexpr.Token) (*ResolverResult, error) {
|
||||
placeholder := "t" + security.PseudorandomString(5)
|
||||
return &ResolverResult{Identifier: "{:" + placeholder + "}", Params: map[string]any{placeholder: t.Literal}}, nil
|
||||
}
|
||||
|
||||
scenarios := []struct {
|
||||
name string
|
||||
args []fexpr.Token
|
||||
resolver func(t fexpr.Token) (*ResolverResult, error)
|
||||
result *ResolverResult
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
"no args",
|
||||
nil,
|
||||
baseTokenResolver,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
|
||||
// format arg
|
||||
// -----------------------------------------------------------
|
||||
{
|
||||
"(format arg) invalid token type function",
|
||||
[]fexpr.Token{
|
||||
{Literal: "abc", Type: fexpr.TokenFunction},
|
||||
},
|
||||
baseTokenResolver,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"(format arg) invalid token type ws",
|
||||
[]fexpr.Token{
|
||||
{Literal: "abc", Type: fexpr.TokenWS},
|
||||
},
|
||||
baseTokenResolver,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"(format arg) invalid token type number",
|
||||
[]fexpr.Token{
|
||||
{Literal: "abc", Type: fexpr.TokenNumber},
|
||||
},
|
||||
baseTokenResolver,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"(format arg) invalid token type identifier",
|
||||
[]fexpr.Token{
|
||||
{Literal: "abc", Type: fexpr.TokenIdentifier},
|
||||
},
|
||||
baseTokenResolver,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"(format arg) valid token type text",
|
||||
[]fexpr.Token{
|
||||
{Literal: "abc", Type: fexpr.TokenText},
|
||||
},
|
||||
baseTokenResolver,
|
||||
&ResolverResult{
|
||||
NullFallback: NullFallbackEnforced,
|
||||
Identifier: `strftime({:format})`,
|
||||
Params: map[string]any{"format": "abc"},
|
||||
},
|
||||
false,
|
||||
},
|
||||
|
||||
// format + time-value args
|
||||
// -----------------------------------------------------------
|
||||
{
|
||||
"(format arg) invalid token type function",
|
||||
[]fexpr.Token{
|
||||
{Literal: "1", Type: fexpr.TokenText},
|
||||
{Literal: "2", Type: fexpr.TokenFunction},
|
||||
},
|
||||
baseTokenResolver,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"(format arg) invalid token type ws",
|
||||
[]fexpr.Token{
|
||||
{Literal: "1", Type: fexpr.TokenText},
|
||||
{Literal: "2", Type: fexpr.TokenWS},
|
||||
},
|
||||
baseTokenResolver,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"(format arg) valid token type number",
|
||||
[]fexpr.Token{
|
||||
{Literal: "1", Type: fexpr.TokenText},
|
||||
{Literal: "2", Type: fexpr.TokenNumber},
|
||||
},
|
||||
baseTokenResolver,
|
||||
&ResolverResult{
|
||||
NullFallback: NullFallbackEnforced,
|
||||
Identifier: `strftime({:format},{:time})`,
|
||||
Params: map[string]any{"format": "1", "time": "2"},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"(format arg) valid token type identifier",
|
||||
[]fexpr.Token{
|
||||
{Literal: "1", Type: fexpr.TokenText},
|
||||
{Literal: "2", Type: fexpr.TokenIdentifier},
|
||||
},
|
||||
baseTokenResolver,
|
||||
&ResolverResult{
|
||||
NullFallback: NullFallbackEnforced,
|
||||
Identifier: `strftime({:format},{:time})`,
|
||||
Params: map[string]any{"format": "1", "time": "2"},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"(format arg) valid token type text",
|
||||
[]fexpr.Token{
|
||||
{Literal: "1", Type: fexpr.TokenText},
|
||||
{Literal: "2", Type: fexpr.TokenText},
|
||||
},
|
||||
baseTokenResolver,
|
||||
&ResolverResult{
|
||||
NullFallback: NullFallbackEnforced,
|
||||
Identifier: `strftime({:format},{:time})`,
|
||||
Params: map[string]any{"format": "1", "time": "2"},
|
||||
},
|
||||
false,
|
||||
},
|
||||
|
||||
// format + time-value + modifier args
|
||||
// -----------------------------------------------------------
|
||||
{
|
||||
"(modifiers arg) invalid token type function",
|
||||
[]fexpr.Token{
|
||||
{Literal: "1", Type: fexpr.TokenText}, // valid format
|
||||
{Literal: "2", Type: fexpr.TokenText}, // valid time-value
|
||||
{Literal: "3", Type: fexpr.TokenText}, // valid modifier
|
||||
{Literal: "4", Type: fexpr.TokenFunction},
|
||||
},
|
||||
baseTokenResolver,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"(modifiers arg) invalid token type ws",
|
||||
[]fexpr.Token{
|
||||
{Literal: "1", Type: fexpr.TokenText}, // valid format
|
||||
{Literal: "2", Type: fexpr.TokenText}, // valid time-value
|
||||
{Literal: "3", Type: fexpr.TokenText}, // valid modifier
|
||||
{Literal: "4", Type: fexpr.TokenWS},
|
||||
},
|
||||
baseTokenResolver,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"(modifiers arg) valid token type number",
|
||||
[]fexpr.Token{
|
||||
{Literal: "1", Type: fexpr.TokenText}, // valid format
|
||||
{Literal: "2", Type: fexpr.TokenText}, // valid time-value
|
||||
{Literal: "3", Type: fexpr.TokenText}, // valid modifier
|
||||
{Literal: "4", Type: fexpr.TokenNumber},
|
||||
},
|
||||
baseTokenResolver,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"(modifiers arg) valid token type identifier",
|
||||
[]fexpr.Token{
|
||||
{Literal: "1", Type: fexpr.TokenText}, // valid format
|
||||
{Literal: "2", Type: fexpr.TokenText}, // valid time-value
|
||||
{Literal: "3", Type: fexpr.TokenText}, // valid modifier
|
||||
{Literal: "4", Type: fexpr.TokenIdentifier},
|
||||
},
|
||||
baseTokenResolver,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"(modifiers arg) valid token type text",
|
||||
[]fexpr.Token{
|
||||
{Literal: "1", Type: fexpr.TokenText}, // valid format
|
||||
{Literal: "2", Type: fexpr.TokenText}, // valid time-value
|
||||
{Literal: "3", Type: fexpr.TokenText}, // valid modifier
|
||||
{Literal: "4", Type: fexpr.TokenText}, // valid modifier
|
||||
},
|
||||
baseTokenResolver,
|
||||
&ResolverResult{
|
||||
NullFallback: NullFallbackEnforced,
|
||||
Identifier: `strftime({:format},{:time},{:m1},{:m2})`,
|
||||
Params: map[string]any{"format": "1", "time": "2", "m1": "3", "m2": "4"},
|
||||
},
|
||||
false,
|
||||
},
|
||||
|
||||
// -----------------------------------------------------------
|
||||
|
||||
{
|
||||
"= 10 args limit",
|
||||
[]fexpr.Token{
|
||||
{Literal: "1", Type: fexpr.TokenText},
|
||||
{Literal: "2", Type: fexpr.TokenText},
|
||||
{Literal: "3", Type: fexpr.TokenText},
|
||||
{Literal: "4", Type: fexpr.TokenText},
|
||||
{Literal: "5", Type: fexpr.TokenText},
|
||||
{Literal: "6", Type: fexpr.TokenText},
|
||||
{Literal: "7", Type: fexpr.TokenText},
|
||||
{Literal: "8", Type: fexpr.TokenText},
|
||||
{Literal: "9", Type: fexpr.TokenText},
|
||||
{Literal: "10", Type: fexpr.TokenText},
|
||||
},
|
||||
baseTokenResolver,
|
||||
&ResolverResult{
|
||||
NullFallback: NullFallbackEnforced,
|
||||
Identifier: `strftime({:format},{:time},{:m1},{:m2},{:m3},{:m4},{:m5},{:m6},{:m7},{:m8})`,
|
||||
Params: map[string]any{
|
||||
"format": "1",
|
||||
"time": "2",
|
||||
"m1": "3",
|
||||
"m2": "4",
|
||||
"m3": "5",
|
||||
"m4": "6",
|
||||
"m5": "7",
|
||||
"m6": "8",
|
||||
"m7": "9",
|
||||
"m8": "10",
|
||||
},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"> 10 args limit",
|
||||
[]fexpr.Token{
|
||||
{Literal: "1", Type: fexpr.TokenText},
|
||||
{Literal: "2", Type: fexpr.TokenText},
|
||||
{Literal: "3", Type: fexpr.TokenText},
|
||||
{Literal: "4", Type: fexpr.TokenText},
|
||||
{Literal: "5", Type: fexpr.TokenText},
|
||||
{Literal: "6", Type: fexpr.TokenText},
|
||||
{Literal: "7", Type: fexpr.TokenText},
|
||||
{Literal: "8", Type: fexpr.TokenText},
|
||||
{Literal: "9", Type: fexpr.TokenText},
|
||||
{Literal: "10", Type: fexpr.TokenText},
|
||||
{Literal: "11", Type: fexpr.TokenText},
|
||||
},
|
||||
baseTokenResolver,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"valid arguments but with resolver error",
|
||||
[]fexpr.Token{
|
||||
{Literal: "1", Type: fexpr.TokenText},
|
||||
{Literal: "2", Type: fexpr.TokenText},
|
||||
{Literal: "3", Type: fexpr.TokenText},
|
||||
},
|
||||
func(t fexpr.Token) (*ResolverResult, error) {
|
||||
return nil, errors.New("test")
|
||||
},
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, s := range scenarios {
|
||||
t.Run(s.name, func(t *testing.T) {
|
||||
result, err := fn(s.resolver, s.args...)
|
||||
|
||||
hasErr := err != nil
|
||||
if hasErr != s.expectErr {
|
||||
t.Fatalf("Expected hasErr %v, got %v (%v)", s.expectErr, hasErr, err)
|
||||
}
|
||||
|
||||
testCompareResults(t, s.result, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTokenFunctionsStrftimeExec(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testDB, err := createTestDB()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer testDB.Close()
|
||||
|
||||
fn, ok := TokenFunctions["strftime"]
|
||||
if !ok {
|
||||
t.Error("Expected strftime token function to be registered.")
|
||||
}
|
||||
|
||||
result, err := fn(
|
||||
func(t fexpr.Token) (*ResolverResult, error) {
|
||||
placeholder := "t" + security.PseudorandomString(5)
|
||||
return &ResolverResult{Identifier: "{:" + placeholder + "}", Params: map[string]any{placeholder: t.Literal}}, nil
|
||||
},
|
||||
fexpr.Token{Literal: "%Y-%m", Type: fexpr.TokenText},
|
||||
fexpr.Token{Literal: "2026-01-02 01:02:03.456Z", Type: fexpr.TokenText},
|
||||
fexpr.Token{Literal: "+1 years", Type: fexpr.TokenText},
|
||||
fexpr.Token{Literal: "+5 months", Type: fexpr.TokenText},
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
column := []string{}
|
||||
err = testDB.NewQuery("select " + result.Identifier).Bind(result.Params).Column(&column)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(column) != 1 {
|
||||
t.Fatalf("Expected exactly 1 column value as result, got %v", column)
|
||||
}
|
||||
|
||||
expected := "2027-06"
|
||||
if column[0] != expected {
|
||||
t.Fatalf("Expected date value %s, got %s", expected, column[0])
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
func testCompareResults(t *testing.T, a, b *ResolverResult) {
|
||||
@@ -258,8 +603,12 @@ func testCompareResults(t *testing.T, a, b *ResolverResult) {
|
||||
t.Fatalf("Expected bMultiMatchSubQuery and bMultiMatchSubQuery to be the same, got\n%s\nvs\n%s", aMultiMatchSubQuery, bMultiMatchSubQuery)
|
||||
}
|
||||
|
||||
if a.NoCoalesce != b.NoCoalesce {
|
||||
t.Fatalf("Expected NoCoalesce to match, got %v vs %v", a.NoCoalesce, b.NoCoalesce)
|
||||
if a.NullFallback != b.NullFallback {
|
||||
t.Fatalf("Expected NullFallback to match, got %v vs %v", a.NullFallback, b.NullFallback)
|
||||
}
|
||||
|
||||
if len(a.Params) != len(b.Params) {
|
||||
t.Fatalf("Expected equal number of params, got %v vs %v", len(a.Params), len(b.Params))
|
||||
}
|
||||
|
||||
// loose placeholders replacement
|
||||
|
||||
@@ -3,7 +3,7 @@ package security
|
||||
import (
|
||||
cryptoRand "crypto/rand"
|
||||
"math/big"
|
||||
mathRand "math/rand" // @todo replace with rand/v2?
|
||||
mathRand "math/rand/v2"
|
||||
)
|
||||
|
||||
const defaultRandomAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
||||
@@ -52,7 +52,7 @@ func PseudorandomStringWithAlphabet(length int, alphabet string) string {
|
||||
max := len(alphabet)
|
||||
|
||||
for i := range b {
|
||||
b[i] = alphabet[mathRand.Intn(max)]
|
||||
b[i] = alphabet[mathRand.IntN(max)]
|
||||
}
|
||||
|
||||
return string(b)
|
||||
|
||||
@@ -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.32.0"
|
||||
PB_VERSION = "v0.36.0"
|
||||
|
||||
+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-Btw6v1uV.js";import{F as Fe}from"./FieldsQueryParam-C-_OAeFs.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-B0jOWZIL.js";import{F as Fe}from"./FieldsQueryParam-f4jfjPs6.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-Btw6v1uV.js";import{F as et}from"./FieldsQueryParam-C-_OAeFs.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-B0jOWZIL.js";import{F as et}from"./FieldsQueryParam-f4jfjPs6.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-Btw6v1uV.js";import{F as Ge}from"./FieldsQueryParam-C-_OAeFs.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-B0jOWZIL.js";import{F as Ge}from"./FieldsQueryParam-f4jfjPs6.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-Btw6v1uV.js";import{F as Ze}from"./FieldsQueryParam-C-_OAeFs.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-B0jOWZIL.js";import{F as Ze}from"./FieldsQueryParam-f4jfjPs6.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-Btw6v1uV.js";import{F as Tt}from"./FieldsQueryParam-C-_OAeFs.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-B0jOWZIL.js";import{F as Tt}from"./FieldsQueryParam-f4jfjPs6.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-Btw6v1uV.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,w,oe,O,ae,I,se,H,ne,J,ie,q,ce,Ie,re,S,z,He,k,W,Se,de,Ae,D,G,Le,ue,Me,K,je,pe,Ne,C,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,De,st,R,Ce,A,we,T,L,v=[],nt=new Map,it,M,$=[],ct=new Map,j,qe,rt;w=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-B0jOWZIL.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,w,oe,O,ae,I,se,H,ne,J,ie,q,ce,Ie,re,S,z,He,k,W,Se,de,Ae,D,G,Le,ue,Me,K,je,pe,Ne,C,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,De,st,R,Ce,A,we,T,L,v=[],nt=new Map,it,M,$=[],ct=new Map,j,qe,rt;w=new Mt({props:{js:`
|
||||
import PocketBase from 'pocketbase';
|
||||
|
||||
const pb = new PocketBase('${a[2]}');
|
||||
+14
File diff suppressed because one or more lines are too long
-14
File diff suppressed because one or more lines are too long
+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-Btw6v1uV.js";import{F as Rt}from"./FieldsQueryParam-C-_OAeFs.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-B0jOWZIL.js";import{F as Rt}from"./FieldsQueryParam-f4jfjPs6.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-Btw6v1uV.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-B0jOWZIL.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-Btw6v1uV.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-B0jOWZIL.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-Btw6v1uV.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-B0jOWZIL.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.
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+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-Btw6v1uV.js";import{F as ul}from"./FieldsQueryParam-C-_OAeFs.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-B0jOWZIL.js";import{F as ul}from"./FieldsQueryParam-f4jfjPs6.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
File diff suppressed because one or more lines are too long
+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-Btw6v1uV.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-B0jOWZIL.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-Btw6v1uV.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-B0jOWZIL.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-Btw6v1uV.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-B0jOWZIL.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-Btw6v1uV.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-B0jOWZIL.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-Btw6v1uV.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-B0jOWZIL.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-Btw6v1uV.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-B0jOWZIL.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-Btw6v1uV.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-B0jOWZIL.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-Btw6v1uV.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-B0jOWZIL.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-Btw6v1uV.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-B0jOWZIL.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-Btw6v1uV.js";import{F as Dt}from"./FieldsQueryParam-C-_OAeFs.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-B0jOWZIL.js";import{F as Dt}from"./FieldsQueryParam-f4jfjPs6.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-Btw6v1uV.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-B0jOWZIL.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-Btw6v1uV.js";import{F as ut}from"./FieldsQueryParam-C-_OAeFs.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-B0jOWZIL.js";import{F as ut}from"./FieldsQueryParam-f4jfjPs6.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]}');
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
+14
File diff suppressed because one or more lines are too long
Vendored
-14
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -37,7 +37,7 @@
|
||||
window.Prism = window.Prism || {};
|
||||
window.Prism.manual = true;
|
||||
</script>
|
||||
<script type="module" crossorigin src="./assets/index-Btw6v1uV.js"></script>
|
||||
<script type="module" crossorigin src="./assets/index-B0jOWZIL.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="./assets/index-wnKjfGML.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
Generated
+244
-264
@@ -23,7 +23,7 @@
|
||||
"chartjs-plugin-zoom": "^2.0.1",
|
||||
"leaflet": "^1.9.4",
|
||||
"luxon": "^3.4.4",
|
||||
"pocketbase": "^0.25.1",
|
||||
"pocketbase": "^0.26.5",
|
||||
"sass": "^1.45.0",
|
||||
"svelte": "^4.0.0",
|
||||
"svelte-flatpickr": "^3.3.3",
|
||||
@@ -46,9 +46,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/autocomplete": {
|
||||
"version": "6.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.19.1.tgz",
|
||||
"integrity": "sha512-q6NenYkEy2fn9+JyjIxMWcNjzTL/IhwqfzOut1/G3PrIFkrbl4AL7Wkse5tLrQUUyqGoAKU5+Pi5jnnXxH5HGw==",
|
||||
"version": "6.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.20.0.tgz",
|
||||
"integrity": "sha512-bOwvTOIJcG5FVo5gUUupiwYh8MioPLQ4UcqbcRf7UQ98X90tCa9E1kZ3Z7tqwpZxYyOvh1YTYbmZE9RTfTp5hg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -59,9 +59,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/commands": {
|
||||
"version": "6.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.10.0.tgz",
|
||||
"integrity": "sha512-2xUIc5mHXQzT16JnyOFkh8PvfeXuIut3pslWGfsGOhxP/lpgRm9HOl/mpzLErgt5mXDovqA0d11P21gofRLb9w==",
|
||||
"version": "6.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.10.1.tgz",
|
||||
"integrity": "sha512-uWDWFypNdQmz2y1LaNJzK7fL7TYKLeUAU0npEC685OKTF3KcQ2Vu3klIM78D7I6wGhktme0lh3CuQLv0ZCrD9Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -146,15 +146,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/language": {
|
||||
"version": "6.11.3",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.11.3.tgz",
|
||||
"integrity": "sha512-9HBM2XnwDj7fnu0551HkGdrUrrqmYq/WC5iv6nbY2WdicXdGbhR/gfbZOH73Aqj4351alY1+aoG9rCNfiwS1RA==",
|
||||
"version": "6.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.12.1.tgz",
|
||||
"integrity": "sha512-Fa6xkSiuGKc8XC8Cn96T+TQHYj4ZZ7RdFmXA3i9xe/3hLHfwPZdM+dqfX0Cp0zQklBKhVD8Yzc8LS45rkqcwpQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.23.0",
|
||||
"@lezer/common": "^1.1.0",
|
||||
"@lezer/common": "^1.5.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.0.0",
|
||||
"style-mod": "^4.0.0"
|
||||
@@ -183,21 +183,21 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/search": {
|
||||
"version": "6.5.11",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.11.tgz",
|
||||
"integrity": "sha512-KmWepDE6jUdL6n8cAAqIpRmLPBZ5ZKnicE8oGU/s3QrAVID+0VhLFrzUucVKHG5035/BSykhExDL/Xm7dHthiA==",
|
||||
"version": "6.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.6.0.tgz",
|
||||
"integrity": "sha512-koFuNXcDvyyotWcgOnZGmY7LZqEOXZaaxD/j6n18TCLx2/9HieZJ5H6hs1g8FiRxBD0DNfs0nXn17g872RmYdw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.0.0",
|
||||
"@codemirror/view": "^6.37.0",
|
||||
"crelt": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/state": {
|
||||
"version": "6.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.2.tgz",
|
||||
"integrity": "sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==",
|
||||
"version": "6.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.4.tgz",
|
||||
"integrity": "sha512-8y7xqG/hpB53l25CIoit9/ngxdfoG+fx+V3SHBrinnhOtLvKHRyAJJuHzkWrR4YXXLX8eXBsejgAAxHUOdW1yw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -205,9 +205,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/view": {
|
||||
"version": "6.38.6",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.38.6.tgz",
|
||||
"integrity": "sha512-qiS0z1bKs5WOvHIAC0Cybmv4AJSkAXgX5aD6Mqd2epSLlVJsQl8NG23jCVouIgkh4All/mrbdsf2UOLFnJw0tw==",
|
||||
"version": "6.39.11",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.39.11.tgz",
|
||||
"integrity": "sha512-bWdeR8gWM87l4DB/kYSF9A+dVackzDb/V56Tq7QVrQ7rn86W0rgZFtlL3g3pem6AeGcb9NQNoy3ao4WpW4h5tQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -655,9 +655,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@lezer/common": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.3.0.tgz",
|
||||
"integrity": "sha512-L9X8uHCYU310o99L3/MpJKYxPzXPOS7S0NmBaM7UO/x2Kb2WbmMLSkfvdr1KxRIFYOpbY0Jhn7CfLSUDzL8arQ==",
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.5.0.tgz",
|
||||
"integrity": "sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -684,9 +684,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/html": {
|
||||
"version": "1.3.12",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.12.tgz",
|
||||
"integrity": "sha512-RJ7eRWdaJe3bsiiLLHjCFT1JMk8m1YP9kaUbvu2rMLEoOnke9mcTVDyfOslsln0LtujdWespjJ39w6zo+RsQYw==",
|
||||
"version": "1.3.13",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.13.tgz",
|
||||
"integrity": "sha512-oI7n6NJml729m7pjm9lvLvmXbdoMoi2f+1pwSDJkl9d68zGr7a9Btz8NdHTGQZtW2DA25ybeuv/SyDb9D5tseg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -720,9 +720,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/lr": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.3.tgz",
|
||||
"integrity": "sha512-yenN5SqAxAPv/qMnpWW0AT7l+SxVrgG+u0tNsRQWqbrz66HIl8DnEbBObvy21J5K7+I1v7gsAnlE2VQ5yYVSeA==",
|
||||
"version": "1.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.7.tgz",
|
||||
"integrity": "sha512-wNIFWdSUfX9Jc6ePMzxSPVgTVB4EOfDIwLQLWASyiUdHKaMsiilj9bYiGkGQCKVodd0x6bgQCV207PILGFCF9Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -737,18 +737,18 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@parcel/watcher": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz",
|
||||
"integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==",
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.4.tgz",
|
||||
"integrity": "sha512-WYa2tUVV5HiArWPB3ydlOc4R2ivq0IDrlqhMi3l7mVsFEXNcTfxYFPIHXHXIh/ca/y/V5N4E1zecyxdIBjYnkQ==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"detect-libc": "^1.0.3",
|
||||
"detect-libc": "^2.0.3",
|
||||
"is-glob": "^4.0.3",
|
||||
"micromatch": "^4.0.5",
|
||||
"node-addon-api": "^7.0.0"
|
||||
"node-addon-api": "^7.0.0",
|
||||
"picomatch": "^4.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
@@ -758,25 +758,25 @@
|
||||
"url": "https://opencollective.com/parcel"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@parcel/watcher-android-arm64": "2.5.1",
|
||||
"@parcel/watcher-darwin-arm64": "2.5.1",
|
||||
"@parcel/watcher-darwin-x64": "2.5.1",
|
||||
"@parcel/watcher-freebsd-x64": "2.5.1",
|
||||
"@parcel/watcher-linux-arm-glibc": "2.5.1",
|
||||
"@parcel/watcher-linux-arm-musl": "2.5.1",
|
||||
"@parcel/watcher-linux-arm64-glibc": "2.5.1",
|
||||
"@parcel/watcher-linux-arm64-musl": "2.5.1",
|
||||
"@parcel/watcher-linux-x64-glibc": "2.5.1",
|
||||
"@parcel/watcher-linux-x64-musl": "2.5.1",
|
||||
"@parcel/watcher-win32-arm64": "2.5.1",
|
||||
"@parcel/watcher-win32-ia32": "2.5.1",
|
||||
"@parcel/watcher-win32-x64": "2.5.1"
|
||||
"@parcel/watcher-android-arm64": "2.5.4",
|
||||
"@parcel/watcher-darwin-arm64": "2.5.4",
|
||||
"@parcel/watcher-darwin-x64": "2.5.4",
|
||||
"@parcel/watcher-freebsd-x64": "2.5.4",
|
||||
"@parcel/watcher-linux-arm-glibc": "2.5.4",
|
||||
"@parcel/watcher-linux-arm-musl": "2.5.4",
|
||||
"@parcel/watcher-linux-arm64-glibc": "2.5.4",
|
||||
"@parcel/watcher-linux-arm64-musl": "2.5.4",
|
||||
"@parcel/watcher-linux-x64-glibc": "2.5.4",
|
||||
"@parcel/watcher-linux-x64-musl": "2.5.4",
|
||||
"@parcel/watcher-win32-arm64": "2.5.4",
|
||||
"@parcel/watcher-win32-ia32": "2.5.4",
|
||||
"@parcel/watcher-win32-x64": "2.5.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-android-arm64": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz",
|
||||
"integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==",
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.4.tgz",
|
||||
"integrity": "sha512-hoh0vx4v+b3BNI7Cjoy2/B0ARqcwVNrzN/n7DLq9ZB4I3lrsvhrkCViJyfTj/Qi5xM9YFiH4AmHGK6pgH1ss7g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -795,9 +795,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-darwin-arm64": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz",
|
||||
"integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==",
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.4.tgz",
|
||||
"integrity": "sha512-kphKy377pZiWpAOyTgQYPE5/XEKVMaj6VUjKT5VkNyUJlr2qZAn8gIc7CPzx+kbhvqHDT9d7EqdOqRXT6vk0zw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -816,9 +816,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-darwin-x64": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz",
|
||||
"integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==",
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.4.tgz",
|
||||
"integrity": "sha512-UKaQFhCtNJW1A9YyVz3Ju7ydf6QgrpNQfRZ35wNKUhTQ3dxJ/3MULXN5JN/0Z80V/KUBDGa3RZaKq1EQT2a2gg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -837,9 +837,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-freebsd-x64": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz",
|
||||
"integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==",
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.4.tgz",
|
||||
"integrity": "sha512-Dib0Wv3Ow/m2/ttvLdeI2DBXloO7t3Z0oCp4bAb2aqyqOjKPPGrg10pMJJAQ7tt8P4V2rwYwywkDhUia/FgS+Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -858,9 +858,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-arm-glibc": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz",
|
||||
"integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==",
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.4.tgz",
|
||||
"integrity": "sha512-I5Vb769pdf7Q7Sf4KNy8Pogl/URRCKu9ImMmnVKYayhynuyGYMzuI4UOWnegQNa2sGpsPSbzDsqbHNMyeyPCgw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -879,9 +879,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-arm-musl": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz",
|
||||
"integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==",
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.4.tgz",
|
||||
"integrity": "sha512-kGO8RPvVrcAotV4QcWh8kZuHr9bXi9a3bSZw7kFarYR0+fGliU7hd/zevhjw8fnvIKG3J9EO5G6sXNGCSNMYPQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -900,9 +900,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-arm64-glibc": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz",
|
||||
"integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==",
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.4.tgz",
|
||||
"integrity": "sha512-KU75aooXhqGFY2W5/p8DYYHt4hrjHZod8AhcGAmhzPn/etTa+lYCDB2b1sJy3sWJ8ahFVTdy+EbqSBvMx3iFlw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -921,9 +921,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-arm64-musl": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz",
|
||||
"integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==",
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.4.tgz",
|
||||
"integrity": "sha512-Qx8uNiIekVutnzbVdrgSanM+cbpDD3boB1f8vMtnuG5Zau4/bdDbXyKwIn0ToqFhIuob73bcxV9NwRm04/hzHQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -942,9 +942,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-x64-glibc": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz",
|
||||
"integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==",
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.4.tgz",
|
||||
"integrity": "sha512-UYBQvhYmgAv61LNUn24qGQdjtycFBKSK3EXr72DbJqX9aaLbtCOO8+1SkKhD/GNiJ97ExgcHBrukcYhVjrnogA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -963,9 +963,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-x64-musl": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz",
|
||||
"integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==",
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.4.tgz",
|
||||
"integrity": "sha512-YoRWCVgxv8akZrMhdyVi6/TyoeeMkQ0PGGOf2E4omODrvd1wxniXP+DBynKoHryStks7l+fDAMUBRzqNHrVOpg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -984,9 +984,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-win32-arm64": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz",
|
||||
"integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==",
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.4.tgz",
|
||||
"integrity": "sha512-iby+D/YNXWkiQNYcIhg8P5hSjzXEHaQrk2SLrWOUD7VeC4Ohu0WQvmV+HDJokZVJ2UjJ4AGXW3bx7Lls9Ln4TQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -1005,9 +1005,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-win32-ia32": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz",
|
||||
"integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==",
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.4.tgz",
|
||||
"integrity": "sha512-vQN+KIReG0a2ZDpVv8cgddlf67J8hk1WfZMMP7sMeZmJRSmEax5xNDNWKdgqSe2brOKTQQAs3aCCUal2qBHAyg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@@ -1026,9 +1026,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-win32-x64": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz",
|
||||
"integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==",
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.4.tgz",
|
||||
"integrity": "sha512-3A6efb6BOKwyw7yk9ro2vus2YTt2nvcd56AuzxdMiVOxL9umDyN5PKkKfZ/gZ9row41SjVmTVQNWQhaRRGpOKw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -1047,9 +1047,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.53.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.1.tgz",
|
||||
"integrity": "sha512-bxZtughE4VNVJlL1RdoSE545kc4JxL7op57KKoi59/gwuU5rV6jLWFXXc8jwgFoT6vtj+ZjO+Z2C5nrY0Cl6wA==",
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.55.1.tgz",
|
||||
"integrity": "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -1061,9 +1061,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm64": {
|
||||
"version": "4.53.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.1.tgz",
|
||||
"integrity": "sha512-44a1hreb02cAAfAKmZfXVercPFaDjqXCK+iKeVOlJ9ltvnO6QqsBHgKVPTu+MJHSLLeMEUbeG2qiDYgbFPU48g==",
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.55.1.tgz",
|
||||
"integrity": "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -1075,9 +1075,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.53.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.1.tgz",
|
||||
"integrity": "sha512-usmzIgD0rf1syoOZ2WZvy8YpXK5G1V3btm3QZddoGSa6mOgfXWkkv+642bfUUldomgrbiLQGrPryb7DXLovPWQ==",
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.55.1.tgz",
|
||||
"integrity": "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -1089,9 +1089,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.53.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.1.tgz",
|
||||
"integrity": "sha512-is3r/k4vig2Gt8mKtTlzzyaSQ+hd87kDxiN3uDSDwggJLUV56Umli6OoL+/YZa/KvtdrdyNfMKHzL/P4siOOmg==",
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.55.1.tgz",
|
||||
"integrity": "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -1103,9 +1103,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||
"version": "4.53.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.1.tgz",
|
||||
"integrity": "sha512-QJ1ksgp/bDJkZB4daldVmHaEQkG4r8PUXitCOC2WRmRaSaHx5RwPoI3DHVfXKwDkB+Sk6auFI/+JHacTekPRSw==",
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.55.1.tgz",
|
||||
"integrity": "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -1117,9 +1117,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||
"version": "4.53.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.1.tgz",
|
||||
"integrity": "sha512-J6ma5xgAzvqsnU6a0+jgGX/gvoGokqpkx6zY4cWizRrm0ffhHDpJKQgC8dtDb3+MqfZDIqs64REbfHDMzxLMqQ==",
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.55.1.tgz",
|
||||
"integrity": "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -1131,9 +1131,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.53.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.1.tgz",
|
||||
"integrity": "sha512-JzWRR41o2U3/KMNKRuZNsDUAcAVUYhsPuMlx5RUldw0E4lvSIXFUwejtYz1HJXohUmqs/M6BBJAUBzKXZVddbg==",
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.55.1.tgz",
|
||||
"integrity": "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -1145,9 +1145,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||
"version": "4.53.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.1.tgz",
|
||||
"integrity": "sha512-L8kRIrnfMrEoHLHtHn+4uYA52fiLDEDyezgxZtGUTiII/yb04Krq+vk3P2Try+Vya9LeCE9ZHU8CXD6J9EhzHQ==",
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.55.1.tgz",
|
||||
"integrity": "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -1159,9 +1159,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.53.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.1.tgz",
|
||||
"integrity": "sha512-ysAc0MFRV+WtQ8li8hi3EoFi7us6d1UzaS/+Dp7FYZfg3NdDljGMoVyiIp6Ucz7uhlYDBZ/zt6XI0YEZbUO11Q==",
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.55.1.tgz",
|
||||
"integrity": "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -1173,9 +1173,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.53.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.1.tgz",
|
||||
"integrity": "sha512-UV6l9MJpDbDZZ/fJvqNcvO1PcivGEf1AvKuTcHoLjVZVFeAMygnamCTDikCVMRnA+qJe+B3pSbgX2+lBMqgBhA==",
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.55.1.tgz",
|
||||
"integrity": "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -1187,9 +1187,23 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-loong64-gnu": {
|
||||
"version": "4.53.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.1.tgz",
|
||||
"integrity": "sha512-UDUtelEprkA85g95Q+nj3Xf0M4hHa4DiJ+3P3h4BuGliY4NReYYqwlc0Y8ICLjN4+uIgCEvaygYlpf0hUj90Yg==",
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.55.1.tgz",
|
||||
"integrity": "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-loong64-musl": {
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.55.1.tgz",
|
||||
"integrity": "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
@@ -1201,9 +1215,23 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
|
||||
"version": "4.53.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.1.tgz",
|
||||
"integrity": "sha512-vrRn+BYhEtNOte/zbc2wAUQReJXxEx2URfTol6OEfY2zFEUK92pkFBSXRylDM7aHi+YqEPJt9/ABYzmcrS4SgQ==",
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.55.1.tgz",
|
||||
"integrity": "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-ppc64-musl": {
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.55.1.tgz",
|
||||
"integrity": "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
@@ -1215,9 +1243,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||
"version": "4.53.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.1.tgz",
|
||||
"integrity": "sha512-gto/1CxHyi4A7YqZZNznQYrVlPSaodOBPKM+6xcDSCMVZN/Fzb4K+AIkNz/1yAYz9h3Ng+e2fY9H6bgawVq17w==",
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.55.1.tgz",
|
||||
"integrity": "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
@@ -1229,9 +1257,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-musl": {
|
||||
"version": "4.53.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.1.tgz",
|
||||
"integrity": "sha512-KZ6Vx7jAw3aLNjFR8eYVcQVdFa/cvBzDNRFM3z7XhNNunWjA03eUrEwJYPk0G8V7Gs08IThFKcAPS4WY/ybIrQ==",
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.55.1.tgz",
|
||||
"integrity": "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
@@ -1243,9 +1271,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||
"version": "4.53.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.1.tgz",
|
||||
"integrity": "sha512-HvEixy2s/rWNgpwyKpXJcHmE7om1M89hxBTBi9Fs6zVuLU4gOrEMQNbNsN/tBVIMbLyysz/iwNiGtMOpLAOlvA==",
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.55.1.tgz",
|
||||
"integrity": "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
@@ -1257,9 +1285,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.53.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.1.tgz",
|
||||
"integrity": "sha512-E/n8x2MSjAQgjj9IixO4UeEUeqXLtiA7pyoXCFYLuXpBA/t2hnbIdxHfA7kK9BFsYAoNU4st1rHYdldl8dTqGA==",
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.55.1.tgz",
|
||||
"integrity": "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -1271,9 +1299,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.53.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.1.tgz",
|
||||
"integrity": "sha512-IhJ087PbLOQXCN6Ui/3FUkI9pWNZe/Z7rEIVOzMsOs1/HSAECCvSZ7PkIbkNqL/AZn6WbZvnoVZw/qwqYMo4/w==",
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.55.1.tgz",
|
||||
"integrity": "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -1284,10 +1312,24 @@
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-openbsd-x64": {
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.55.1.tgz",
|
||||
"integrity": "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-openharmony-arm64": {
|
||||
"version": "4.53.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.1.tgz",
|
||||
"integrity": "sha512-0++oPNgLJHBblreu0SFM7b3mAsBJBTY0Ksrmu9N6ZVrPiTkRgda52mWR7TKhHAsUb9noCjFvAw9l6ZO1yzaVbA==",
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.55.1.tgz",
|
||||
"integrity": "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -1299,9 +1341,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.53.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.1.tgz",
|
||||
"integrity": "sha512-VJXivz61c5uVdbmitLkDlbcTk9Or43YC2QVLRkqp86QoeFSqI81bNgjhttqhKNMKnQMWnecOCm7lZz4s+WLGpQ==",
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.55.1.tgz",
|
||||
"integrity": "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -1313,9 +1355,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.53.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.1.tgz",
|
||||
"integrity": "sha512-NmZPVTUOitCXUH6erJDzTQ/jotYw4CnkMDjCYRxNHVD9bNyfrGoIse684F9okwzKCV4AIHRbUkeTBc9F2OOH5Q==",
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.55.1.tgz",
|
||||
"integrity": "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@@ -1327,9 +1369,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-gnu": {
|
||||
"version": "4.53.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.1.tgz",
|
||||
"integrity": "sha512-2SNj7COIdAf6yliSpLdLG8BEsp5lgzRehgfkP0Av8zKfQFKku6JcvbobvHASPJu4f3BFxej5g+HuQPvqPhHvpQ==",
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.55.1.tgz",
|
||||
"integrity": "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -1341,9 +1383,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.53.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.1.tgz",
|
||||
"integrity": "sha512-rLarc1Ofcs3DHtgSzFO31pZsCh8g05R2azN1q3fF+H423Co87My0R+tazOEvYVKXSLh8C4LerMK41/K7wlklcg==",
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.1.tgz",
|
||||
"integrity": "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -1360,6 +1402,7 @@
|
||||
"integrity": "sha512-Txsm1tJvtiYeLUVRNqxZGKR/mI+CzuIQuc2gn+YCs9rMTowpNZ2Nqt53JdL8KF9bLhAf2ruR/dr9eZCwdTriRA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@sveltejs/vite-plugin-svelte-inspector": "^2.1.0",
|
||||
"debug": "^4.3.4",
|
||||
@@ -1442,26 +1485,13 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/braces": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"fill-range": "^7.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/chart.js": {
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.1.tgz",
|
||||
"integrity": "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@kurkle/color": "^0.3.0"
|
||||
},
|
||||
@@ -1574,17 +1604,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
|
||||
"integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
||||
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"bin": {
|
||||
"detect-libc": "bin/detect-libc.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
@@ -1636,20 +1663,6 @@
|
||||
"@types/estree": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/flatpickr": {
|
||||
"version": "4.6.13",
|
||||
"resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.13.tgz",
|
||||
@@ -1714,17 +1727,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-reference": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz",
|
||||
@@ -1765,6 +1767,7 @@
|
||||
"integrity": "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
@@ -1786,21 +1789,6 @@
|
||||
"dev": true,
|
||||
"license": "CC0-1.0"
|
||||
},
|
||||
"node_modules/micromatch": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
||||
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"braces": "^3.0.3",
|
||||
"picomatch": "^2.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
@@ -1855,23 +1843,23 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/pocketbase": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/pocketbase/-/pocketbase-0.25.2.tgz",
|
||||
"integrity": "sha512-ONZl1+qHJMnhR2uacBlBJ90lm7njtL/zy0606+1ROfK9hSL4LRBRc8r89rMcNRzPzRqCNyoFTh2Qg/lYXdEC1w==",
|
||||
"version": "0.26.6",
|
||||
"resolved": "https://registry.npmjs.org/pocketbase/-/pocketbase-0.26.6.tgz",
|
||||
"integrity": "sha512-Pl7V4y3DWglYITC4cBpclmuIzePRGsb/sXk/Wyqxznwu5JsHA5IILJY81PT2XQ3OSKCakWjbxjYBqtdcghzKvA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -1929,9 +1917,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "4.53.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.1.tgz",
|
||||
"integrity": "sha512-n2I0V0lN3E9cxxMqBCT3opWOiQBzRN7UG60z/WDKqdX2zHUS/39lezBcsckZFsV6fUTSnfqI7kHf60jDAPGKug==",
|
||||
"version": "4.55.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.55.1.tgz",
|
||||
"integrity": "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -1945,37 +1933,41 @@
|
||||
"npm": ">=8.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-android-arm-eabi": "4.53.1",
|
||||
"@rollup/rollup-android-arm64": "4.53.1",
|
||||
"@rollup/rollup-darwin-arm64": "4.53.1",
|
||||
"@rollup/rollup-darwin-x64": "4.53.1",
|
||||
"@rollup/rollup-freebsd-arm64": "4.53.1",
|
||||
"@rollup/rollup-freebsd-x64": "4.53.1",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.53.1",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.53.1",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.53.1",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.53.1",
|
||||
"@rollup/rollup-linux-loong64-gnu": "4.53.1",
|
||||
"@rollup/rollup-linux-ppc64-gnu": "4.53.1",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.53.1",
|
||||
"@rollup/rollup-linux-riscv64-musl": "4.53.1",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.53.1",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.53.1",
|
||||
"@rollup/rollup-linux-x64-musl": "4.53.1",
|
||||
"@rollup/rollup-openharmony-arm64": "4.53.1",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.53.1",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.53.1",
|
||||
"@rollup/rollup-win32-x64-gnu": "4.53.1",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.53.1",
|
||||
"@rollup/rollup-android-arm-eabi": "4.55.1",
|
||||
"@rollup/rollup-android-arm64": "4.55.1",
|
||||
"@rollup/rollup-darwin-arm64": "4.55.1",
|
||||
"@rollup/rollup-darwin-x64": "4.55.1",
|
||||
"@rollup/rollup-freebsd-arm64": "4.55.1",
|
||||
"@rollup/rollup-freebsd-x64": "4.55.1",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.55.1",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.55.1",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.55.1",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.55.1",
|
||||
"@rollup/rollup-linux-loong64-gnu": "4.55.1",
|
||||
"@rollup/rollup-linux-loong64-musl": "4.55.1",
|
||||
"@rollup/rollup-linux-ppc64-gnu": "4.55.1",
|
||||
"@rollup/rollup-linux-ppc64-musl": "4.55.1",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.55.1",
|
||||
"@rollup/rollup-linux-riscv64-musl": "4.55.1",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.55.1",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.55.1",
|
||||
"@rollup/rollup-linux-x64-musl": "4.55.1",
|
||||
"@rollup/rollup-openbsd-x64": "4.55.1",
|
||||
"@rollup/rollup-openharmony-arm64": "4.55.1",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.55.1",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.55.1",
|
||||
"@rollup/rollup-win32-x64-gnu": "4.55.1",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.55.1",
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/sass": {
|
||||
"version": "1.93.3",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.93.3.tgz",
|
||||
"integrity": "sha512-elOcIZRTM76dvxNAjqYrucTSI0teAF/L2Lv0s6f6b7FOwcwIuA357bIE871580AjHJuSvLIRUosgV+lIWx6Rgg==",
|
||||
"version": "1.97.2",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.97.2.tgz",
|
||||
"integrity": "sha512-y5LWb0IlbO4e97Zr7c3mlpabcbBtS+ieiZ9iwDooShpFKWXf62zz5pEPdwrLYm+Bxn1fnbwFGzHuCLSA9tBmrw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"chokidar": "^4.0.0",
|
||||
"immutable": "^5.0.2",
|
||||
@@ -2014,6 +2006,7 @@
|
||||
"integrity": "sha512-eeEgGc2DtiUil5ANdtd8vPwt9AgaMdnuUFnPft9F5oMvU/FHu5IHFic+p1dR/UOB7XU2mX2yHW+NcTch4DCh5Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.2.1",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.15",
|
||||
@@ -2073,26 +2066,13 @@
|
||||
"url": "https://github.com/sponsors/ItalyPaleAle"
|
||||
}
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "5.4.21",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz",
|
||||
"integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.21.3",
|
||||
"postcss": "^8.4.43",
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@
|
||||
"chartjs-plugin-zoom": "^2.0.1",
|
||||
"leaflet": "^1.9.4",
|
||||
"luxon": "^3.4.4",
|
||||
"pocketbase": "^0.25.1",
|
||||
"pocketbase": "^0.26.5",
|
||||
"sass": "^1.45.0",
|
||||
"svelte": "^4.0.0",
|
||||
"svelte-flatpickr": "^3.3.3",
|
||||
|
||||
@@ -244,7 +244,7 @@
|
||||
|
||||
// Returns object with all the completions matching the context.
|
||||
function completions(context) {
|
||||
let word = context.matchBefore(/[\'\"\@\w\.]*/);
|
||||
let word = context.matchBefore(/[\'\"\@\w\.\:]*/);
|
||||
if (word && word.from == word.to && !context.explicit) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
$: authAlertTemplate = {
|
||||
key: "authAlert.emailTemplate",
|
||||
label: "Default Login alert email template",
|
||||
placeholders: ["APP_NAME", "APP_URL", "RECORD:*"],
|
||||
placeholders: ["APP_NAME", "APP_URL", "RECORD:*", "ALERT_INFO"],
|
||||
config: collection.authAlert.emailTemplate,
|
||||
};
|
||||
$: emailTemplatesList = isSuperusers
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
if (!old) {
|
||||
return false;
|
||||
}
|
||||
return old.maxSelect != 1 && field.maxSelect == 1;
|
||||
return old.maxSelect > 1 && field.maxSelect <= 1;
|
||||
}) || [];
|
||||
|
||||
$: showChanges = !isNewCollectionView || isCollectionRenamed || changedRules.length;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import CommonHelper from "@/utils/CommonHelper";
|
||||
import { confirm } from "@/stores/confirmation";
|
||||
import { errors, removeError, setErrors } from "@/stores/errors";
|
||||
import { addSuccessToast, removeAllToasts } from "@/stores/toasts";
|
||||
import { addInfoToast, addSuccessToast, removeAllToasts } from "@/stores/toasts";
|
||||
import {
|
||||
addCollection,
|
||||
removeCollection,
|
||||
@@ -346,6 +346,11 @@
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function copyJSON() {
|
||||
CommonHelper.copyToClipboard(JSON.stringify(original, null, 2));
|
||||
addInfoToast("The collection JSON was copied to your clipboard!", 3000);
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
|
||||
@@ -382,7 +387,16 @@
|
||||
class="btn btn-sm btn-circle btn-transparent flex-gap-0"
|
||||
>
|
||||
<i class="ri-more-line" aria-hidden="true" />
|
||||
<Toggler class="dropdown dropdown-right m-t-5">
|
||||
<Toggler class="dropdown dropdown-right dropdown-nowrap">
|
||||
<button
|
||||
type="button"
|
||||
class="dropdown-item closable"
|
||||
role="menuitem"
|
||||
on:click={() => copyJSON()}
|
||||
>
|
||||
<i class="ri-braces-line" aria-hidden="true" />
|
||||
<span class="txt">Copy raw JSON</span>
|
||||
</button>
|
||||
{#if !collection.system}
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
{#if field.primaryKey}
|
||||
<i
|
||||
class="ri-information-line link-hint"
|
||||
use:tooltip={"All record ids have unique case-insensitive (ASCII) validation applied in addition to the user defined validation pattern."}
|
||||
use:tooltip={"All record ids have forbidden characters and unique case-insensitive (ASCII) validations in addition to the user defined regex pattern."}
|
||||
/>
|
||||
{/if}
|
||||
</label>
|
||||
|
||||
@@ -134,7 +134,7 @@
|
||||
const result = await ApiClient.collection(selectedCollection.id).getList(page, batchSize, {
|
||||
filter: normalizedFilter,
|
||||
sort: sort,
|
||||
fields: "*:excerpt(100)",
|
||||
fields: CommonHelper.getExcerptCollectionFieldsList(selectedCollection),
|
||||
skipTotal: 1,
|
||||
requestKey: uniqueId + "loadImagePicker",
|
||||
});
|
||||
|
||||
@@ -148,6 +148,7 @@
|
||||
|
||||
const listFields = editorFields
|
||||
.map((f) => f.name + ":excerpt(200)")
|
||||
// @todo exclude id and single rel fields from the excerpt list
|
||||
.concat(relFields.map((field) => "expand." + field.name + ".*:excerpt(200)"));
|
||||
if (listFields.length) {
|
||||
listFields.unshift("*");
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
let isLoadingSelected = false;
|
||||
let isReloadingRecord = {};
|
||||
|
||||
$: maxSelect = field?.maxSelect || null;
|
||||
$: maxSelect = field?.maxSelect || 1;
|
||||
|
||||
$: collectionId = field?.collectionId;
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
$: canLoadMore = lastItemsCount == batchSize;
|
||||
|
||||
$: canSelectMore = maxSelect <= 0 || maxSelect > selected.length;
|
||||
$: canSelectMore = maxSelect > selected.length;
|
||||
|
||||
export function show() {
|
||||
filter = "";
|
||||
@@ -98,7 +98,7 @@
|
||||
ApiClient.collection(collectionId).getFullList({
|
||||
batch: batchSize,
|
||||
filter: filters.join("||"),
|
||||
fields: "*:excerpt(200)",
|
||||
fields: CommonHelper.getExcerptCollectionFieldsList(collection),
|
||||
expand: getExpand(),
|
||||
requestKey: null,
|
||||
}),
|
||||
@@ -162,7 +162,7 @@
|
||||
const result = await ApiClient.collection(collectionId).getList(page, batchSize, {
|
||||
filter: CommonHelper.normalizeSearchFilter(filter, fallbackSearchFields),
|
||||
sort: sort,
|
||||
fields: "*:excerpt(200)",
|
||||
fields: CommonHelper.getExcerptCollectionFieldsList(collection),
|
||||
skipTotal: 1,
|
||||
expand: getExpand(),
|
||||
requestKey: uniqueId + "loadList",
|
||||
@@ -190,7 +190,7 @@
|
||||
|
||||
try {
|
||||
const reloaded = await ApiClient.collection(collectionId).getOne(record.id, {
|
||||
fields: "*:excerpt(200)",
|
||||
fields: CommonHelper.getExcerptCollectionFieldsList(collection),
|
||||
expand: getExpand(),
|
||||
requestKey: uniqueId + "reload" + record.id,
|
||||
});
|
||||
|
||||
@@ -64,10 +64,12 @@
|
||||
|
||||
isLoading = true;
|
||||
|
||||
const fieldCollection = $collections.find((c) => c.id == field.collectionId);
|
||||
|
||||
let expands = [];
|
||||
const presentableRelFields = $collections
|
||||
.find((c) => c.id == field.collectionId)
|
||||
?.fields?.filter((f) => !f.hidden && f.presentable && f.type == "relation");
|
||||
const presentableRelFields = fieldCollection?.fields?.filter(
|
||||
(f) => !f.hidden && f.presentable && f.type == "relation",
|
||||
);
|
||||
for (const field of presentableRelFields) {
|
||||
expands = expands.concat(CommonHelper.getExpandPresentableRelFields(field, $collections, 2));
|
||||
}
|
||||
@@ -84,7 +86,7 @@
|
||||
loadPromises.push(
|
||||
ApiClient.collection(field.collectionId).getFullList(batchSize, {
|
||||
filter: filters.join("||"),
|
||||
fields: "*:excerpt(200)",
|
||||
fields: CommonHelper.getExcerptCollectionFieldsList(fieldCollection),
|
||||
expand: expands.join(","),
|
||||
requestKey: null,
|
||||
}),
|
||||
|
||||
@@ -88,13 +88,20 @@
|
||||
the backup and will restart the application process.
|
||||
</p>
|
||||
<p>
|
||||
This means that on success all of your data (including app settings, users, superusers, etc.) will
|
||||
be replaced with the ones from the backup.
|
||||
This means that on success all of your data (including app settings, users, superusers, etc.)
|
||||
will be replaced with the ones from the backup.
|
||||
</p>
|
||||
<p>
|
||||
Nothing will happen if the backup is invalid or incompatible (ex. missing
|
||||
Nothing will happen if the backup is invalid (ex. missing
|
||||
<code>data.db</code> file).
|
||||
</p>
|
||||
<p>Below is an oversimplified version of the restore flow:</p>
|
||||
<ol>
|
||||
<li>Replaces the current <code>pb_data</code> with the content from the backup</li>
|
||||
<li>Triggers app restart</li>
|
||||
<li>Applies all migrations that are missing in the restored <code>pb_data</code></li>
|
||||
<li>Initializes the app server as usual</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -81,7 +81,6 @@
|
||||
|
||||
try {
|
||||
await ApiClient.backups.delete(name);
|
||||
CommonHelper.removeByKey(backups, "name", name);
|
||||
loadBackups();
|
||||
addSuccessToast(`Successfully deleted ${name}.`);
|
||||
} catch (err) {
|
||||
|
||||
@@ -1774,7 +1774,7 @@ export default class CommonHelper {
|
||||
/**
|
||||
* Returns an array with all public collection identifiers (collection fields + type specific fields).
|
||||
*
|
||||
* @param {[type]} collection The collection to extract identifiers from.
|
||||
* @param {Object} collection The collection to extract identifiers from.
|
||||
* @param {String} prefix Optional prefix for each found identified.
|
||||
* @return {Array}
|
||||
*/
|
||||
@@ -1804,6 +1804,30 @@ export default class CommonHelper {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a wildcard "fields" string with the excerpt modifier applied to all collection fields
|
||||
* (except the primary key and relation fields).
|
||||
*
|
||||
* @param {Object} collection
|
||||
* @param {Number} [maxExcerpt]
|
||||
* @return {String}
|
||||
*/
|
||||
static getExcerptCollectionFieldsList(collection, maxExcerpt = 200) {
|
||||
let result = ["*"];
|
||||
|
||||
const fields = collection?.fields || [];
|
||||
for (const field of fields) {
|
||||
if (field.primaryKey || field.type == "relation") {
|
||||
continue
|
||||
}
|
||||
|
||||
result.push(`${field.name}:excerpt(${maxExcerpt})`);
|
||||
}
|
||||
|
||||
return result.join(",");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates recursively a list with all the autocomplete field keys
|
||||
* for the collectionNameOrId collection.
|
||||
@@ -1923,13 +1947,14 @@ export default class CommonHelper {
|
||||
for (const key of keys) {
|
||||
result.push(key);
|
||||
|
||||
// add ":isset" modifier to non-base keys
|
||||
// add ":isset"/":changed" modifier to non-base keys
|
||||
const parts = key.split(".");
|
||||
if (
|
||||
parts.length === 3 &&
|
||||
// doesn't contain another modifier
|
||||
parts[2].indexOf(":") === -1
|
||||
) {
|
||||
result.push(key + ":changed");
|
||||
result.push(key + ":isset");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user