diff --git a/CHANGELOG.md b/CHANGELOG.md index c001b79e67..8ea9a2ff2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,25 @@ +## v0.40.3 + +- Write the status header for JSON responses only if the fields picker succeed or has acceptable fallback. + _This is to allow custom response status code for failed json writes._ + +- Fixed collection index validator to allow expressions with parenthesis in the optional `WHERE` clause. + +- Clamped arccosine to [-1,1] in the Harvesine formula for the `geoDistance()` filter function to workaround edge case related to float rounding errors for some coordinates. + +- Prevent unnecessary body chunk read if we already known that we are beyond the allowed limit. + +- Updated the `json` field validator to check the `encoding/json/v2` semantics and allow duplicated keys on record marshalize for compliance with old jsonv1 data. + +- Fixed nested cascade delete of self-referenced relation records. + +- Minor UI fixes (updated dark primary btn color contrast, force reload the records list if the deleted record has self-referenced cascade relation field, etc.). + +- Changed JSVM `$app` variable definition from TS type to interface ([#7834](https://github.com/pocketbase/pocketbase/issues/7834)). + +- Bumped `golang.org/x/*` dependencies to silence security scanners ([#7829](https://github.com/pocketbase/pocketbase/discussions/7829)). + + ## v0.40.2 - Return an error when filter params fallback fails to json serialize and optimized params replacement to execute in a single pass. diff --git a/CHANGELOG_16_22.md b/CHANGELOG_16_22.md index 90f3396c8e..12090fea45 100644 --- a/CHANGELOG_16_22.md +++ b/CHANGELOG_16_22.md @@ -2,6 +2,15 @@ > For the most recent versions, please refer to [CHANGELOG.md](./CHANGELOG.md) --- +## v0.22.55 + +- (_Backported from v0.40.3_) Fixed collection index validator to allow expressions with parenthesis in the optional `WHERE` clause. + +- (_Backported from v0.40.3_) Fixed nested cascade delete of self-referenced relation records. + +- (_Backported from v0.40.3_) Bumped `golang.org/x/*` dependencies to silence security scanners ([#7829](https://github.com/pocketbase/pocketbase/discussions/7829)). + + ## v0.22.54 - (_Backported from v0.40.2_) Bumped goja and its related dependencies _(regex unescaped dash error fix and base64 optimizations)_. diff --git a/apis/health.go b/apis/health.go index aa438070f5..1d512796c7 100644 --- a/apis/health.go +++ b/apis/health.go @@ -37,7 +37,7 @@ func healthCheck(e *core.RequestEvent) error { headersToCheck := append( slices.Clone(e.App.Settings().TrustedProxy.Headers), // common proxy headers - "CF-Connecting-IP", "Fly-Client-IP", "X‑Forwarded-For", + "CF-Connecting-IP", "Fly-Client-IP", "X-Forwarded-For", ) for _, header := range headersToCheck { if e.Request.Header.Get(header) != "" { diff --git a/apis/middlewares_body_limit.go b/apis/middlewares_body_limit.go index b02f0f65f9..1c456156b3 100644 --- a/apis/middlewares_body_limit.go +++ b/apis/middlewares_body_limit.go @@ -84,49 +84,73 @@ func applyBodyLimit(e *core.RequestEvent, limitBytes int64) error { } // replace the request body - // - // note: we don't use sync.Pool since the size of the elements could vary too much - // and it might not be efficient (see https://github.com/golang/go/issues/23199) - e.Request.Body = &limitedReader{ReadCloser: e.Request.Body, limit: limitBytes} + e.Request.Body = newMaxBytesReader(e.Request.Body, limitBytes) return nil } -type limitedReader struct { +func newMaxBytesReader(body io.ReadCloser, limitBytes int64) *maxBytesReader { + return &maxBytesReader{ + ReadCloser: body, + limit: limitBytes, + remaining: limitBytes, + } +} + +// maxBytesReader is very similar to the http.MaxBytesReader but support +// rereads and doesn't try to prematurely close the related response +// to allow consequent middlewares to operate correctly. +type maxBytesReader struct { io.ReadCloser limit int64 - totalRead int64 + remaining int64 + stickyErr error } -func (r *limitedReader) Read(b []byte) (int, error) { +func (r *maxBytesReader) Read(b []byte) (int, error) { + if r.stickyErr != nil { + return 0, r.stickyErr + } + + if len(b) == 0 { + return 0, nil + } + + // if possible no need to read the entire chunk since + // remaining+1 is enough to determine whether it exceed the limit + if int64(len(b))-1 > r.remaining { + b = b[:r.remaining+1] + } + n, err := r.ReadCloser.Read(b) - if err != nil { + + if int64(n) <= r.remaining { + r.remaining -= int64(n) + r.stickyErr = err return n, err } - r.totalRead += int64(n) - if r.totalRead > r.limit { - return n, ErrRequestEntityTooLarge - } + n = int(r.remaining) + + r.remaining = 0 + r.stickyErr = ErrRequestEntityTooLarge - return n, nil + return n, r.stickyErr } // explicit casts to ensure that the main struct methods will be invoked // (extra precautions in case of nested interface wrapping erasure) // --- -func (r *limitedReader) Reread() { +func (r *maxBytesReader) Reread() { rereader, ok := r.ReadCloser.(router.Rereader) if ok { rereader.Reread() + r.remaining = r.limit + r.stickyErr = nil } } -func (r *limitedReader) Close() error { - closer, ok := r.ReadCloser.(io.Closer) - if ok { - return closer.Close() - } - return nil +func (r *maxBytesReader) Close() error { + return r.ReadCloser.Close() } diff --git a/apis/middlewares_body_limit_test.go b/apis/middlewares_body_limit_test.go index 8e04e72438..f4ac9ae780 100644 --- a/apis/middlewares_body_limit_test.go +++ b/apis/middlewares_body_limit_test.go @@ -1,9 +1,10 @@ package apis_test import ( - "bytes" - "fmt" + "io" + "net/http" "net/http/httptest" + "strings" "testing" "github.com/pocketbase/pocketbase/apis" @@ -19,13 +20,35 @@ func TestBodyLimitMiddleware(t *testing.T) { if err != nil { t.Fatal(err) } - pbRouter.POST("/a", func(e *core.RequestEvent) error { - return e.String(200, "a") - }) // default global BodyLimit check - pbRouter.POST("/b", func(e *core.RequestEvent) error { - return e.String(200, "b") - }).Bind(apis.BodyLimit(20)) + testHandler := func(e *core.RequestEvent) error { + // read the body multiple times to ensure that the limited + // reader guards and rereads are invoked + var result any + if err := e.BindBody(&result); err != nil { + return err + } + + if err := e.BindBody(&result); err != nil { + return err + } + + return e.JSON(200, result) + } + + const customLimit = 20 + + pbRouter.POST("/a", testHandler) // default global BodyLimit check + pbRouter.POST("/b", testHandler).Bind(apis.BodyLimit(customLimit)) + pbRouter.POST("/iof", func(e *core.RequestEvent) error { + // ensure that normal io methods still operate correctly + b, err := io.ReadAll(e.Request.Body) + if err != nil { + return err + } + + return e.String(http.StatusOK, string(b)) + }).Bind(apis.BodyLimit(customLimit)) mux, err := pbRouter.BuildMux() if err != nil { @@ -33,20 +56,90 @@ func TestBodyLimitMiddleware(t *testing.T) { } scenarios := []struct { - url string - size int64 - expectedStatus int + name string + url string + body string + lazyContentLength bool + expectedStatus int }{ - {"/a", 21, 200}, - {"/a", apis.DefaultMaxBodySize + 1, 413}, - {"/b", 20, 200}, - {"/b", 21, 413}, + { + "(eager content-length check) with body = default limit", + "/a", + `"` + strings.Repeat("a", int(apis.DefaultMaxBodySize-2)) + `"`, + false, + http.StatusOK, + }, + { + "(eager content-length check) with body > default limit", + "/a", + `"` + strings.Repeat("a", int(apis.DefaultMaxBodySize)) + `"`, + false, + http.StatusRequestEntityTooLarge, + }, + { + "(lazy content-length check) with body = default limit", + "/a", + `"` + strings.Repeat("a", int(apis.DefaultMaxBodySize-2)) + `"`, + true, + http.StatusOK, + }, + { + "(lazy content-length check) with body > default limit", + "/a", + `"` + strings.Repeat("a", int(apis.DefaultMaxBodySize)) + `"`, + true, + http.StatusRequestEntityTooLarge, + }, + // --- + { + "(eager content-length check) with body = custom limit", + "/b", + `"` + strings.Repeat("a", customLimit-2) + `"`, + false, + http.StatusOK, + }, + { + "(eager content-length check) with body > custom limit", + "/b", + `"` + strings.Repeat("a", customLimit) + `"`, + false, + http.StatusRequestEntityTooLarge, + }, + { + "(lazy content-length check) with body = custom limit", + "/b", + `"` + strings.Repeat("a", customLimit-2) + `"`, + true, + http.StatusOK, + }, + { + "(lazy content-length check) with body > custom limit", + "/b", + `"` + strings.Repeat("a", customLimit) + `"`, + true, + http.StatusRequestEntityTooLarge, + }, + // --- + { + "io.ReadAll io.EOF exact limit check", + "/iof", + `"` + strings.Repeat("a", customLimit-2) + `"`, + true, + http.StatusOK, + }, } for _, s := range scenarios { - t.Run(fmt.Sprintf("%s_%d", s.url, s.size), func(t *testing.T) { + t.Run(s.name, func(t *testing.T) { rec := httptest.NewRecorder() - req := httptest.NewRequest("POST", s.url, bytes.NewReader(make([]byte, s.size))) + + req := httptest.NewRequest("POST", s.url, strings.NewReader(s.body)) + req.Header.Set("Content-Type", "application/json") + + if s.lazyContentLength { + req.ContentLength = -1 + } + mux.ServeHTTP(rec, req) result := rec.Result() diff --git a/core/field_json.go b/core/field_json.go index 5dac9bc956..2d3588d512 100644 --- a/core/field_json.go +++ b/core/field_json.go @@ -2,6 +2,8 @@ package core import ( "context" + "encoding/json/jsontext" + "encoding/json/v2" "slices" "strconv" "strings" @@ -171,6 +173,18 @@ func (f *JSONField) ValidateValue(ctx context.Context, app App, record *Record) return validation.NewError("validation_invalid_json", "Must be a valid json value") } + // temp extra encoding/json/v2 check since the above validator is + // still using the v1 semantics + // + // @todo remove after updating the string validator + if len(raw) > 0 { + var dummy any + err := json.Unmarshal(raw, &dummy, jsontext.AllowInvalidUTF8(true)) + if err != nil { + return validation.NewError("validation_invalid_json", "Must be a valid json value") + } + } + rawStr := strings.TrimSpace(raw.String()) if f.Required && slices.Contains(emptyJSONValues, rawStr) { diff --git a/core/field_json_test.go b/core/field_json_test.go index 13eb1f2140..52fa4be408 100644 --- a/core/field_json_test.go +++ b/core/field_json_test.go @@ -101,6 +101,16 @@ func TestJSONFieldValidateValue(t *testing.T) { }, true, }, + { + "invalid raw value (v2 semantics)", + &core.JSONField{Name: "test"}, + func() *core.Record { + record := core.NewRecord(collection) + record.SetRaw("test", types.JSONRaw(`{"a": 1, "a": 2}`)) + return record + }, + true, + }, { "zero field value (not required)", &core.JSONField{Name: "test"}, diff --git a/core/record_model.go b/core/record_model.go index b27b520352..b654864d08 100644 --- a/core/record_model.go +++ b/core/record_model.go @@ -3,6 +3,7 @@ package core import ( "bytes" "context" + "database/sql" "encoding/json/jsontext" "encoding/json/v2" "errors" @@ -1333,7 +1334,9 @@ func (m Record) MarshalJSON() ([]byte, error) { return json.Marshal( m.PublicExport(), json.Deterministic(true), - // to preserve the old jsonv1 behavior in case of invalid data + // for compliance with old data (and slightly better performance) + jsontext.AllowDuplicateNames(true), + // preserve the old jsonv1 behavior in case of invalid data jsontext.AllowInvalidUTF8(true), ) } @@ -1532,12 +1535,14 @@ func cascadeRecordDelete(app App, mainRecord *Record, refs map[*Collection][]Fie continue // skip missing or view collections } - recordTableName := inflector.Columnify(refCollection.Name) + refTableName := inflector.Columnify(refCollection.Name) for _, field := range fields { - prefixedFieldName := recordTableName + "." + inflector.Columnify(field.GetName()) + prefixedFieldName := refTableName + "." + inflector.Columnify(field.GetName()) - query := app.RecordQuery(refCollection) + // fetch only the related ids because they will be queried anyway right + // before delete to ensure that we are working with fresh record data + query := app.DB().Select(refTableName + ".id").From(refTableName) if opt, ok := field.(MultiValuer); !ok || !opt.IsMultiple() { query.AndWhere(dbx.HashExp{prefixedFieldName: mainRecord.Id}) @@ -1551,23 +1556,24 @@ func cascadeRecordDelete(app App, mainRecord *Record, refs map[*Collection][]Fie } if refCollection.Id == mainRecord.Collection().Id { - query.AndWhere(dbx.Not(dbx.HashExp{recordTableName + ".id": mainRecord.Id})) + query.AndWhere(dbx.Not(dbx.HashExp{refTableName + ".id": mainRecord.Id})) } // trigger cascade for each batchSize rel items until there is none - batchSize := 4000 - rows := make([]*Record, 0, batchSize) + batchSize := 8000 + refIds := make([]string, 0, batchSize) for { - if err := query.Limit(int64(batchSize)).All(&rows); err != nil { + err := query.Limit(int64(batchSize)).Column(&refIds) + if err != nil { return err } - total := len(rows) + total := len(refIds) if total == 0 { break } - err := deleteRefRecords(app, mainRecord, rows, field) + err = deleteRefRecords(app, mainRecord, refCollection, refIds, field) if err != nil { return err } @@ -1576,7 +1582,7 @@ func cascadeRecordDelete(app App, mainRecord *Record, refs map[*Collection][]Fie break // no more items } - rows = rows[:0] // keep allocated memory + refIds = refIds[:0] // keep allocated memory } } } @@ -1589,13 +1595,21 @@ func cascadeRecordDelete(app App, mainRecord *Record, refs map[*Collection][]Fie // just unset the record id from any relation field values (if they are not required). // // NB! This method is expected to be called from inside of a transaction. -func deleteRefRecords(app App, mainRecord *Record, refRecords []*Record, field Field) error { +func deleteRefRecords(app App, mainRecord *Record, refCollection *Collection, refIds []string, field Field) error { relField, _ := field.(*RelationField) if relField == nil { return errors.New("only RelationField is supported at the moment, got " + field.Type()) } - for _, refRecord := range refRecords { + for _, refId := range refIds { + refRecord, err := app.FindRecordById(refCollection, refId) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + continue // already deleted + } + return err + } + ids := refRecord.GetStringSlice(relField.Name) // unset the record id diff --git a/core/record_model_test.go b/core/record_model_test.go index 75e046e29c..bac46a8b24 100644 --- a/core/record_model_test.go +++ b/core/record_model_test.go @@ -1413,14 +1413,15 @@ func TestRecordPublicExportAndMarshalJSON(t *testing.T) { f3 := &core.SelectField{Name: "field3", MaxSelect: 2, Values: []string{"test1", "test2", "test3"}} f4 := &core.TextField{Name: "field4", Hidden: true} f5 := &core.TextField{Name: "field5", Hidden: true} + f6 := &core.JSONField{Name: "field6"} colBase := core.NewBaseCollection("test_base") colBase.Id = "_pbc_base_123" - colBase.Fields.Add(f1, f2, f3, f4, f5) + colBase.Fields.Add(f1, f2, f3, f4, f5, f6) colAuth := core.NewAuthCollection("test_auth") colAuth.Id = "_pbc_auth_123" - colAuth.Fields.Add(f1, f2, f3, f4, f5) + colAuth.Fields.Add(f1, f2, f3, f4, f5, f6) scenarios := []struct { name string @@ -1439,7 +1440,7 @@ func TestRecordPublicExportAndMarshalJSON(t *testing.T) { false, nil, nil, - `{"collectionId":"_pbc_base_123","collectionName":"test_base","expand":{"test":123},"field1":"field_1�","field2":"field_2.png","field3":["test1","test2"],"id":"test_id"}`, + `{"collectionId":"_pbc_base_123","collectionName":"test_base","expand":{"test":123},"field1":"field_1�","field2":"field_2.png","field3":["test1","test2"],"field6":{"a":1,"a":2},"id":"test_id"}`, }, { "[base] with email visibility", @@ -1448,7 +1449,7 @@ func TestRecordPublicExportAndMarshalJSON(t *testing.T) { false, nil, nil, - `{"collectionId":"_pbc_base_123","collectionName":"test_base","expand":{"test":123},"field1":"field_1�","field2":"field_2.png","field3":["test1","test2"],"id":"test_id"}`, + `{"collectionId":"_pbc_base_123","collectionName":"test_base","expand":{"test":123},"field1":"field_1�","field2":"field_2.png","field3":["test1","test2"],"field6":{"a":1,"a":2},"id":"test_id"}`, }, { "[base] with custom data", @@ -1457,7 +1458,7 @@ func TestRecordPublicExportAndMarshalJSON(t *testing.T) { true, nil, nil, - `{"collectionId":"_pbc_base_123","collectionName":"test_base","email":"test_email","emailVisibility":"test_invalid","expand":{"test":123},"field1":"field_1�","field2":"field_2.png","field3":["test1","test2"],"id":"test_id","password":"test_passwordHash","tokenKey":"test_tokenKey","unknown":"test_unknown","verified":true}`, + `{"collectionId":"_pbc_base_123","collectionName":"test_base","email":"test_email","emailVisibility":"test_invalid","expand":{"test":123},"field1":"field_1�","field2":"field_2.png","field3":["test1","test2"],"field6":{"a":1,"a":2},"id":"test_id","password":"test_passwordHash","tokenKey":"test_tokenKey","unknown":"test_unknown","verified":true}`, }, { "[base] with explicit hide and unhide fields", @@ -1466,7 +1467,7 @@ func TestRecordPublicExportAndMarshalJSON(t *testing.T) { true, []string{"field3", "field1", "expand", "collectionId", "collectionName", "email", "tokenKey", "unknown"}, []string{"field4", "@pbInternalAbc"}, - `{"emailVisibility":"test_invalid","field2":"field_2.png","field4":"field_4","id":"test_id","password":"test_passwordHash","verified":true}`, + `{"emailVisibility":"test_invalid","field2":"field_2.png","field4":"field_4","field6":{"a":1,"a":2},"id":"test_id","password":"test_passwordHash","verified":true}`, }, { "[base] trying to unhide custom fields without explicit WithCustomData", @@ -1475,7 +1476,7 @@ func TestRecordPublicExportAndMarshalJSON(t *testing.T) { true, nil, []string{"field5", "@pbInternalAbc", "email", "tokenKey", "unknown"}, - `{"collectionId":"_pbc_base_123","collectionName":"test_base","email":"test_email","emailVisibility":"test_invalid","expand":{"test":123},"field1":"field_1�","field2":"field_2.png","field3":["test1","test2"],"field5":"field_5","id":"test_id","password":"test_passwordHash","tokenKey":"test_tokenKey","unknown":"test_unknown","verified":true}`, + `{"collectionId":"_pbc_base_123","collectionName":"test_base","email":"test_email","emailVisibility":"test_invalid","expand":{"test":123},"field1":"field_1�","field2":"field_2.png","field3":["test1","test2"],"field5":"field_5","field6":{"a":1,"a":2},"id":"test_id","password":"test_passwordHash","tokenKey":"test_tokenKey","unknown":"test_unknown","verified":true}`, }, // auth @@ -1486,7 +1487,7 @@ func TestRecordPublicExportAndMarshalJSON(t *testing.T) { false, nil, nil, - `{"collectionId":"_pbc_auth_123","collectionName":"test_auth","emailVisibility":false,"expand":{"test":123},"field1":"field_1�","field2":"field_2.png","field3":["test1","test2"],"id":"test_id","verified":true}`, + `{"collectionId":"_pbc_auth_123","collectionName":"test_auth","emailVisibility":false,"expand":{"test":123},"field1":"field_1�","field2":"field_2.png","field3":["test1","test2"],"field6":{"a":1,"a":2},"id":"test_id","verified":true}`, }, { "[auth] with email visibility", @@ -1495,7 +1496,7 @@ func TestRecordPublicExportAndMarshalJSON(t *testing.T) { false, nil, nil, - `{"collectionId":"_pbc_auth_123","collectionName":"test_auth","email":"test_email","emailVisibility":false,"expand":{"test":123},"field1":"field_1�","field2":"field_2.png","field3":["test1","test2"],"id":"test_id","verified":true}`, + `{"collectionId":"_pbc_auth_123","collectionName":"test_auth","email":"test_email","emailVisibility":false,"expand":{"test":123},"field1":"field_1�","field2":"field_2.png","field3":["test1","test2"],"field6":{"a":1,"a":2},"id":"test_id","verified":true}`, }, { "[auth] with custom data", @@ -1504,7 +1505,7 @@ func TestRecordPublicExportAndMarshalJSON(t *testing.T) { true, nil, nil, - `{"collectionId":"_pbc_auth_123","collectionName":"test_auth","emailVisibility":false,"expand":{"test":123},"field1":"field_1�","field2":"field_2.png","field3":["test1","test2"],"id":"test_id","unknown":"test_unknown","verified":true}`, + `{"collectionId":"_pbc_auth_123","collectionName":"test_auth","emailVisibility":false,"expand":{"test":123},"field1":"field_1�","field2":"field_2.png","field3":["test1","test2"],"field6":{"a":1,"a":2},"id":"test_id","unknown":"test_unknown","verified":true}`, }, { "[auth] with explicit hide and unhide fields", @@ -1513,7 +1514,7 @@ func TestRecordPublicExportAndMarshalJSON(t *testing.T) { true, []string{"field3", "field1", "expand", "collectionId", "collectionName", "email", "unknown"}, []string{"field4", "@pbInternalAbc"}, - `{"emailVisibility":false,"field2":"field_2.png","field4":"field_4","id":"test_id","verified":true}`, + `{"emailVisibility":false,"field2":"field_2.png","field4":"field_4","field6":{"a":1,"a":2},"id":"test_id","verified":true}`, }, { "[auth] trying to unhide custom fields without explicit WithCustomData", @@ -1522,7 +1523,7 @@ func TestRecordPublicExportAndMarshalJSON(t *testing.T) { true, nil, []string{"field5", "@pbInternalAbc", "tokenKey", "unknown", "email"}, // emailVisibility:false has higher priority - `{"collectionId":"_pbc_auth_123","collectionName":"test_auth","emailVisibility":false,"expand":{"test":123},"field1":"field_1�","field2":"field_2.png","field3":["test1","test2"],"field5":"field_5","id":"test_id","unknown":"test_unknown","verified":true}`, + `{"collectionId":"_pbc_auth_123","collectionName":"test_auth","emailVisibility":false,"expand":{"test":123},"field1":"field_1�","field2":"field_2.png","field3":["test1","test2"],"field5":"field_5","field6":{"a":1,"a":2},"id":"test_id","unknown":"test_unknown","verified":true}`, }, } @@ -1533,6 +1534,7 @@ func TestRecordPublicExportAndMarshalJSON(t *testing.T) { "field3": []string{"test1", "test2"}, "field4": "field_4", "field5": "field_5", + "field6": types.JSONRaw(`{"a":1,"a":2}`), // intentionally duplicated to check serialization "expand": map[string]any{"test": 123}, "collectionId": "m_id", // should be always ignored "collectionName": "m_name", // should be always ignored @@ -1558,6 +1560,7 @@ func TestRecordPublicExportAndMarshalJSON(t *testing.T) { exportResult, err := json.Marshal( m.PublicExport(), json.Deterministic(true), + jsontext.AllowDuplicateNames(true), jsontext.AllowInvalidUTF8(true), ) if err != nil { @@ -2324,16 +2327,105 @@ func TestRecordDelete(t *testing.T) { } // ensure that the json rel fields were prefixed joinedQueries := strings.Join(calledQueries, " ") - expectedRelManyPart := "SELECT `demo1`.* FROM `demo1` WHERE EXISTS (SELECT 1 FROM json_each(CASE WHEN iif(json_valid([[demo1.rel_many]]), json_type([[demo1.rel_many]])='array', FALSE) THEN [[demo1.rel_many]] ELSE json_array([[demo1.rel_many]]) END) {{__je__}} WHERE [[__je__.value]]='" + expectedRelManyPart := "SELECT `demo1`.`id` FROM `demo1` WHERE EXISTS (SELECT 1 FROM json_each(CASE WHEN iif(json_valid([[demo1.rel_many]]), json_type([[demo1.rel_many]])='array', FALSE) THEN [[demo1.rel_many]] ELSE json_array([[demo1.rel_many]]) END) {{__je__}} WHERE [[__je__.value]]='" if !strings.Contains(joinedQueries, expectedRelManyPart) { t.Fatalf("(rec3) Expected the cascade delete to call the query \n%v, got \n%v", expectedRelManyPart, calledQueries) } - expectedRelOnePart := "SELECT `demo1`.* FROM `demo1` WHERE (`demo1`.`rel_one`='" + expectedRelOnePart := "SELECT `demo1`.`id` FROM `demo1` WHERE (`demo1`.`rel_one`='" if !strings.Contains(joinedQueries, expectedRelOnePart) { t.Fatalf("(rec3) Expected the cascade delete to call the query \n%v, got \n%v", expectedRelOnePart, calledQueries) } } +func TestRecordDeleteWithMultipleRelationCascade(t *testing.T) { + t.Parallel() + + app, _ := tests.NewTestApp() + defer app.Cleanup() + + // create a mock collection with self referencing multiple relation field + // --- + collection := core.NewBaseCollection("test") + err := app.Save(collection) + if err != nil { + t.Fatal(err) + } + + // for simpler mocks + collection.Fields.GetByName("id").(*core.TextField).Min = 1 + + collection.Fields.Add(&core.RelationField{ + Name: "rels", + CollectionId: collection.Id, + MaxSelect: 99, + CascadeDelete: true, + }) + + err = app.Save(collection) + if err != nil { + t.Fatal(err) + } + + // create mock records + // --- + relsData := map[string][]string{ + "a": nil, + "b": {"a"}, + "c": {"a", "b"}, + "d": {}, + "e": {"c", "d"}, + } + for id, rels := range relsData { + record := core.NewRecord(collection) + record.Set("id", id) + record.Set("rels", rels) + err = app.SaveNoValidate(record) // map is not ordered + if err != nil { + t.Fatalf("failed to create mock record: %v", err) + } + } + + // trigger cascade delete for the top record + // --- + aRecord, err := app.FindRecordById(collection, "a") + if err != nil { + t.Fatal(err) + } + + err = app.Delete(aRecord) + if err != nil { + t.Fatal(err) + } + + // verify cascade delete + // --- + expectedRels := map[string][]string{ + "d": {}, + "e": {"d"}, + } + + allRecords, err := app.FindAllRecords(collection) + if err != nil { + t.Fatal(err) + } + + if len(allRecords) != len(expectedRels) { + t.Fatalf("Expected %d remaining records, got %d", len(expectedRels), len(allRecords)) + } + + for _, r := range allRecords { + expected, ok := expectedRels[r.Id] + if !ok { + t.Fatalf("Record %q wasn't found in %v", r.Id, expectedRels) + } + + rels := r.GetStringSlice("rels") + if !slices.Equal(rels, expected) { + t.Fatalf("Record %q expected rels\n%v\ngot\n%v", r.Id, expected, rels) + } + } +} + func TestRecordDeleteBatchProcessing(t *testing.T) { t.Parallel() diff --git a/go.mod b/go.mod index 5acdbeb310..e5b8790b1d 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/pocketbase/tygoja v0.1.0 github.com/spf13/cast v1.10.0 github.com/spf13/cobra v1.10.2 - golang.org/x/crypto v0.55.0 + golang.org/x/crypto v0.56.0 golang.org/x/image v0.45.0 golang.org/x/net v0.58.0 golang.org/x/oauth2 v0.36.0 diff --git a/go.sum b/go.sum index 1361584ab1..46cc46711c 100644 --- a/go.sum +++ b/go.sum @@ -88,8 +88,8 @@ github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PK github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 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.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M= -golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis= +golang.org/x/crypto v0.56.0 h1:GUh5Ii4J5jtcseSMiRqr1jXCNHoxjeV9Fmekc2oLy6Y= +golang.org/x/crypto v0.56.0/go.mod h1:OMW5y6CY9l38uPLmxU6l6pwcXp1obtLo3e6gT7gQR2I= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.45.0 h1:FMb1nTbH5H9vF55SriQHgFw5GnNL9Jg6L25BwXKzhB0= golang.org/x/image v0.45.0/go.mod h1:n62x/7RqlwXDvGsSU4u6IUTUf6KghUZ9Bt7cG/T9Fx4= diff --git a/plugins/jsvm/internal/types/generated/types.d.ts b/plugins/jsvm/internal/types/generated/types.d.ts index 7131db9d35..e563f4256c 100644 --- a/plugins/jsvm/internal/types/generated/types.d.ts +++ b/plugins/jsvm/internal/types/generated/types.d.ts @@ -1,4 +1,4 @@ -// 1788352612 +// 1788714636 // GENERATED CODE - DO NOT MODIFY BY HAND // ------------------------------------------------------------------- @@ -113,7 +113,7 @@ type excludeHooks = { type CoreApp = excludeHooks // PocketBase without the on* hook methods -type PocketBase = excludeHooks +interface PocketBase extends excludeHooks{} /** * `$app` is the current running PocketBase instance that is globally @@ -1964,8 +1964,8 @@ namespace os { * than ReadFrom. This is used to permit ReadFrom to call io.Copy * without leading to a recursive call to ReadFrom. */ - type _sVRgVGh = noReadFrom&File - interface fileWithoutReadFrom extends _sVRgVGh { + type _sgIssSZ = noReadFrom&File + interface fileWithoutReadFrom extends _sgIssSZ { } interface File { /** @@ -2009,8 +2009,8 @@ namespace os { * than WriteTo. This is used to permit WriteTo to call io.Copy * without leading to a recursive call to WriteTo. */ - type _sQzCJfX = noWriteTo&File - interface fileWithoutWriteTo extends _sQzCJfX { + type _sRmRjyu = noWriteTo&File + interface fileWithoutWriteTo extends _sRmRjyu { } interface File { /** @@ -2957,8 +2957,8 @@ namespace os { * * The methods of File are safe for concurrent use. */ - type _sometOC = file - interface File extends _sometOC { + type _spYcXgA = file + interface File extends _spYcXgA { } /** * A FileInfo describes a file and is returned by [Stat] and [Lstat]. @@ -3009,628 +3009,174 @@ namespace os { } /** - * Package filepath implements utility routines for manipulating filename paths - * in a way compatible with the target operating system-defined file paths. - * - * The filepath package uses either forward slashes or backslashes, - * depending on the operating system. To process paths such as URLs - * that always use forward slashes regardless of the operating - * system, see the [path] package. + * Package dbx provides a set of DB-agnostic and easy-to-use query building methods for relational databases. */ -namespace filepath { - interface match { +namespace dbx { + /** + * Builder supports building SQL statements in a DB-agnostic way. + * Builder mainly provides two sets of query building methods: those building SELECT statements + * and those manipulating DB data or schema (e.g. INSERT statements, CREATE TABLE statements). + */ + interface Builder { + [key:string]: any; /** - * Match reports whether name matches the shell file name pattern. - * The pattern syntax is: - * - * ``` - * pattern: - * { term } - * term: - * '*' matches any sequence of non-Separator characters - * '?' matches any single non-Separator character - * '[' [ '^' ] { character-range } ']' - * character class (must be non-empty) - * c matches character c (c != '*', '?', '\\', '[') - * '\\' c matches character c (except on Windows) - * - * character-range: - * c matches character c (c != '\\', '-', ']') - * '\\' c matches character c (except on Windows) - * lo '-' hi matches character c for lo <= c <= hi - * ``` - * - * Path segments in the pattern must be separated by [Separator]. - * - * Match requires pattern to match all of name, not just a substring. - * The only possible returned error is [ErrBadPattern], when pattern - * is malformed. - * - * On Windows, escaping is disabled. Instead, '\\' is treated as - * path separator. + * NewQuery creates a new Query object with the given SQL statement. + * The SQL statement may contain parameter placeholders which can be bound with actual parameter + * values before the statement is executed. */ - (pattern: string, name: string): boolean - } - interface glob { + newQuery(_arg0: string): (Query) /** - * Glob returns the names of all files matching pattern or nil - * if there is no matching file. The syntax of patterns is the same - * as in [Match]. The pattern may describe hierarchical names such as - * /usr/*\/bin/ed (assuming the [Separator] is '/'). - * - * Glob ignores file system errors such as I/O errors reading directories. - * The only possible returned error is [ErrBadPattern], when pattern - * is malformed. + * Select returns a new SelectQuery object that can be used to build a SELECT statement. + * The parameters to this method should be the list column names to be selected. + * A column name may have an optional alias name. For example, Select("id", "my_name AS name"). */ - (pattern: string): Array - } - interface clean { + select(..._arg0: string[]): (SelectQuery) /** - * Clean returns the shortest path name equivalent to path - * by purely lexical processing. It applies the following rules - * iteratively until no further processing can be done: - * - * 1. Replace multiple [Separator] elements with a single one. - * 2. Eliminate each . path name element (the current directory). - * 3. Eliminate each inner .. path name element (the parent directory) - * ``` - * along with the non-.. element that precedes it. - * ``` - * 4. Eliminate .. elements that begin a rooted path: - * ``` - * that is, replace "/.." by "/" at the beginning of a path, - * assuming Separator is '/'. - * ``` - * - * The returned path ends in a slash only if it represents a root directory, - * such as "/" on Unix or `C:\` on Windows. - * - * Finally, any occurrences of slash are replaced by Separator. - * - * If the result of this process is an empty string, Clean - * returns the string ".". - * - * On Windows, Clean does not modify the volume name other than to replace - * occurrences of "/" with `\`. - * For example, Clean("//host/share/../x") returns `\\host\share\x`. - * - * See also Rob Pike, “Lexical File Names in Plan 9 or - * Getting Dot-Dot Right,” - * https://9p.io/sys/doc/lexnames.html + * ModelQuery returns a new ModelQuery object that can be used to perform model insertion, update, and deletion. + * The parameter to this method should be a pointer to the model struct that needs to be inserted, updated, or deleted. */ - (path: string): string - } - interface isLocal { + model(_arg0: { + }): (ModelQuery) /** - * IsLocal reports whether path, using lexical analysis only, has all of these properties: - * - * ``` - * - is within the subtree rooted at the directory in which path is evaluated - * - is not an absolute path - * - is not empty - * - on Windows, is not a reserved name such as "NUL" - * ``` - * - * If IsLocal(path) returns true, then - * Join(base, path) will always produce a path contained within base and - * Clean(path) will always produce an unrooted path with no ".." path elements. - * - * IsLocal is a purely lexical operation. - * In particular, it does not account for the effect of any symbolic links - * that may exist in the filesystem. + * GeneratePlaceholder generates an anonymous parameter placeholder with the given parameter ID. */ - (path: string): boolean - } - interface localize { + generatePlaceholder(_arg0: number): string /** - * Localize converts a slash-separated path into an operating system path. - * The input path must be a valid path as reported by [io/fs.ValidPath]. - * - * Localize returns an error if the path cannot be represented by the operating system. - * For example, the path a\b is rejected on Windows, on which \ is a separator - * character and cannot be part of a filename. - * - * The path returned by Localize will always be local, as reported by IsLocal. + * Quote quotes a string so that it can be embedded in a SQL statement as a string value. */ - (path: string): string - } - interface toSlash { + quote(_arg0: string): string /** - * ToSlash returns the result of replacing each separator character - * in path with a slash ('/') character. Multiple separators are - * replaced by multiple slashes. + * QuoteSimpleTableName quotes a simple table name. + * A simple table name does not contain any schema prefix. */ - (path: string): string - } - interface fromSlash { + quoteSimpleTableName(_arg0: string): string /** - * FromSlash returns the result of replacing each slash ('/') character - * in path with a separator character. Multiple slashes are replaced - * by multiple separators. - * - * See also the Localize function, which converts a slash-separated path - * as used by the io/fs package to an operating system path. + * QuoteSimpleColumnName quotes a simple column name. + * A simple column name does not contain any table prefix. */ - (path: string): string - } - interface splitList { + quoteSimpleColumnName(_arg0: string): string /** - * SplitList splits a list of paths joined by the OS-specific [ListSeparator], - * usually found in PATH or GOPATH environment variables. - * Unlike strings.Split, SplitList returns an empty slice when passed an empty - * string. + * QueryBuilder returns the query builder supporting the current DB. */ - (path: string): Array - } - interface split { + queryBuilder(): QueryBuilder /** - * Split splits path immediately following the final [Separator], - * separating it into a directory and file name component. - * If there is no Separator in path, Split returns an empty dir - * and file set to path. - * The returned values have the property that path = dir+file. + * Insert creates a Query that represents an INSERT SQL statement. + * The keys of cols are the column names, while the values of cols are the corresponding column + * values to be inserted. */ - (path: string): [string, string] - } - interface join { + insert(table: string, cols: Params): (Query) /** - * Join joins any number of path elements into a single path, - * separating them with an OS specific [Separator]. Empty elements - * are ignored. The result is Cleaned. However, if the argument - * list is empty or all its elements are empty, Join returns - * an empty string. - * On Windows, the result will only be a UNC path if the first - * non-empty element is a UNC path. + * Upsert creates a Query that represents an UPSERT SQL statement. + * Upsert inserts a row into the table if the primary key or unique index is not found. + * Otherwise it will update the row with the new values. + * The keys of cols are the column names, while the values of cols are the corresponding column + * values to be inserted. */ - (...elem: string[]): string - } - interface ext { + upsert(table: string, cols: Params, ...constraints: string[]): (Query) /** - * Ext returns the file name extension used by path. - * The extension is the suffix beginning at the final dot - * in the final element of path; it is empty if there is - * no dot. + * Update creates a Query that represents an UPDATE SQL statement. + * The keys of cols are the column names, while the values of cols are the corresponding new column + * values. If the "where" expression is nil, the UPDATE SQL statement will have no WHERE clause + * (be careful in this case as the SQL statement will update ALL rows in the table). */ - (path: string): string - } - interface evalSymlinks { + update(table: string, cols: Params, where: Expression): (Query) /** - * EvalSymlinks returns the path name after the evaluation of any symbolic - * links. - * If path is relative the result will be relative to the current directory, - * unless one of the components is an absolute symbolic link. - * EvalSymlinks calls [Clean] on the result. + * Delete creates a Query that represents a DELETE SQL statement. + * If the "where" expression is nil, the DELETE SQL statement will have no WHERE clause + * (be careful in this case as the SQL statement will delete ALL rows in the table). */ - (path: string): string - } - interface isAbs { + delete(table: string, where: Expression): (Query) /** - * IsAbs reports whether the path is absolute. + * CreateTable creates a Query that represents a CREATE TABLE SQL statement. + * The keys of cols are the column names, while the values of cols are the corresponding column types. + * The optional "options" parameters will be appended to the generated SQL statement. */ - (path: string): boolean - } - interface abs { + createTable(table: string, cols: _TygojaDict, ...options: string[]): (Query) /** - * Abs returns an absolute representation of path. - * If the path is not absolute it will be joined with the current - * working directory to turn it into an absolute path. The absolute - * path name for a given file is not guaranteed to be unique. - * Abs calls [Clean] on the result. + * RenameTable creates a Query that can be used to rename a table. */ - (path: string): string - } - interface rel { + renameTable(oldName: string, newName: string): (Query) /** - * Rel returns a relative path that is lexically equivalent to targPath when - * joined to basePath with an intervening separator. That is, - * [Join](basePath, Rel(basePath, targPath)) is equivalent to targPath itself. - * - * The returned path will always be relative to basePath, even if basePath and - * targPath share no elements. Rel calls [Clean] on the result. - * - * An error is returned if targPath can't be made relative to basePath - * or if knowing the current working directory would be necessary to compute it. + * DropTable creates a Query that can be used to drop a table. */ - (basePath: string, targPath: string): string - } - /** - * WalkFunc is the type of the function called by [Walk] to visit each - * file or directory. - * - * The path argument contains the argument to Walk as a prefix. - * That is, if Walk is called with root argument "dir" and finds a file - * named "a" in that directory, the walk function will be called with - * argument "dir/a". - * - * The directory and file are joined with Join, which may clean the - * directory name: if Walk is called with the root argument "x/../dir" - * and finds a file named "a" in that directory, the walk function will - * be called with argument "dir/a", not "x/../dir/a". - * - * The info argument is the fs.FileInfo for the named path. - * - * The error result returned by the function controls how Walk continues. - * If the function returns the special value [SkipDir], Walk skips the - * current directory (path if info.IsDir() is true, otherwise path's - * parent directory). If the function returns the special value [SkipAll], - * Walk skips all remaining files and directories. Otherwise, if the function - * returns a non-nil error, Walk stops entirely and returns that error. - * - * The err argument reports an error related to path, signaling that Walk - * will not walk into that directory. The function can decide how to - * handle that error; as described earlier, returning the error will - * cause Walk to stop walking the entire tree. - * - * Walk calls the function with a non-nil err argument in two cases. - * - * First, if an [os.Lstat] on the root directory or any directory or file - * in the tree fails, Walk calls the function with path set to that - * directory or file's path, info set to nil, and err set to the error - * from os.Lstat. - * - * Second, if a directory's Readdirnames method fails, Walk calls the - * function with path set to the directory's path, info, set to an - * [fs.FileInfo] describing the directory, and err set to the error from - * Readdirnames. - */ - interface WalkFunc {(path: string, info: fs.FileInfo, err: Error): void } - interface walkDir { + dropTable(table: string): (Query) /** - * WalkDir walks the file tree rooted at root, calling fn for each file or - * directory in the tree, including root. - * - * All errors that arise visiting files and directories are filtered by fn: - * see the [fs.WalkDirFunc] documentation for details. - * - * The files are walked in lexical order, which makes the output deterministic - * but requires WalkDir to read an entire directory into memory before proceeding - * to walk that directory. - * - * WalkDir does not follow symbolic links. - * - * WalkDir calls fn with paths that use the separator character appropriate - * for the operating system. This is unlike [io/fs.WalkDir], which always - * uses slash separated paths. + * TruncateTable creates a Query that can be used to truncate a table. */ - (root: string, fn: fs.WalkDirFunc): void - } - interface walk { + truncateTable(table: string): (Query) /** - * Walk walks the file tree rooted at root, calling fn for each file or - * directory in the tree, including root. - * - * All errors that arise visiting files and directories are filtered by fn: - * see the [WalkFunc] documentation for details. - * - * The files are walked in lexical order, which makes the output deterministic - * but requires Walk to read an entire directory into memory before proceeding - * to walk that directory. - * - * Walk does not follow symbolic links. - * - * Walk is less efficient than [WalkDir], introduced in Go 1.16, - * which avoids calling os.Lstat on every visited file or directory. + * AddColumn creates a Query that can be used to add a column to a table. */ - (root: string, fn: WalkFunc): void - } - interface base { + addColumn(table: string, col: string, typ: string): (Query) /** - * Base returns the last element of path. - * Trailing path separators are removed before extracting the last element. - * If the path is empty, Base returns ".". - * If the path consists entirely of separators, Base returns a single separator. + * DropColumn creates a Query that can be used to drop a column from a table. */ - (path: string): string - } - interface dir { + dropColumn(table: string, col: string): (Query) /** - * Dir returns all but the last element of path, typically the path's directory. - * After dropping the final element, Dir calls [Clean] on the path and trailing - * slashes are removed. - * If the path is empty, Dir returns ".". - * If the path consists entirely of separators, Dir returns a single separator. - * The returned path does not end in a separator unless it is the root directory. - * - * On Windows, given a volume-only name such as "C:", Dir returns "C:.", - * the current directory on drive C. To obtain the drive's root "C:\", - * use [VolumeName] combined with a separator. + * RenameColumn creates a Query that can be used to rename a column in a table. */ - (path: string): string - } - interface volumeName { + renameColumn(table: string, oldName: string, newName: string): (Query) /** - * VolumeName returns leading volume name. - * Given "C:\foo\bar" it returns "C:" on Windows. - * Given "\\host\share\foo" it returns "\\host\share". - * On other platforms it returns "". + * AlterColumn creates a Query that can be used to change the definition of a table column. */ - (path: string): string - } - interface hasPrefix { + alterColumn(table: string, col: string, typ: string): (Query) /** - * HasPrefix exists for historical compatibility and should not be used. - * - * Deprecated: HasPrefix does not respect path boundaries and - * does not ignore case when required. + * AddPrimaryKey creates a Query that can be used to specify primary key(s) for a table. + * The "name" parameter specifies the name of the primary key constraint. */ - (p: string, prefix: string): boolean - } -} - -/** - * Package template is a thin wrapper around the standard html/template - * and text/template packages that implements a convenient registry to - * load and cache templates on the fly concurrently. - * - * It was created to assist the JSVM plugin HTML rendering, but could be used in other Go code. - * - * Example: - * - * ``` - * registry := template.NewRegistry() - * - * html1, err := registry.LoadFiles( - * // the files set wil be parsed only once and then cached - * "layout.html", - * "content.html", - * ).Render(map[string]any{"name": "John"}) - * - * html2, err := registry.LoadFiles( - * // reuse the already parsed and cached files set - * "layout.html", - * "content.html", - * ).Render(map[string]any{"name": "Jane"}) - * ``` - */ -namespace template { - interface newRegistry { + addPrimaryKey(table: string, name: string, ...cols: string[]): (Query) /** - * NewRegistry creates and initializes a new templates registry with - * some defaults (eg. global "raw" template function for unescaped HTML). - * - * Use the Registry.Load* methods to load templates into the registry. + * DropPrimaryKey creates a Query that can be used to remove the named primary key constraint from a table. */ - (): (Registry) - } - /** - * Registry defines a templates registry that is safe to be used by multiple goroutines. - * - * Use the Registry.Load* methods to load templates into the registry. - */ - interface Registry { - } - interface Registry { + dropPrimaryKey(table: string, name: string): (Query) /** - * AddFuncs registers new global template functions. - * - * The key of each map entry is the function name that will be used in the templates. - * If a function with the map entry name already exists it will be replaced with the new one. - * - * The value of each map entry is a function that must have either a - * single return value, or two return values of which the second has type error. - * - * Example: - * - * ``` - * r.AddFuncs(map[string]any{ - * "toUpper": func(str string) string { - * return strings.ToUppser(str) - * }, - * ... - * }) - * ``` + * AddForeignKey creates a Query that can be used to add a foreign key constraint to a table. + * The length of cols and refCols must be the same as they refer to the primary and referential columns. + * The optional "options" parameters will be appended to the SQL statement. They can be used to + * specify options such as "ON DELETE CASCADE". */ - addFuncs(funcs: _TygojaDict): (Registry) - } - interface Registry { + addForeignKey(table: string, name: string, cols: Array, refCols: Array, refTable: string, ...options: string[]): (Query) /** - * LoadFiles caches (if not already) the specified filenames set as a - * single template and returns a ready to use Renderer instance. - * - * There must be at least 1 filename specified. + * DropForeignKey creates a Query that can be used to remove the named foreign key constraint from a table. */ - loadFiles(...filenames: string[]): (Renderer) - } - interface Registry { + dropForeignKey(table: string, name: string): (Query) /** - * LoadString caches (if not already) the specified inline string as a - * single template and returns a ready to use Renderer instance. + * CreateIndex creates a Query that can be used to create an index for a table. */ - loadString(text: string): (Renderer) - } - interface Registry { + createIndex(table: string, name: string, ...cols: string[]): (Query) /** - * LoadFS caches (if not already) the specified fs and globPatterns - * pair as single template and returns a ready to use Renderer instance. - * - * There must be at least 1 file matching the provided globPattern(s) - * (note that most file names serves as glob patterns matching themselves). + * CreateUniqueIndex creates a Query that can be used to create a unique index for a table. */ - loadFS(fsys: fs.FS, ...globPatterns: string[]): (Renderer) + createUniqueIndex(table: string, name: string, ...cols: string[]): (Query) + /** + * DropIndex creates a Query that can be used to remove the named index from a table. + */ + dropIndex(table: string, name: string): (Query) } /** - * Renderer defines a single parsed template. + * BaseBuilder provides a basic implementation of the Builder interface. */ - interface Renderer { + interface BaseBuilder { } - interface Renderer { + interface newBaseBuilder { /** - * Render executes the template with the specified data as the dot object - * and returns the result as plain string. + * NewBaseBuilder creates a new BaseBuilder instance. */ - render(data: any): string + (db: DB, executor: Executor): (BaseBuilder) } -} - -/** - * Package dbx provides a set of DB-agnostic and easy-to-use query building methods for relational databases. - */ -namespace dbx { - /** - * Builder supports building SQL statements in a DB-agnostic way. - * Builder mainly provides two sets of query building methods: those building SELECT statements - * and those manipulating DB data or schema (e.g. INSERT statements, CREATE TABLE statements). - */ - interface Builder { - [key:string]: any; - /** - * NewQuery creates a new Query object with the given SQL statement. - * The SQL statement may contain parameter placeholders which can be bound with actual parameter - * values before the statement is executed. - */ - newQuery(_arg0: string): (Query) - /** - * Select returns a new SelectQuery object that can be used to build a SELECT statement. - * The parameters to this method should be the list column names to be selected. - * A column name may have an optional alias name. For example, Select("id", "my_name AS name"). - */ - select(..._arg0: string[]): (SelectQuery) - /** - * ModelQuery returns a new ModelQuery object that can be used to perform model insertion, update, and deletion. - * The parameter to this method should be a pointer to the model struct that needs to be inserted, updated, or deleted. - */ - model(_arg0: { - }): (ModelQuery) - /** - * GeneratePlaceholder generates an anonymous parameter placeholder with the given parameter ID. - */ - generatePlaceholder(_arg0: number): string - /** - * Quote quotes a string so that it can be embedded in a SQL statement as a string value. - */ - quote(_arg0: string): string - /** - * QuoteSimpleTableName quotes a simple table name. - * A simple table name does not contain any schema prefix. - */ - quoteSimpleTableName(_arg0: string): string - /** - * QuoteSimpleColumnName quotes a simple column name. - * A simple column name does not contain any table prefix. - */ - quoteSimpleColumnName(_arg0: string): string - /** - * QueryBuilder returns the query builder supporting the current DB. - */ - queryBuilder(): QueryBuilder - /** - * Insert creates a Query that represents an INSERT SQL statement. - * The keys of cols are the column names, while the values of cols are the corresponding column - * values to be inserted. - */ - insert(table: string, cols: Params): (Query) - /** - * Upsert creates a Query that represents an UPSERT SQL statement. - * Upsert inserts a row into the table if the primary key or unique index is not found. - * Otherwise it will update the row with the new values. - * The keys of cols are the column names, while the values of cols are the corresponding column - * values to be inserted. - */ - upsert(table: string, cols: Params, ...constraints: string[]): (Query) - /** - * Update creates a Query that represents an UPDATE SQL statement. - * The keys of cols are the column names, while the values of cols are the corresponding new column - * values. If the "where" expression is nil, the UPDATE SQL statement will have no WHERE clause - * (be careful in this case as the SQL statement will update ALL rows in the table). - */ - update(table: string, cols: Params, where: Expression): (Query) - /** - * Delete creates a Query that represents a DELETE SQL statement. - * If the "where" expression is nil, the DELETE SQL statement will have no WHERE clause - * (be careful in this case as the SQL statement will delete ALL rows in the table). - */ - delete(table: string, where: Expression): (Query) - /** - * CreateTable creates a Query that represents a CREATE TABLE SQL statement. - * The keys of cols are the column names, while the values of cols are the corresponding column types. - * The optional "options" parameters will be appended to the generated SQL statement. - */ - createTable(table: string, cols: _TygojaDict, ...options: string[]): (Query) - /** - * RenameTable creates a Query that can be used to rename a table. - */ - renameTable(oldName: string, newName: string): (Query) - /** - * DropTable creates a Query that can be used to drop a table. - */ - dropTable(table: string): (Query) - /** - * TruncateTable creates a Query that can be used to truncate a table. - */ - truncateTable(table: string): (Query) - /** - * AddColumn creates a Query that can be used to add a column to a table. - */ - addColumn(table: string, col: string, typ: string): (Query) - /** - * DropColumn creates a Query that can be used to drop a column from a table. - */ - dropColumn(table: string, col: string): (Query) - /** - * RenameColumn creates a Query that can be used to rename a column in a table. - */ - renameColumn(table: string, oldName: string, newName: string): (Query) - /** - * AlterColumn creates a Query that can be used to change the definition of a table column. - */ - alterColumn(table: string, col: string, typ: string): (Query) - /** - * AddPrimaryKey creates a Query that can be used to specify primary key(s) for a table. - * The "name" parameter specifies the name of the primary key constraint. - */ - addPrimaryKey(table: string, name: string, ...cols: string[]): (Query) - /** - * DropPrimaryKey creates a Query that can be used to remove the named primary key constraint from a table. - */ - dropPrimaryKey(table: string, name: string): (Query) - /** - * AddForeignKey creates a Query that can be used to add a foreign key constraint to a table. - * The length of cols and refCols must be the same as they refer to the primary and referential columns. - * The optional "options" parameters will be appended to the SQL statement. They can be used to - * specify options such as "ON DELETE CASCADE". - */ - addForeignKey(table: string, name: string, cols: Array, refCols: Array, refTable: string, ...options: string[]): (Query) - /** - * DropForeignKey creates a Query that can be used to remove the named foreign key constraint from a table. - */ - dropForeignKey(table: string, name: string): (Query) - /** - * CreateIndex creates a Query that can be used to create an index for a table. - */ - createIndex(table: string, name: string, ...cols: string[]): (Query) - /** - * CreateUniqueIndex creates a Query that can be used to create a unique index for a table. - */ - createUniqueIndex(table: string, name: string, ...cols: string[]): (Query) - /** - * DropIndex creates a Query that can be used to remove the named index from a table. - */ - dropIndex(table: string, name: string): (Query) - } - /** - * BaseBuilder provides a basic implementation of the Builder interface. - */ - interface BaseBuilder { - } - interface newBaseBuilder { - /** - * NewBaseBuilder creates a new BaseBuilder instance. - */ - (db: DB, executor: Executor): (BaseBuilder) - } - interface BaseBuilder { - /** - * DB returns the DB instance that this builder is associated with. - */ - db(): (DB) - } - interface BaseBuilder { - /** - * Executor returns the executor object (a DB instance or a transaction) for executing SQL statements. - */ - executor(): Executor - } - interface BaseBuilder { + interface BaseBuilder { + /** + * DB returns the DB instance that this builder is associated with. + */ + db(): (DB) + } + interface BaseBuilder { + /** + * Executor returns the executor object (a DB instance or a transaction) for executing SQL statements. + */ + executor(): Executor + } + interface BaseBuilder { /** * NewQuery creates a new Query object with the given SQL statement. * The SQL statement may contain parameter placeholders which can be bound with actual parameter @@ -3798,14 +3344,14 @@ namespace dbx { /** * MssqlBuilder is the builder for SQL Server databases. */ - type _sLFcOeZ = BaseBuilder - interface MssqlBuilder extends _sLFcOeZ { + type _swcntDE = BaseBuilder + interface MssqlBuilder extends _swcntDE { } /** * MssqlQueryBuilder is the query builder for SQL Server databases. */ - type _scSYDMq = BaseQueryBuilder - interface MssqlQueryBuilder extends _scSYDMq { + type _snJOAqT = BaseQueryBuilder + interface MssqlQueryBuilder extends _snJOAqT { } interface newMssqlBuilder { /** @@ -3876,8 +3422,8 @@ namespace dbx { /** * MysqlBuilder is the builder for MySQL databases. */ - type _sVQyyaz = BaseBuilder - interface MysqlBuilder extends _sVQyyaz { + type _sSBDQlh = BaseBuilder + interface MysqlBuilder extends _sSBDQlh { } interface newMysqlBuilder { /** @@ -3952,14 +3498,14 @@ namespace dbx { /** * OciBuilder is the builder for Oracle databases. */ - type _snYCBUl = BaseBuilder - interface OciBuilder extends _snYCBUl { + type _srFluux = BaseBuilder + interface OciBuilder extends _srFluux { } /** * OciQueryBuilder is the query builder for Oracle databases. */ - type _sMBpXFE = BaseQueryBuilder - interface OciQueryBuilder extends _sMBpXFE { + type _smKxGcw = BaseQueryBuilder + interface OciQueryBuilder extends _smKxGcw { } interface newOciBuilder { /** @@ -4022,8 +3568,8 @@ namespace dbx { /** * PgsqlBuilder is the builder for PostgreSQL databases. */ - type _shgmXri = BaseBuilder - interface PgsqlBuilder extends _shgmXri { + type _syjFlMY = BaseBuilder + interface PgsqlBuilder extends _syjFlMY { } interface newPgsqlBuilder { /** @@ -4090,8 +3636,8 @@ namespace dbx { /** * SqliteQueryBuilder is the query builder for SQLite databases. */ - type _sTfBgLP = BaseQueryBuilder - interface SqliteQueryBuilder extends _sTfBgLP { + type _sDHUMAL = BaseQueryBuilder + interface SqliteQueryBuilder extends _sDHUMAL { } interface SqliteQueryBuilder { /** @@ -4112,8 +3658,8 @@ namespace dbx { /** * SqliteBuilder is the builder for SQLite databases. */ - type _shMLFrp = BaseBuilder - interface SqliteBuilder extends _shMLFrp { + type _sEfwqAY = BaseBuilder + interface SqliteBuilder extends _sEfwqAY { } interface newSqliteBuilder { /** @@ -4212,8 +3758,8 @@ namespace dbx { /** * StandardBuilder is the builder that is used by DB for an unknown driver. */ - type _sozwign = BaseBuilder - interface StandardBuilder extends _sozwign { + type _ssbrLtO = BaseBuilder + interface StandardBuilder extends _ssbrLtO { } interface newStandardBuilder { /** @@ -4279,8 +3825,8 @@ namespace dbx { * DB enhances sql.DB by providing a set of DB-agnostic query building methods. * DB allows easier query building and population of data into Go variables. */ - type _sXYniib = Builder - interface DB extends _sXYniib { + type _sDtvvOV = Builder + interface DB extends _sDtvvOV { /** * FieldMapper maps struct fields to DB columns. Defaults to DefaultFieldMapFunc. */ @@ -5110,8 +4656,8 @@ namespace dbx { * Rows enhances sql.Rows by providing additional data query methods. * Rows can be obtained by calling Query.Rows(). It is mainly used to populate data row by row. */ - type _srgmYSe = sql.Rows - interface Rows extends _srgmYSe { + type _sMYwxsv = sql.Rows + interface Rows extends _sMYwxsv { } interface Rows { /** @@ -5486,8 +5032,8 @@ namespace dbx { }): string } interface structInfo { } - type _sCKamzJ = structInfo - interface structValue extends _sCKamzJ { + type _sOzUeAW = structInfo + interface structValue extends _sOzUeAW { } interface fieldInfo { } @@ -5526,8 +5072,8 @@ namespace dbx { /** * Tx enhances sql.Tx with additional querying methods. */ - type _sgihemC = Builder - interface Tx extends _sgihemC { + type _sSyBQus = Builder + interface Tx extends _sSyBQus { } interface Tx { /** @@ -5544,504 +5090,853 @@ namespace dbx { } /** - * Package validation provides configurable and extensible rules for validating data of various types. + * Package filepath implements utility routines for manipulating filename paths + * in a way compatible with the target operating system-defined file paths. + * + * The filepath package uses either forward slashes or backslashes, + * depending on the operating system. To process paths such as URLs + * that always use forward slashes regardless of the operating + * system, see the [path] package. */ -namespace ozzo_validation { - /** - * Error interface represents an validation error - */ - interface Error { - [key:string]: any; - error(): string - code(): string - message(): string - setMessage(_arg0: string): Error - params(): _TygojaDict - setParams(_arg0: _TygojaDict): Error - } -} - -namespace security { - interface s256Challenge { +namespace filepath { + interface match { /** - * S256Challenge creates base64 encoded sha256 challenge string derived from code. - * The padding of the result base64 string is stripped per [RFC 7636]. + * Match reports whether name matches the shell file name pattern. + * The pattern syntax is: * - * [RFC 7636]: https://datatracker.ietf.org/doc/html/rfc7636#section-4.2 - */ - (code: string): string - } - interface md5 { - /** - * MD5 creates md5 hash from the provided plain text. - */ - (text: string): string - } - interface sha256 { - /** - * SHA256 creates sha256 hash as defined in FIPS 180-4 from the provided text. - */ - (text: string): string - } - interface sha512 { - /** - * SHA512 creates sha512 hash as defined in FIPS 180-4 from the provided text. - */ - (text: string): string - } - interface hs256 { - /** - * HS256 creates a HMAC hash with sha256 digest algorithm. + * ``` + * pattern: + * { term } + * term: + * '*' matches any sequence of non-Separator characters + * '?' matches any single non-Separator character + * '[' [ '^' ] { character-range } ']' + * character class (must be non-empty) + * c matches character c (c != '*', '?', '\\', '[') + * '\\' c matches character c (except on Windows) + * + * character-range: + * c matches character c (c != '\\', '-', ']') + * '\\' c matches character c (except on Windows) + * lo '-' hi matches character c for lo <= c <= hi + * ``` + * + * Path segments in the pattern must be separated by [Separator]. + * + * Match requires pattern to match all of name, not just a substring. + * The only possible returned error is [ErrBadPattern], when pattern + * is malformed. + * + * On Windows, escaping is disabled. Instead, '\\' is treated as + * path separator. */ - (text: string, secret: string): string + (pattern: string, name: string): boolean } - interface hs512 { + interface glob { /** - * HS512 creates a HMAC hash with sha512 digest algorithm. + * Glob returns the names of all files matching pattern or nil + * if there is no matching file. The syntax of patterns is the same + * as in [Match]. The pattern may describe hierarchical names such as + * /usr/*\/bin/ed (assuming the [Separator] is '/'). + * + * Glob ignores file system errors such as I/O errors reading directories. + * The only possible returned error is [ErrBadPattern], when pattern + * is malformed. */ - (text: string, secret: string): string + (pattern: string): Array } - interface equal { + interface clean { /** - * Equal compares two hash strings for equality without leaking timing information. - */ - (hash1: string, hash2: string): boolean - } - // @ts-ignore - import crand = rand - interface encrypt { - /** - * Encrypt encrypts "data" with the specified "key" (must be valid 32 char AES key). + * Clean returns the shortest path name equivalent to path + * by purely lexical processing. It applies the following rules + * iteratively until no further processing can be done: * - * This method uses AES-256-GCM block cypher mode. - */ - (data: string|Array, key: string): string - } - interface decrypt { - /** - * Decrypt decrypts encrypted text with key (must be valid 32 chars AES key). + * 1. Replace multiple [Separator] elements with a single one. + * 2. Eliminate each . path name element (the current directory). + * 3. Eliminate each inner .. path name element (the parent directory) + * ``` + * along with the non-.. element that precedes it. + * ``` + * 4. Eliminate .. elements that begin a rooted path: + * ``` + * that is, replace "/.." by "/" at the beginning of a path, + * assuming Separator is '/'. + * ``` * - * This method uses AES-256-GCM block cypher mode. - */ - (cipherText: string, key: string): string|Array - } - interface parseUnverifiedJWT { - /** - * ParseUnverifiedJWT parses JWT and returns its claims - * but DOES NOT verify the signature. + * The returned path ends in a slash only if it represents a root directory, + * such as "/" on Unix or `C:\` on Windows. * - * It verifies only the exp, iat and nbf claims. + * Finally, any occurrences of slash are replaced by Separator. + * + * If the result of this process is an empty string, Clean + * returns the string ".". + * + * On Windows, Clean does not modify the volume name other than to replace + * occurrences of "/" with `\`. + * For example, Clean("//host/share/../x") returns `\\host\share\x`. + * + * See also Rob Pike, “Lexical File Names in Plan 9 or + * Getting Dot-Dot Right,” + * https://9p.io/sys/doc/lexnames.html */ - (token: string): jwt.MapClaims + (path: string): string } - interface parseJWT { + interface isLocal { /** - * ParseJWT verifies and parses JWT and returns its claims. + * IsLocal reports whether path, using lexical analysis only, has all of these properties: + * + * ``` + * - is within the subtree rooted at the directory in which path is evaluated + * - is not an absolute path + * - is not empty + * - on Windows, is not a reserved name such as "NUL" + * ``` + * + * If IsLocal(path) returns true, then + * Join(base, path) will always produce a path contained within base and + * Clean(path) will always produce an unrooted path with no ".." path elements. + * + * IsLocal is a purely lexical operation. + * In particular, it does not account for the effect of any symbolic links + * that may exist in the filesystem. */ - (token: string, verificationKey: string): jwt.MapClaims + (path: string): boolean } - interface newJWT { + interface localize { /** - * NewJWT generates and returns new HS256 signed JWT. + * Localize converts a slash-separated path into an operating system path. + * The input path must be a valid path as reported by [io/fs.ValidPath]. + * + * Localize returns an error if the path cannot be represented by the operating system. + * For example, the path a\b is rejected on Windows, on which \ is a separator + * character and cannot be part of a filename. + * + * The path returned by Localize will always be local, as reported by IsLocal. */ - (payload: jwt.MapClaims, signingKey: string, duration: time.Duration): string + (path: string): string } - // @ts-ignore - import cryptoRand = rand - // @ts-ignore - import mathRand = rand - interface randomString { + interface toSlash { /** - * RandomString generates a cryptographically random string with the specified length. - * - * The generated string matches [A-Za-z0-9]+ and it's transparent to URL-encoding. + * ToSlash returns the result of replacing each separator character + * in path with a slash ('/') character. Multiple separators are + * replaced by multiple slashes. */ - (length: number): string + (path: string): string } - interface randomStringWithAlphabet { + interface fromSlash { /** - * RandomStringWithAlphabet generates a cryptographically random string - * with the specified length and characters set. + * FromSlash returns the result of replacing each slash ('/') character + * in path with a separator character. Multiple slashes are replaced + * by multiple separators. * - * It panics if for some reason rand.Int returns a non-nil error. + * See also the Localize function, which converts a slash-separated path + * as used by the io/fs package to an operating system path. */ - (length: number, alphabet: string): string + (path: string): string } - interface pseudorandomString { + interface splitList { /** - * PseudorandomString generates a pseudorandom string with the specified length. - * - * The generated string matches [A-Za-z0-9]+ and it's transparent to URL-encoding. - * - * For a cryptographically random string (but a little bit slower) use RandomString instead. + * SplitList splits a list of paths joined by the OS-specific [ListSeparator], + * usually found in PATH or GOPATH environment variables. + * Unlike strings.Split, SplitList returns an empty slice when passed an empty + * string. */ - (length: number): string + (path: string): Array } - interface pseudorandomStringWithAlphabet { + interface split { /** - * PseudorandomStringWithAlphabet generates a pseudorandom string - * with the specified length and characters set. - * - * For a cryptographically random (but a little bit slower) use RandomStringWithAlphabet instead. + * Split splits path immediately following the final [Separator], + * separating it into a directory and file name component. + * If there is no Separator in path, Split returns an empty dir + * and file set to path. + * The returned values have the property that path = dir+file. */ - (length: number, alphabet: string): string + (path: string): [string, string] } - interface randomStringByRegex { + interface join { /** - * RandomStringByRegex generates a random string matching the regex pattern. - * If optFlags is not set, fallbacks to [syntax.Perl]. - * - * NB! While the source of the randomness comes from [crypto/rand] this method - * is not recommended to be used on its own in critical secure contexts because - * the generated length could vary too much on the used pattern and may not be - * as secure as simply calling [security.RandomString]. - * If you still insist on using it for such purposes, consider at least - * a large enough minimum length for the generated string, e.g. `[a-z0-9]{30}`. - * - * This function is inspired by github.com/pipe01/revregexp, github.com/lucasjones/reggen and other similar packages. + * Join joins any number of path elements into a single path, + * separating them with an OS specific [Separator]. Empty elements + * are ignored. The result is Cleaned. However, if the argument + * list is empty or all its elements are empty, Join returns + * an empty string. + * On Windows, the result will only be a UNC path if the first + * non-empty element is a UNC path. */ - (pattern: string, ...optFlags: syntax.Flags[]): string - } -} - -namespace filesystem { - /** - * FileReader defines an interface for a file resource reader. - */ - interface FileReader { - [key:string]: any; - open(): io.ReadSeekCloser - } - /** - * File defines a single file [io.ReadSeekCloser] resource. - * - * The file could be from a local path, multipart/form-data header, etc. - */ - interface File { - reader: FileReader - name: string - originalName: string - size: number + (...elem: string[]): string } - interface File { + interface ext { /** - * AsMap implements [core.mapExtractor] and returns a value suitable - * to be used in an API rule expression. + * Ext returns the file name extension used by path. + * The extension is the suffix beginning at the final dot + * in the final element of path; it is empty if there is + * no dot. */ - asMap(): _TygojaDict + (path: string): string } - interface newFileFromPath { + interface evalSymlinks { /** - * NewFileFromPath creates a new File instance from the provided local file path. + * EvalSymlinks returns the path name after the evaluation of any symbolic + * links. + * If path is relative the result will be relative to the current directory, + * unless one of the components is an absolute symbolic link. + * EvalSymlinks calls [Clean] on the result. */ - (path: string): (File) + (path: string): string } - interface newFileFromBytes { + interface isAbs { /** - * NewFileFromBytes creates a new File instance from the provided byte slice. + * IsAbs reports whether the path is absolute. */ - (b: string|Array, name: string): (File) + (path: string): boolean } - interface newFileFromMultipart { + interface abs { /** - * NewFileFromMultipart creates a new File from the provided multipart header. + * Abs returns an absolute representation of path. + * If the path is not absolute it will be joined with the current + * working directory to turn it into an absolute path. The absolute + * path name for a given file is not guaranteed to be unique. + * Abs calls [Clean] on the result. */ - (mh: multipart.FileHeader): (File) + (path: string): string } - interface newFileFromURL { + interface rel { /** - * NewFileFromURL creates a new File from the provided url by - * downloading the resource and load it as BytesReader. - * - * Example + * Rel returns a relative path that is lexically equivalent to targPath when + * joined to basePath with an intervening separator. That is, + * [Join](basePath, Rel(basePath, targPath)) is equivalent to targPath itself. * - * ``` - * ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - * defer cancel() + * The returned path will always be relative to basePath, even if basePath and + * targPath share no elements. Rel calls [Clean] on the result. * - * file, err := filesystem.NewFileFromURL(ctx, "https://example.com/image.png") - * ``` - */ - (ctx: context.Context, url: string): (File) - } - /** - * MultipartReader defines a FileReader from [multipart.FileHeader]. - */ - interface MultipartReader { - header?: multipart.FileHeader - } - interface MultipartReader { - /** - * Open implements the [filesystem.FileReader] interface. + * An error is returned if targPath can't be made relative to basePath + * or if knowing the current working directory would be necessary to compute it. */ - open(): io.ReadSeekCloser + (basePath: string, targPath: string): string } /** - * PathReader defines a FileReader from a local file path. - */ - interface PathReader { - path: string - } - interface PathReader { - /** - * Open implements the [filesystem.FileReader] interface. - */ - open(): io.ReadSeekCloser - } - /** - * BytesReader defines a FileReader from bytes content. + * WalkFunc is the type of the function called by [Walk] to visit each + * file or directory. + * + * The path argument contains the argument to Walk as a prefix. + * That is, if Walk is called with root argument "dir" and finds a file + * named "a" in that directory, the walk function will be called with + * argument "dir/a". + * + * The directory and file are joined with Join, which may clean the + * directory name: if Walk is called with the root argument "x/../dir" + * and finds a file named "a" in that directory, the walk function will + * be called with argument "dir/a", not "x/../dir/a". + * + * The info argument is the fs.FileInfo for the named path. + * + * The error result returned by the function controls how Walk continues. + * If the function returns the special value [SkipDir], Walk skips the + * current directory (path if info.IsDir() is true, otherwise path's + * parent directory). If the function returns the special value [SkipAll], + * Walk skips all remaining files and directories. Otherwise, if the function + * returns a non-nil error, Walk stops entirely and returns that error. + * + * The err argument reports an error related to path, signaling that Walk + * will not walk into that directory. The function can decide how to + * handle that error; as described earlier, returning the error will + * cause Walk to stop walking the entire tree. + * + * Walk calls the function with a non-nil err argument in two cases. + * + * First, if an [os.Lstat] on the root directory or any directory or file + * in the tree fails, Walk calls the function with path set to that + * directory or file's path, info set to nil, and err set to the error + * from os.Lstat. + * + * Second, if a directory's Readdirnames method fails, Walk calls the + * function with path set to the directory's path, info, set to an + * [fs.FileInfo] describing the directory, and err set to the error from + * Readdirnames. */ - interface BytesReader { - bytes: string|Array - } - interface BytesReader { + interface WalkFunc {(path: string, info: fs.FileInfo, err: Error): void } + interface walkDir { /** - * Open implements the [filesystem.FileReader] interface. + * WalkDir walks the file tree rooted at root, calling fn for each file or + * directory in the tree, including root. + * + * All errors that arise visiting files and directories are filtered by fn: + * see the [fs.WalkDirFunc] documentation for details. + * + * The files are walked in lexical order, which makes the output deterministic + * but requires WalkDir to read an entire directory into memory before proceeding + * to walk that directory. + * + * WalkDir does not follow symbolic links. + * + * WalkDir calls fn with paths that use the separator character appropriate + * for the operating system. This is unlike [io/fs.WalkDir], which always + * uses slash separated paths. */ - open(): io.ReadSeekCloser - } - type _sBXnmoz = bytes.Reader - interface bytesReadSeekCloser extends _sBXnmoz { + (root: string, fn: fs.WalkDirFunc): void } - interface bytesReadSeekCloser { + interface walk { /** - * Close implements the [io.ReadSeekCloser] interface. + * Walk walks the file tree rooted at root, calling fn for each file or + * directory in the tree, including root. + * + * All errors that arise visiting files and directories are filtered by fn: + * see the [WalkFunc] documentation for details. + * + * The files are walked in lexical order, which makes the output deterministic + * but requires Walk to read an entire directory into memory before proceeding + * to walk that directory. + * + * Walk does not follow symbolic links. + * + * Walk is less efficient than [WalkDir], introduced in Go 1.16, + * which avoids calling os.Lstat on every visited file or directory. */ - close(): void + (root: string, fn: WalkFunc): void } - /** - * openFuncAsReader defines a FileReader from a bare Open function. - */ - interface openFuncAsReader {(): io.ReadSeekCloser } - interface openFuncAsReader { + interface base { /** - * Open implements the [filesystem.FileReader] interface. + * Base returns the last element of path. + * Trailing path separators are removed before extracting the last element. + * If the path is empty, Base returns ".". + * If the path consists entirely of separators, Base returns a single separator. */ - open(): io.ReadSeekCloser - } - type _sLTIQZF = hook.Event - interface DeleteEvent extends _sLTIQZF { - filesystem?: System - fileKey: string - } - type _ssmagsT = hook.Event - interface NewWriterEvent extends _ssmagsT { - filesystem?: System - fileKey: string - options?: blob.WriterOptions - writer?: blob.Writer // filled only after e.Next() - } - interface System { + (path: string): string } - interface newS3 { + interface dir { /** - * NewS3 initializes a new S3 filesystem instance. + * Dir returns all but the last element of path, typically the path's directory. + * After dropping the final element, Dir calls [Clean] on the path and trailing + * slashes are removed. + * If the path is empty, Dir returns ".". + * If the path consists entirely of separators, Dir returns a single separator. + * The returned path does not end in a separator unless it is the root directory. * - * NB! Make sure to call `Close()` after you are done working with it. + * On Windows, given a volume-only name such as "C:", Dir returns "C:.", + * the current directory on drive C. To obtain the drive's root "C:\", + * use [VolumeName] combined with a separator. */ - (bucketName: string, region: string, endpoint: string, accessKey: string, secretKey: string, s3ForcePathStyle: boolean): (System) + (path: string): string } - interface newLocal { + interface volumeName { /** - * NewLocal initializes a new local filesystem instance. - * - * NB! Make sure to call `Close()` after you are done working with it. + * VolumeName returns leading volume name. + * Given "C:\foo\bar" it returns "C:" on Windows. + * Given "\\host\share\foo" it returns "\\host\share". + * On other platforms it returns "". */ - (dirPath: string): (System) + (path: string): string } - interface System { + interface hasPrefix { /** - * SetContext assigns the specified context to the current filesystem. + * HasPrefix exists for historical compatibility and should not be used. + * + * Deprecated: HasPrefix does not respect path boundaries and + * does not ignore case when required. */ - setContext(ctx: context.Context): void + (p: string, prefix: string): boolean } - interface System { +} + +namespace security { + interface s256Challenge { /** - * Close releases any resources used for the related filesystem. + * S256Challenge creates base64 encoded sha256 challenge string derived from code. + * The padding of the result base64 string is stripped per [RFC 7636]. + * + * [RFC 7636]: https://datatracker.ietf.org/doc/html/rfc7636#section-4.2 */ - close(): void + (code: string): string } - interface System { + interface md5 { /** - * OnNewWriter is a low level hook that is triggered on every new writer initialization - * (aka. when attempting to create a new file with [system.NewWriter] or [system.Upload]). - * - * Note that currently it doesn't trigger on [System.Copy] but this may change in future releases. + * MD5 creates md5 hash from the provided plain text. */ - onNewWriter(): (hook.Hook) + (text: string): string } - interface System { + interface sha256 { /** - * OnDelete is a low level hook that is triggered on every [System.Delete] call. - * - * Note that the hook doesn't fire when a file is being overwritten - * by a new one, because in that case [System.Delete] is not invoked. + * SHA256 creates sha256 hash as defined in FIPS 180-4 from the provided text. */ - onDelete(): (hook.Hook) + (text: string): string } - interface System { + interface sha512 { /** - * Exists checks if file with fileKey path exists or not. + * SHA512 creates sha512 hash as defined in FIPS 180-4 from the provided text. */ - exists(fileKey: string): boolean + (text: string): string } - interface System { + interface hs256 { /** - * Attributes returns the attributes for the file with fileKey path. - * - * If the file doesn't exist it returns ErrNotFound. + * HS256 creates a HMAC hash with sha256 digest algorithm. */ - attributes(fileKey: string): (blob.Attributes) + (text: string, secret: string): string } - interface System { + interface hs512 { /** - * GetReader returns a file content reader for the given fileKey. - * - * NB! Make sure to call Close() on the file after you are done working with it. - * - * If the file doesn't exist returns ErrNotFound. + * HS512 creates a HMAC hash with sha512 digest algorithm. */ - getReader(fileKey: string): (blob.Reader) + (text: string, secret: string): string } - interface System { + interface equal { /** - * Deprecated: Please use GetReader(fileKey) instead. + * Equal compares two hash strings for equality without leaking timing information. */ - getFile(fileKey: string): (blob.Reader) + (hash1: string, hash2: string): boolean } - interface System { + // @ts-ignore + import crand = rand + interface encrypt { /** - * GetReuploadableFile constructs a new reuploadable File value - * from the associated fileKey blob.Reader. - * - * If preserveName is false then the returned File.Name will have - * a new randomly generated suffix, otherwise it will reuse the original one. - * - * This method could be useful in case you want to clone an existing - * Record file and assign it to a new Record (e.g. in a Record duplicate action). + * Encrypt encrypts "data" with the specified "key" (must be valid 32 char AES key). * - * If you simply want to copy an existing file to a new location you - * could check the Copy(srcKey, dstKey) method. + * This method uses AES-256-GCM block cypher mode. */ - getReuploadableFile(fileKey: string, preserveName: boolean): (File) + (data: string|Array, key: string): string } - interface System { + interface decrypt { /** - * Copy copies the file stored at srcKey to dstKey. - * - * If srcKey file doesn't exist, it returns ErrNotFound. + * Decrypt decrypts encrypted text with key (must be valid 32 chars AES key). * - * If dstKey file already exists, it is overwritten. + * This method uses AES-256-GCM block cypher mode. */ - copy(srcKey: string, dstKey: string): void + (cipherText: string, key: string): string|Array } - interface System { + interface parseUnverifiedJWT { /** - * List returns a flat list with info for all files under the specified prefix. + * ParseUnverifiedJWT parses JWT and returns its claims + * but DOES NOT verify the signature. + * + * It verifies only the exp, iat and nbf claims. */ - list(prefix: string): Array<(blob.ListObject | undefined)> + (token: string): jwt.MapClaims } - interface System { + interface parseJWT { /** - * Upload writes content into the fileKey location. + * ParseJWT verifies and parses JWT and returns its claims. */ - upload(content: string|Array, fileKey: string): void + (token: string, verificationKey: string): jwt.MapClaims } - interface System { + interface newJWT { /** - * UploadFile uploads the provided File to the fileKey location. + * NewJWT generates and returns new HS256 signed JWT. */ - uploadFile(file: File, fileKey: string): void + (payload: jwt.MapClaims, signingKey: string, duration: time.Duration): string } - interface System { + // @ts-ignore + import cryptoRand = rand + // @ts-ignore + import mathRand = rand + interface randomString { /** - * UploadMultipart uploads the provided multipart file to the fileKey location. + * RandomString generates a cryptographically random string with the specified length. + * + * The generated string matches [A-Za-z0-9]+ and it's transparent to URL-encoding. */ - uploadMultipart(fh: multipart.FileHeader, fileKey: string): void + (length: number): string } - interface System { + interface randomStringWithAlphabet { /** - * NewWriter returns a new blob.Writer instance allowing direct file - * create from an io.Reader value. + * RandomStringWithAlphabet generates a cryptographically random string + * with the specified length and characters set. * - * If a file with the specified fileKey already exists, it will be replaced. + * It panics if for some reason rand.Int returns a non-nil error. + */ + (length: number, alphabet: string): string + } + interface pseudorandomString { + /** + * PseudorandomString generates a pseudorandom string with the specified length. * - * NB! Make sure to call `Close()` on the resulting writer after you are done working with it. + * The generated string matches [A-Za-z0-9]+ and it's transparent to URL-encoding. * - * Note: If you have a bytes slice, [filesystem.File], or a multipart header value, - * you can check also the Upload* related methods as they are more user-friendly. + * For a cryptographically random string (but a little bit slower) use RandomString instead. + */ + (length: number): string + } + interface pseudorandomStringWithAlphabet { + /** + * PseudorandomStringWithAlphabet generates a pseudorandom string + * with the specified length and characters set. * - * Example: + * For a cryptographically random (but a little bit slower) use RandomStringWithAlphabet instead. + */ + (length: number, alphabet: string): string + } + interface randomStringByRegex { + /** + * RandomStringByRegex generates a random string matching the regex pattern. + * If optFlags is not set, fallbacks to [syntax.Perl]. * - * ``` - * content := strings.NewReader("Lorem ipsum dolor sit amet...") + * NB! While the source of the randomness comes from [crypto/rand] this method + * is not recommended to be used on its own in critical secure contexts because + * the generated length could vary too much on the used pattern and may not be + * as secure as simply calling [security.RandomString]. + * If you still insist on using it for such purposes, consider at least + * a large enough minimum length for the generated string, e.g. `[a-z0-9]{30}`. * - * fsys, _ := filesystem.NewLocal("dir") - * defer fsys.Close() + * This function is inspired by github.com/pipe01/revregexp, github.com/lucasjones/reggen and other similar packages. + */ + (pattern: string, ...optFlags: syntax.Flags[]): string + } +} + +namespace filesystem { + /** + * FileReader defines an interface for a file resource reader. + */ + interface FileReader { + [key:string]: any; + open(): io.ReadSeekCloser + } + /** + * File defines a single file [io.ReadSeekCloser] resource. + * + * The file could be from a local path, multipart/form-data header, etc. + */ + interface File { + reader: FileReader + name: string + originalName: string + size: number + } + interface File { + /** + * AsMap implements [core.mapExtractor] and returns a value suitable + * to be used in an API rule expression. + */ + asMap(): _TygojaDict + } + interface newFileFromPath { + /** + * NewFileFromPath creates a new File instance from the provided local file path. + */ + (path: string): (File) + } + interface newFileFromBytes { + /** + * NewFileFromBytes creates a new File instance from the provided byte slice. + */ + (b: string|Array, name: string): (File) + } + interface newFileFromMultipart { + /** + * NewFileFromMultipart creates a new File from the provided multipart header. + */ + (mh: multipart.FileHeader): (File) + } + interface newFileFromURL { + /** + * NewFileFromURL creates a new File from the provided url by + * downloading the resource and load it as BytesReader. * - * w, _ := fsys.NewWriter("example/file/key", nil) - * w.ReadFrom(content) - * w.Close() + * Example + * + * ``` + * ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + * defer cancel() + * + * file, err := filesystem.NewFileFromURL(ctx, "https://example.com/image.png") * ``` */ - newWriter(fileKey: string, opts: blob.WriterOptions): (blob.Writer) + (ctx: context.Context, url: string): (File) + } + /** + * MultipartReader defines a FileReader from [multipart.FileHeader]. + */ + interface MultipartReader { + header?: multipart.FileHeader + } + interface MultipartReader { + /** + * Open implements the [filesystem.FileReader] interface. + */ + open(): io.ReadSeekCloser + } + /** + * PathReader defines a FileReader from a local file path. + */ + interface PathReader { + path: string + } + interface PathReader { + /** + * Open implements the [filesystem.FileReader] interface. + */ + open(): io.ReadSeekCloser + } + /** + * BytesReader defines a FileReader from bytes content. + */ + interface BytesReader { + bytes: string|Array + } + interface BytesReader { + /** + * Open implements the [filesystem.FileReader] interface. + */ + open(): io.ReadSeekCloser + } + type _sbNoBcY = bytes.Reader + interface bytesReadSeekCloser extends _sbNoBcY { + } + interface bytesReadSeekCloser { + /** + * Close implements the [io.ReadSeekCloser] interface. + */ + close(): void + } + /** + * openFuncAsReader defines a FileReader from a bare Open function. + */ + interface openFuncAsReader {(): io.ReadSeekCloser } + interface openFuncAsReader { + /** + * Open implements the [filesystem.FileReader] interface. + */ + open(): io.ReadSeekCloser + } + type _sLIcpce = hook.Event + interface DeleteEvent extends _sLIcpce { + filesystem?: System + fileKey: string + } + type _sgtQhTO = hook.Event + interface NewWriterEvent extends _sgtQhTO { + filesystem?: System + fileKey: string + options?: blob.WriterOptions + writer?: blob.Writer // filled only after e.Next() } interface System { + } + interface newS3 { /** - * Delete deletes stored file at fileKey location. + * NewS3 initializes a new S3 filesystem instance. * - * If the file doesn't exist returns ErrNotFound. + * NB! Make sure to call `Close()` after you are done working with it. */ - delete(fileKey: string): void + (bucketName: string, region: string, endpoint: string, accessKey: string, secretKey: string, s3ForcePathStyle: boolean): (System) } - interface System { + interface newLocal { /** - * DeletePrefix deletes everything starting with the specified prefix. + * NewLocal initializes a new local filesystem instance. * - * The prefix could be subpath (ex. "/a/b/") or filename prefix (ex. "/a/b/file_"). + * NB! Make sure to call `Close()` after you are done working with it. */ - deletePrefix(prefix: string): Array + (dirPath: string): (System) } interface System { /** - * Checks if the provided dir prefix doesn't have any files. - * - * A trailing slash will be appended to a non-empty dir string argument - * to ensure that the checked prefix is a "directory". - * - * Returns "false" in case it has at least one file, otherwise - "true". + * SetContext assigns the specified context to the current filesystem. */ - isEmptyDir(dir: string): boolean + setContext(ctx: context.Context): void } interface System { /** - * Serve serves the file at fileKey location to an HTTP response. + * Close releases any resources used for the related filesystem. + */ + close(): void + } + interface System { + /** + * OnNewWriter is a low level hook that is triggered on every new writer initialization + * (aka. when attempting to create a new file with [system.NewWriter] or [system.Upload]). * - * If the `download` query parameter is used the file will be always served for - * download no matter of its type (aka. with "Content-Disposition: attachment"). + * Note that currently it doesn't trigger on [System.Copy] but this may change in future releases. + */ + onNewWriter(): (hook.Hook) + } + interface System { + /** + * OnDelete is a low level hook that is triggered on every [System.Delete] call. * - * Internally this method uses [http.ServeContent] so Range requests, - * If-Match, If-Unmodified-Since, etc. headers are handled transparently. + * Note that the hook doesn't fire when a file is being overwritten + * by a new one, because in that case [System.Delete] is not invoked. */ - serve(res: http.ResponseWriter, req: http.Request, fileKey: string, name: string): void + onDelete(): (hook.Hook) } interface System { /** - * CreateThumb creates a new thumb image for the file at originalKey location. - * The new thumb file is stored at thumbKey location. + * Exists checks if file with fileKey path exists or not. + */ + exists(fileKey: string): boolean + } + interface System { + /** + * Attributes returns the attributes for the file with fileKey path. * - * thumbSize is in the format: - * - 0xH (eg. 0x100) - resize to H height preserving the aspect ratio - * - Wx0 (eg. 300x0) - resize to W width preserving the aspect ratio - * - WxH (eg. 300x100) - resize and crop to WxH viewbox (from center) - * - WxHt (eg. 300x100t) - resize and crop to WxH viewbox (from top) - * - WxHb (eg. 300x100b) - resize and crop to WxH viewbox (from bottom) - * - WxHf (eg. 300x100f) - fit inside a WxH viewbox (without cropping) + * If the file doesn't exist it returns ErrNotFound. */ - createThumb(originalKey: string, thumbKey: string, thumbSize: string): void + attributes(fileKey: string): (blob.Attributes) } -} - + interface System { + /** + * GetReader returns a file content reader for the given fileKey. + * + * NB! Make sure to call Close() on the file after you are done working with it. + * + * If the file doesn't exist returns ErrNotFound. + */ + getReader(fileKey: string): (blob.Reader) + } + interface System { + /** + * Deprecated: Please use GetReader(fileKey) instead. + */ + getFile(fileKey: string): (blob.Reader) + } + interface System { + /** + * GetReuploadableFile constructs a new reuploadable File value + * from the associated fileKey blob.Reader. + * + * If preserveName is false then the returned File.Name will have + * a new randomly generated suffix, otherwise it will reuse the original one. + * + * This method could be useful in case you want to clone an existing + * Record file and assign it to a new Record (e.g. in a Record duplicate action). + * + * If you simply want to copy an existing file to a new location you + * could check the Copy(srcKey, dstKey) method. + */ + getReuploadableFile(fileKey: string, preserveName: boolean): (File) + } + interface System { + /** + * Copy copies the file stored at srcKey to dstKey. + * + * If srcKey file doesn't exist, it returns ErrNotFound. + * + * If dstKey file already exists, it is overwritten. + */ + copy(srcKey: string, dstKey: string): void + } + interface System { + /** + * List returns a flat list with info for all files under the specified prefix. + */ + list(prefix: string): Array<(blob.ListObject | undefined)> + } + interface System { + /** + * Upload writes content into the fileKey location. + */ + upload(content: string|Array, fileKey: string): void + } + interface System { + /** + * UploadFile uploads the provided File to the fileKey location. + */ + uploadFile(file: File, fileKey: string): void + } + interface System { + /** + * UploadMultipart uploads the provided multipart file to the fileKey location. + */ + uploadMultipart(fh: multipart.FileHeader, fileKey: string): void + } + interface System { + /** + * NewWriter returns a new blob.Writer instance allowing direct file + * create from an io.Reader value. + * + * If a file with the specified fileKey already exists, it will be replaced. + * + * NB! Make sure to call `Close()` on the resulting writer after you are done working with it. + * + * Note: If you have a bytes slice, [filesystem.File], or a multipart header value, + * you can check also the Upload* related methods as they are more user-friendly. + * + * Example: + * + * ``` + * content := strings.NewReader("Lorem ipsum dolor sit amet...") + * + * fsys, _ := filesystem.NewLocal("dir") + * defer fsys.Close() + * + * w, _ := fsys.NewWriter("example/file/key", nil) + * w.ReadFrom(content) + * w.Close() + * ``` + */ + newWriter(fileKey: string, opts: blob.WriterOptions): (blob.Writer) + } + interface System { + /** + * Delete deletes stored file at fileKey location. + * + * If the file doesn't exist returns ErrNotFound. + */ + delete(fileKey: string): void + } + interface System { + /** + * DeletePrefix deletes everything starting with the specified prefix. + * + * The prefix could be subpath (ex. "/a/b/") or filename prefix (ex. "/a/b/file_"). + */ + deletePrefix(prefix: string): Array + } + interface System { + /** + * Checks if the provided dir prefix doesn't have any files. + * + * A trailing slash will be appended to a non-empty dir string argument + * to ensure that the checked prefix is a "directory". + * + * Returns "false" in case it has at least one file, otherwise - "true". + */ + isEmptyDir(dir: string): boolean + } + interface System { + /** + * Serve serves the file at fileKey location to an HTTP response. + * + * If the `download` query parameter is used the file will be always served for + * download no matter of its type (aka. with "Content-Disposition: attachment"). + * + * Internally this method uses [http.ServeContent] so Range requests, + * If-Match, If-Unmodified-Since, etc. headers are handled transparently. + */ + serve(res: http.ResponseWriter, req: http.Request, fileKey: string, name: string): void + } + interface System { + /** + * CreateThumb creates a new thumb image for the file at originalKey location. + * The new thumb file is stored at thumbKey location. + * + * thumbSize is in the format: + * - 0xH (eg. 0x100) - resize to H height preserving the aspect ratio + * - Wx0 (eg. 300x0) - resize to W width preserving the aspect ratio + * - WxH (eg. 300x100) - resize and crop to WxH viewbox (from center) + * - WxHt (eg. 300x100t) - resize and crop to WxH viewbox (from top) + * - WxHb (eg. 300x100b) - resize and crop to WxH viewbox (from bottom) + * - WxHf (eg. 300x100f) - fit inside a WxH viewbox (without cropping) + */ + createThumb(originalKey: string, thumbKey: string, thumbSize: string): void + } +} + +/** + * Package validation provides configurable and extensible rules for validating data of various types. + */ +namespace ozzo_validation { + /** + * Error interface represents an validation error + */ + interface Error { + [key:string]: any; + error(): string + code(): string + message(): string + setMessage(_arg0: string): Error + params(): _TygojaDict + setParams(_arg0: _TygojaDict): Error + } +} + /** * Package exec runs external commands. It wraps os.StartProcess to make it * easier to remap stdin and stdout, connect I/O with pipes, and do other @@ -7851,8 +7746,8 @@ namespace core { /** * AuthOrigin defines a Record proxy for working with the authOrigins collection. */ - type _sfJGbjT = Record - interface AuthOrigin extends _sfJGbjT { + type _skUTTOQ = Record + interface AuthOrigin extends _skUTTOQ { } interface newAuthOrigin { /** @@ -8623,8 +8518,8 @@ namespace core { * @todo experiment eventually replacing the rules *string with a struct? * @todo consider changing the Indexes field to a "getter" for the sqlite_master table? */ - type _sEQqEtN = BaseModel - interface baseCollection extends _sEQqEtN { + type _sRZkQBb = BaseModel + interface baseCollection extends _sRZkQBb { listRule?: string viewRule?: string createRule?: string @@ -8651,8 +8546,8 @@ namespace core { /** * Collection defines the table, fields and various options related to a set of records. */ - type _sICkDKI = baseCollection&collectionAuthOptions&collectionViewOptions - interface Collection extends _sICkDKI { + type _sVCSHXH = baseCollection&collectionAuthOptions&collectionViewOptions + interface Collection extends _sVCSHXH { } interface newCollection { /** @@ -9674,8 +9569,8 @@ namespace core { /** * RequestEvent defines the PocketBase router handler event. */ - type _sLoInlv = router.Event - interface RequestEvent extends _sLoInlv { + type _sHkEkYp = router.Event + interface RequestEvent extends _sHkEkYp { app: App auth?: Record } @@ -9735,8 +9630,8 @@ namespace core { */ clone(): (RequestInfo) } - type _ssCzTbt = hook.Event&RequestEvent - interface BatchRequestEvent extends _ssCzTbt { + type _sVXRxMa = hook.Event&RequestEvent + interface BatchRequestEvent extends _sVXRxMa { batch: Array<(InternalRequest | undefined)> } interface InternalRequest { @@ -9778,24 +9673,24 @@ namespace core { */ tags(): Array } - type _sVCLqGL = hook.Event - interface BootstrapEvent extends _sVCLqGL { + type _sdxMSqt = hook.Event + interface BootstrapEvent extends _sdxMSqt { app: App } - type _sRTNRbV = hook.Event - interface TerminateEvent extends _sRTNRbV { + type _sqLfYeT = hook.Event + interface TerminateEvent extends _sqLfYeT { app: App isRestart: boolean } - type _sYTokdQ = hook.Event - interface BackupEvent extends _sYTokdQ { + type _sOaKOTX = hook.Event + interface BackupEvent extends _sOaKOTX { app: App context: context.Context name: string // the name of the backup to create/restore. exclude: Array // list of dir entries to exclude from the backup create/restore. } - type _snZkWmy = hook.Event - interface ServeEvent extends _snZkWmy { + type _salbcgr = hook.Event + interface ServeEvent extends _salbcgr { app: App router?: router.Router server?: http.Server @@ -9842,39 +9737,39 @@ namespace core { */ fs: fs.FS } - type _sVWJubz = hook.Event&RequestEvent - interface SettingsListRequestEvent extends _sVWJubz { + type _syMCPRb = hook.Event&RequestEvent + interface SettingsListRequestEvent extends _syMCPRb { settings?: Settings } - type _swVtPXE = hook.Event&RequestEvent - interface SettingsUpdateRequestEvent extends _swVtPXE { + type _sqpIEBm = hook.Event&RequestEvent + interface SettingsUpdateRequestEvent extends _sqpIEBm { oldSettings?: Settings newSettings?: Settings } - type _sAzHzBI = hook.Event - interface SettingsReloadEvent extends _sAzHzBI { + type _sIkzIda = hook.Event + interface SettingsReloadEvent extends _sIkzIda { app: App } - type _sdsOSBn = hook.Event - interface MailerEvent extends _sdsOSBn { + type _sbBRJSa = hook.Event + interface MailerEvent extends _sbBRJSa { app: App mailer: mailer.Mailer message?: mailer.Message } - type _sdozaLu = MailerEvent&baseRecordEventData - interface MailerRecordEvent extends _sdozaLu { + type _sVWOUZa = MailerEvent&baseRecordEventData + interface MailerRecordEvent extends _sVWOUZa { meta: _TygojaDict } - type _sHjaTPY = hook.Event&filesystem.NewWriterEvent - interface FilesystemNewWriterEvent extends _sHjaTPY { + type _sXHptlc = hook.Event&filesystem.NewWriterEvent + interface FilesystemNewWriterEvent extends _sXHptlc { app: App } - type _sTWWrGc = hook.Event&filesystem.DeleteEvent - interface FilesystemDeleteEvent extends _sTWWrGc { + type _sasEdrD = hook.Event&filesystem.DeleteEvent + interface FilesystemDeleteEvent extends _sasEdrD { app: App } - type _sQvqBZX = hook.Event&baseModelEventData - interface ModelEvent extends _sQvqBZX { + type _sHLlOfS = hook.Event&baseModelEventData + interface ModelEvent extends _sHLlOfS { app: App context: context.Context /** @@ -9886,12 +9781,12 @@ namespace core { */ type: string } - type _sbwnsQL = ModelEvent - interface ModelErrorEvent extends _sbwnsQL { + type _saIXSlj = ModelEvent + interface ModelErrorEvent extends _saIXSlj { error: Error } - type _sPmjPej = hook.Event&baseRecordEventData - interface RecordEvent extends _sPmjPej { + type _siDFCDs = hook.Event&baseRecordEventData + interface RecordEvent extends _siDFCDs { app: App context: context.Context /** @@ -9903,12 +9798,12 @@ namespace core { */ type: string } - type _stmeQNY = RecordEvent - interface RecordErrorEvent extends _stmeQNY { + type _sNeIyFn = RecordEvent + interface RecordErrorEvent extends _sNeIyFn { error: Error } - type _sBUTBHa = hook.Event&baseCollectionEventData - interface CollectionEvent extends _sBUTBHa { + type _satfxiI = hook.Event&baseCollectionEventData + interface CollectionEvent extends _satfxiI { app: App context: context.Context /** @@ -9920,16 +9815,16 @@ namespace core { */ type: string } - type _sfVpqel = CollectionEvent - interface CollectionErrorEvent extends _sfVpqel { + type _seQvQwl = CollectionEvent + interface CollectionErrorEvent extends _seQvQwl { error: Error } - type _sSdexPu = hook.Event&RequestEvent&baseRecordEventData - interface FileTokenRequestEvent extends _sSdexPu { + type _sELEntR = hook.Event&RequestEvent&baseRecordEventData + interface FileTokenRequestEvent extends _sELEntR { token: string } - type _sQikLtf = hook.Event&RequestEvent&baseCollectionEventData - interface FileDownloadRequestEvent extends _sQikLtf { + type _sMbHtMV = hook.Event&RequestEvent&baseCollectionEventData + interface FileDownloadRequestEvent extends _sMbHtMV { record?: Record fileField?: FileField servedPath: string @@ -9943,21 +9838,21 @@ namespace core { */ thumbError: Error } - type _snmyceD = hook.Event&RequestEvent - interface CollectionsListRequestEvent extends _snmyceD { + type _savwOak = hook.Event&RequestEvent + interface CollectionsListRequestEvent extends _savwOak { collections: Array<(Collection | undefined)> result?: search.Result } - type _sFsJAMD = hook.Event&RequestEvent - interface CollectionsImportRequestEvent extends _sFsJAMD { + type _slwOFAf = hook.Event&RequestEvent + interface CollectionsImportRequestEvent extends _slwOFAf { collectionsData: Array<_TygojaDict> deleteMissing: boolean } - type _sGApmzZ = hook.Event&RequestEvent&baseCollectionEventData - interface CollectionRequestEvent extends _sGApmzZ { + type _sYHYhOQ = hook.Event&RequestEvent&baseCollectionEventData + interface CollectionRequestEvent extends _sYHYhOQ { } - type _sUqEANN = hook.Event&RequestEvent - interface RealtimeConnectRequestEvent extends _sUqEANN { + type _sMwDzja = hook.Event&RequestEvent + interface RealtimeConnectRequestEvent extends _sMwDzja { client: subscriptions.Client /** * IdleTimeout specifies the max duration to wait for a new message @@ -9981,59 +9876,59 @@ namespace core { */ maxTimeout: time.Duration } - type _ssNHqgV = hook.Event&RequestEvent - interface RealtimeMessageEvent extends _ssNHqgV { + type _sJZEyAl = hook.Event&RequestEvent + interface RealtimeMessageEvent extends _sJZEyAl { client: subscriptions.Client message?: subscriptions.Message } - type _sdqkRYx = hook.Event&RequestEvent - interface RealtimeSubscribeRequestEvent extends _sdqkRYx { + type _sMEZZwx = hook.Event&RequestEvent + interface RealtimeSubscribeRequestEvent extends _sMEZZwx { client: subscriptions.Client subscriptions: Array } - type _srPXSqH = hook.Event&RequestEvent&baseCollectionEventData - interface RecordsListRequestEvent extends _srPXSqH { + type _sOEioim = hook.Event&RequestEvent&baseCollectionEventData + interface RecordsListRequestEvent extends _sOEioim { /** * @todo consider removing and maybe add as generic to the search.Result? */ records: Array<(Record | undefined)> result?: search.Result } - type _sWPZdKP = hook.Event&RequestEvent&baseCollectionEventData - interface RecordRequestEvent extends _sWPZdKP { + type _sYBQkRT = hook.Event&RequestEvent&baseCollectionEventData + interface RecordRequestEvent extends _sYBQkRT { record?: Record } - type _sREXdmH = hook.Event&baseRecordEventData - interface RecordEnrichEvent extends _sREXdmH { + type _sSFyFCB = hook.Event&baseRecordEventData + interface RecordEnrichEvent extends _sSFyFCB { app: App requestInfo?: RequestInfo } - type _szLmvkV = hook.Event&RequestEvent&baseCollectionEventData - interface RecordCreateOTPRequestEvent extends _szLmvkV { + type _smuxffh = hook.Event&RequestEvent&baseCollectionEventData + interface RecordCreateOTPRequestEvent extends _smuxffh { record?: Record password: string } - type _slSPbTV = hook.Event&RequestEvent&baseCollectionEventData - interface RecordAuthWithOTPRequestEvent extends _slSPbTV { + type _sZUkggv = hook.Event&RequestEvent&baseCollectionEventData + interface RecordAuthWithOTPRequestEvent extends _sZUkggv { record?: Record otp?: OTP } - type _seckqwY = hook.Event&RequestEvent&baseCollectionEventData - interface RecordAuthRequestEvent extends _seckqwY { + type _sRMmVNR = hook.Event&RequestEvent&baseCollectionEventData + interface RecordAuthRequestEvent extends _sRMmVNR { record?: Record token: string meta: any authMethod: string } - type _sLNMlVt = hook.Event&RequestEvent&baseCollectionEventData - interface RecordAuthWithPasswordRequestEvent extends _sLNMlVt { + type _siHqObM = hook.Event&RequestEvent&baseCollectionEventData + interface RecordAuthWithPasswordRequestEvent extends _siHqObM { record?: Record identity: string identityField: string password: string } - type _stXxWje = hook.Event&RequestEvent&baseCollectionEventData - interface RecordAuthWithOAuth2RequestEvent extends _stXxWje { + type _sNmEWPY = hook.Event&RequestEvent&baseCollectionEventData + interface RecordAuthWithOAuth2RequestEvent extends _sNmEWPY { providerName: string providerClient: auth.Provider record?: Record @@ -10041,41 +9936,41 @@ namespace core { createData: _TygojaDict isNewRecord: boolean } - type _spZKJzQ = hook.Event&RequestEvent&baseCollectionEventData - interface RecordAuthRefreshRequestEvent extends _spZKJzQ { + type _sNpgBcw = hook.Event&RequestEvent&baseCollectionEventData + interface RecordAuthRefreshRequestEvent extends _sNpgBcw { record?: Record } - type _sVBFeZu = hook.Event&RequestEvent&baseCollectionEventData - interface RecordRequestPasswordResetRequestEvent extends _sVBFeZu { + type _sjZAPbR = hook.Event&RequestEvent&baseCollectionEventData + interface RecordRequestPasswordResetRequestEvent extends _sjZAPbR { record?: Record } - type _suCDuhT = hook.Event&RequestEvent&baseCollectionEventData - interface RecordConfirmPasswordResetRequestEvent extends _suCDuhT { + type _sDxRako = hook.Event&RequestEvent&baseCollectionEventData + interface RecordConfirmPasswordResetRequestEvent extends _sDxRako { record?: Record } - type _sKcMyDE = hook.Event&RequestEvent&baseCollectionEventData - interface RecordRequestVerificationRequestEvent extends _sKcMyDE { + type _skmVfkI = hook.Event&RequestEvent&baseCollectionEventData + interface RecordRequestVerificationRequestEvent extends _skmVfkI { record?: Record } - type _sQPvXky = hook.Event&RequestEvent&baseCollectionEventData - interface RecordConfirmVerificationRequestEvent extends _sQPvXky { + type _soludsJ = hook.Event&RequestEvent&baseCollectionEventData + interface RecordConfirmVerificationRequestEvent extends _soludsJ { record?: Record } - type _sfhfrFW = hook.Event&RequestEvent&baseCollectionEventData - interface RecordRequestEmailChangeRequestEvent extends _sfhfrFW { + type _snewJpv = hook.Event&RequestEvent&baseCollectionEventData + interface RecordRequestEmailChangeRequestEvent extends _snewJpv { record?: Record newEmail: string } - type _sehHzyX = hook.Event&RequestEvent&baseCollectionEventData - interface RecordConfirmEmailChangeRequestEvent extends _sehHzyX { + type _sBQDVcU = hook.Event&RequestEvent&baseCollectionEventData + interface RecordConfirmEmailChangeRequestEvent extends _sBQDVcU { record?: Record newEmail: string } /** * ExternalAuth defines a Record proxy for working with the externalAuths collection. */ - type _syuwsGJ = Record - interface ExternalAuth extends _syuwsGJ { + type _sxwOsja = Record + interface ExternalAuth extends _sxwOsja { } interface newExternalAuth { /** @@ -12618,8 +12513,8 @@ namespace core { interface onlyFieldType { type: string } - type _sttmWKP = Field - interface fieldWithType extends _sttmWKP { + type _sobXxBx = Field + interface fieldWithType extends _sobXxBx { type: string } interface fieldWithType { @@ -12651,8 +12546,8 @@ namespace core { */ scan(value: any): void } - type _sbcFHBG = BaseModel - interface Log extends _sbcFHBG { + type _scHkwNm = BaseModel + interface Log extends _scHkwNm { created: types.DateTime data: types.JSONMap message: string @@ -12707,8 +12602,8 @@ namespace core { /** * MFA defines a Record proxy for working with the mfas collection. */ - type _smwEvgI = Record - interface MFA extends _smwEvgI { + type _sMkWfDf = Record + interface MFA extends _sMkWfDf { } interface newMFA { /** @@ -12930,8 +12825,8 @@ namespace core { /** * OTP defines a Record proxy for working with the otps collection. */ - type _swbrvZi = Record - interface OTP extends _swbrvZi { + type _sfRGgyY = Record + interface OTP extends _sfRGgyY { } interface newOTP { /** @@ -13167,8 +13062,8 @@ namespace core { } interface runner { } - type _sqPHlMA = BaseModel - interface Record extends _sqPHlMA { + type _sRQHOmG = BaseModel + interface Record extends _sRQHOmG { } interface newRecord { /** @@ -13649,8 +13544,8 @@ namespace core { * BaseRecordProxy implements the [RecordProxy] interface and it is intended * to be used as embed to custom user provided Record proxy structs. */ - type _sEhFpjh = Record - interface BaseRecordProxy extends _sEhFpjh { + type _sOhfTQZ = Record + interface BaseRecordProxy extends _sOhfTQZ { } interface BaseRecordProxy { /** @@ -13904,8 +13799,8 @@ namespace core { /** * Settings defines the PocketBase app settings. */ - type _srZnGgE = settings - interface Settings extends _srZnGgE { + type _sDIkKCd = settings + interface Settings extends _sDIkKCd { } interface Settings { /** @@ -14220,8 +14115,8 @@ namespace core { */ string(): string } - type _sWcXSli = BaseModel - interface Param extends _sWcXSli { + type _sGHjOtf = BaseModel + interface Param extends _sGHjOtf { created: types.DateTime updated: types.DateTime value: types.JSONRaw @@ -14762,16 +14657,21 @@ namespace apis { */ (limitBytes: number): (hook.Handler) } - type _sztMYph = io.ReadCloser - interface limitedReader extends _sztMYph { + /** + * maxBytesReader is very similar to the http.MaxBytesReader but support + * rereads and doesn't try to prematurely close the related response + * to allow consequent middlewares to operate correctly. + */ + type _sMwllhP = io.ReadCloser + interface maxBytesReader extends _sMwllhP { } - interface limitedReader { + interface maxBytesReader { read(b: string|Array): number } - interface limitedReader { + interface maxBytesReader { reread(): void } - interface limitedReader { + interface maxBytesReader { close(): void } /** @@ -14917,8 +14817,8 @@ namespace apis { */ (config: GzipConfig): (hook.Handler) } - type _sMUuEDO = http.ResponseWriter&io.Writer - interface gzipResponseWriter extends _sMUuEDO { + type _sFnHZmO = http.ResponseWriter&io.Writer + interface gzipResponseWriter extends _sFnHZmO { } interface gzipResponseWriter { writeHeader(code: number): void @@ -14938,16 +14838,16 @@ namespace apis { interface gzipResponseWriter { unwrap(): http.ResponseWriter } - type _sIlkKLi = sync.RWMutex - interface rateLimiter extends _sIlkKLi { + type _spUUQeD = sync.RWMutex + interface rateLimiter extends _spUUQeD { } /** * @todo evaluate swiching to sliding window with approximation counter similar to Cloudflare. * * rateClient implements fixed window rate limit strategy. */ - type _scUrcgR = sync.Mutex - interface rateClient extends _scUrcgR { + type _sjiUSpY = sync.Mutex + interface rateClient extends _sjiUSpY { } interface realtimeSubscribeForm { clientId: string @@ -15207,8 +15107,8 @@ namespace pocketbase { * It implements [CoreApp] via embedding and all of the app interface methods * could be accessed directly through the instance (eg. PocketBase.DataDir()). */ - type _sJPRheP = CoreApp - interface PocketBase extends _sJPRheP { + type _soNkBgo = CoreApp + interface PocketBase extends _soNkBgo { /** * RootCmd is the main console command */ @@ -15288,46 +15188,151 @@ namespace pocketbase { } /** - * Package sync provides basic synchronization primitives such as mutual - * exclusion locks. Other than the [Once] and [WaitGroup] types, most are intended - * for use by low-level library routines. Higher-level synchronization is - * better done via channels and communication. + * Package template is a thin wrapper around the standard html/template + * and text/template packages that implements a convenient registry to + * load and cache templates on the fly concurrently. * - * Values containing the types defined in this package should not be copied. + * It was created to assist the JSVM plugin HTML rendering, but could be used in other Go code. + * + * Example: + * + * ``` + * registry := template.NewRegistry() + * + * html1, err := registry.LoadFiles( + * // the files set wil be parsed only once and then cached + * "layout.html", + * "content.html", + * ).Render(map[string]any{"name": "John"}) + * + * html2, err := registry.LoadFiles( + * // reuse the already parsed and cached files set + * "layout.html", + * "content.html", + * ).Render(map[string]any{"name": "Jane"}) + * ``` */ -namespace sync { - // @ts-ignore - import isync = sync +namespace template { + interface newRegistry { + /** + * NewRegistry creates and initializes a new templates registry with + * some defaults (eg. global "raw" template function for unescaped HTML). + * + * Use the Registry.Load* methods to load templates into the registry. + */ + (): (Registry) + } /** - * A Mutex is a mutual exclusion lock. - * The zero value for a Mutex is an unlocked mutex. - * - * A Mutex must not be copied after first use. - * - * In the terminology of [the Go memory model], - * the n'th call to [Mutex.Unlock] “synchronizes before” the m'th call to [Mutex.Lock] - * for any n < m. - * A successful call to [Mutex.TryLock] is equivalent to a call to Lock. - * A failed call to TryLock does not establish any “synchronizes before” - * relation at all. + * Registry defines a templates registry that is safe to be used by multiple goroutines. * - * [the Go memory model]: https://go.dev/ref/mem + * Use the Registry.Load* methods to load templates into the registry. */ - interface Mutex { + interface Registry { } - interface Mutex { + interface Registry { /** - * Lock locks m. - * If the lock is already in use, the calling goroutine - * blocks until the mutex is available. + * AddFuncs registers new global template functions. + * + * The key of each map entry is the function name that will be used in the templates. + * If a function with the map entry name already exists it will be replaced with the new one. + * + * The value of each map entry is a function that must have either a + * single return value, or two return values of which the second has type error. + * + * Example: + * + * ``` + * r.AddFuncs(map[string]any{ + * "toUpper": func(str string) string { + * return strings.ToUppser(str) + * }, + * ... + * }) + * ``` */ - lock(): void + addFuncs(funcs: _TygojaDict): (Registry) } - interface Mutex { + interface Registry { /** - * TryLock tries to lock m and reports whether it succeeded. + * LoadFiles caches (if not already) the specified filenames set as a + * single template and returns a ready to use Renderer instance. * - * Note that while correct uses of TryLock do exist, they are rare, + * There must be at least 1 filename specified. + */ + loadFiles(...filenames: string[]): (Renderer) + } + interface Registry { + /** + * LoadString caches (if not already) the specified inline string as a + * single template and returns a ready to use Renderer instance. + */ + loadString(text: string): (Renderer) + } + interface Registry { + /** + * LoadFS caches (if not already) the specified fs and globPatterns + * pair as single template and returns a ready to use Renderer instance. + * + * There must be at least 1 file matching the provided globPattern(s) + * (note that most file names serves as glob patterns matching themselves). + */ + loadFS(fsys: fs.FS, ...globPatterns: string[]): (Renderer) + } + /** + * Renderer defines a single parsed template. + */ + interface Renderer { + } + interface Renderer { + /** + * Render executes the template with the specified data as the dot object + * and returns the result as plain string. + */ + render(data: any): string + } +} + +/** + * Package sync provides basic synchronization primitives such as mutual + * exclusion locks. Other than the [Once] and [WaitGroup] types, most are intended + * for use by low-level library routines. Higher-level synchronization is + * better done via channels and communication. + * + * Values containing the types defined in this package should not be copied. + */ +namespace sync { + // @ts-ignore + import isync = sync + /** + * A Mutex is a mutual exclusion lock. + * The zero value for a Mutex is an unlocked mutex. + * + * A Mutex must not be copied after first use. + * + * In the terminology of [the Go memory model], + * the n'th call to [Mutex.Unlock] “synchronizes before” the m'th call to [Mutex.Lock] + * for any n < m. + * A successful call to [Mutex.TryLock] is equivalent to a call to Lock. + * A failed call to TryLock does not establish any “synchronizes before” + * relation at all. + * + * [the Go memory model]: https://go.dev/ref/mem + */ + interface Mutex { + } + interface Mutex { + /** + * Lock locks m. + * If the lock is already in use, the calling goroutine + * blocks until the mutex is available. + */ + lock(): void + } + interface Mutex { + /** + * TryLock tries to lock m and reports whether it succeeded. + * + * Note that while correct uses of TryLock do exist, they are rare, * and use of TryLock is often a sign of a deeper problem * in a particular use of mutexes. */ @@ -16352,173 +16357,6 @@ namespace time { } } -/** - * Package context defines the Context type, which carries deadlines, - * cancellation signals, and other request-scoped values across API boundaries - * and between processes. - * - * Incoming requests to a server should create a [Context], and outgoing - * calls to servers should accept a Context. The chain of function - * calls between them must propagate the Context, optionally replacing - * it with a derived Context created using [WithCancel], [WithDeadline], - * [WithTimeout], or [WithValue]. - * - * A Context may be canceled to indicate that work done on its behalf should stop. - * A Context with a deadline is canceled after the deadline passes. - * When a Context is canceled, all Contexts derived from it are also canceled. - * - * The [WithCancel], [WithDeadline], and [WithTimeout] functions take a - * Context (the parent) and return a derived Context (the child) and a - * [CancelFunc]. Calling the CancelFunc directly cancels the child and its - * children, removes the parent's reference to the child, and stops - * any associated timers. Failing to call the CancelFunc leaks the - * child and its children until the parent is canceled. The go vet tool - * checks that CancelFuncs are used on all control-flow paths. - * - * The [WithCancelCause] function returns a [CancelCauseFunc], which takes - * an error and records it as the cancellation cause. [WithDeadlineCause] - * and [WithTimeoutCause] take a cause to use when the deadline expires. - * Calling [Cause] on the canceled context or any of its children retrieves - * the cause. If no cause is specified, Cause(ctx) returns the same value - * as ctx.Err(). - * - * Programs that use Contexts should follow these rules to keep interfaces - * consistent across packages and enable static analysis tools to check context - * propagation: - * - * Do not store Contexts inside a struct type; instead, pass a Context - * explicitly to each function that needs it. This is discussed further in - * https://go.dev/blog/context-and-structs. The Context should be the first - * parameter, typically named ctx: - * - * ``` - * func DoSomething(ctx context.Context, arg Arg) error { - * // ... use ctx ... - * } - * ``` - * - * Do not pass a nil [Context], even if a function permits it. Pass [context.TODO] - * if you are unsure about which Context to use. - * - * Use context Values only for request-scoped data that transits processes and - * APIs, not for passing optional parameters to functions. - * - * The same Context may be passed to functions running in different goroutines; - * Contexts are safe for simultaneous use by multiple goroutines. - * - * See https://go.dev/blog/context for example code for a server that uses - * Contexts. - */ -namespace context { - /** - * A Context carries a deadline, a cancellation signal, and other values across - * API boundaries. - * - * Context's methods may be called by multiple goroutines simultaneously. - */ - interface Context { - [key:string]: any; - /** - * Deadline returns the time when work done on behalf of this context - * should be canceled. Deadline returns ok==false when no deadline is - * set. Successive calls to Deadline return the same results. - */ - deadline(): [time.Time, boolean] - /** - * Done returns a channel that's closed when work done on behalf of this - * context should be canceled. Done may return nil if this context can - * never be canceled. Successive calls to Done return the same value. - * The close of the Done channel may happen asynchronously, - * after the cancel function returns. - * - * WithCancel arranges for Done to be closed when cancel is called; - * WithDeadline arranges for Done to be closed when the deadline - * expires; WithTimeout arranges for Done to be closed when the timeout - * elapses. - * - * Done is provided for use in select statements: - * - * // Stream generates values with DoSomething and sends them to out - * // until DoSomething returns an error or ctx.Done is closed. - * func Stream(ctx context.Context, out chan<- Value) error { - * for { - * v, err := DoSomething(ctx) - * if err != nil { - * return err - * } - * select { - * case <-ctx.Done(): - * return ctx.Err() - * case out <- v: - * } - * } - * } - * - * See https://go.dev/blog/pipelines for more examples of how to use - * a Done channel for cancellation. - */ - done(): undefined - /** - * If Done is not yet closed, Err returns nil. - * If Done is closed, Err returns a non-nil error explaining why: - * DeadlineExceeded if the context's deadline passed, - * or Canceled if the context was canceled for some other reason. - * After Err returns a non-nil error, successive calls to Err return the same error. - */ - err(): void - /** - * Value returns the value associated with this context for key, or nil - * if no value is associated with key. Successive calls to Value with - * the same key returns the same result. - * - * Use context values only for request-scoped data that transits - * processes and API boundaries, not for passing optional parameters to - * functions. - * - * A key identifies a specific value in a Context. Functions that wish - * to store values in Context typically allocate a key in a global - * variable then use that key as the argument to context.WithValue and - * Context.Value. A key can be any type that supports equality; - * packages should define keys as an unexported type to avoid - * collisions. - * - * Packages that define a Context key should provide type-safe accessors - * for the values stored using that key: - * - * ``` - * // Package user defines a User type that's stored in Contexts. - * package user - * - * import "context" - * - * // User is the type of value stored in the Contexts. - * type User struct {...} - * - * // key is an unexported type for keys defined in this package. - * // This prevents collisions with keys defined in other packages. - * type key int - * - * // userKey is the key for user.User values in Contexts. It is - * // unexported; clients use user.NewContext and user.FromContext - * // instead of using this key directly. - * var userKey key - * - * // NewContext returns a new Context that carries value u. - * func NewContext(ctx context.Context, u *User) context.Context { - * return context.WithValue(ctx, userKey, u) - * } - * - * // FromContext returns the User value stored in ctx, if any. - * func FromContext(ctx context.Context) (*User, bool) { - * u, ok := ctx.Value(userKey).(*User) - * return u, ok - * } - * ``` - */ - value(key: any): any - } -} - /** * Package fs defines basic interfaces to a file system. * A file system can be provided by the host operating system @@ -16733,3661 +16571,3570 @@ namespace fs { interface WalkDirFunc {(path: string, d: DirEntry, err: Error): void } } -namespace exec { - /** - * Cmd represents an external command being prepared or run. - * - * A Cmd cannot be reused after calling its [Cmd.Start], [Cmd.Run], - * [Cmd.Output], or [Cmd.CombinedOutput] methods. - */ - interface Cmd { - /** - * Path is the path of the command to run. - * - * This is the only field that must be set to a non-zero - * value. If Path is relative, it is evaluated relative - * to Dir. - */ - path: string - /** - * Args holds command line arguments, including the command as Args[0]. - * If the Args field is empty or nil, Run uses {Path}. - * - * In typical use, both Path and Args are set by calling Command. - */ - args: Array +/** + * Package cron implements a crontab-like service to execute and schedule + * repeative tasks/jobs. + * + * Example: + * + * ``` + * c := cron.New() + * c.MustAdd("dailyReport", "0 0 * * *", func() { ... }) + * c.Start() + * ``` + */ +namespace cron { + /** + * Cron is a crontab-like struct for tasks/jobs scheduling. + */ + interface Cron { + } + interface Cron { /** - * Env specifies the environment of the process. - * Each entry is of the form "key=value". - * If Env is nil, the new process uses the current process's - * environment. - * If Env contains duplicate environment keys, only the last - * value in the slice for each duplicate key is used. - * As a special case on Windows, SYSTEMROOT is always added if - * missing and not explicitly set to the empty string. - * - * See also the Dir field, which may set PWD in the environment. + * SetInterval changes the current cron tick interval + * (it usually should be >= 1 minute). */ - env: Array + setInterval(d: time.Duration): void + } + interface Cron { /** - * Dir specifies the working directory of the command. - * If Dir is the empty string, Run runs the command in the - * calling process's current directory. - * - * On Unix systems, the value of Dir also determines the - * child process's PWD environment variable if not otherwise - * specified. A Unix process represents its working directory - * not by name but as an implicit reference to a node in the - * file tree. So, if the child process obtains its working - * directory by calling a function such as C's getcwd, which - * computes the canonical name by walking up the file tree, it - * will not recover the original value of Dir if that value - * was an alias involving symbolic links. However, if the - * child process calls Go's [os.Getwd] or GNU C's - * get_current_dir_name, and the value of PWD is an alias for - * the current directory, those functions will return the - * value of PWD, which matches the value of Dir. + * SetTimezone changes the current cron tick timezone. */ - dir: string + setTimezone(l: time.Location): void + } + interface Cron { /** - * Stdin specifies the process's standard input. - * - * If Stdin is nil, the process reads from the null device (os.DevNull). - * - * If Stdin is an *os.File, the process's standard input is connected - * directly to that file. - * - * Otherwise, during the execution of the command a separate - * goroutine reads from Stdin and delivers that data to the command - * over a pipe. In this case, Wait does not complete until the goroutine - * stops copying, either because it has reached the end of Stdin - * (EOF or a read error), or because writing to the pipe returned an error, - * or because a nonzero WaitDelay was set and expired. - * - * Regardless of WaitDelay, Wait can block until a Read from - * Stdin completes. If you need to use a blocking io.Reader, - * use the StdinPipe method to get a pipe, copy from the Reader - * to the pipe, and arrange to close the Reader after Wait returns. + * MustAdd is similar to Add() but panic on failure. */ - stdin: io.Reader + mustAdd(jobId: string, cronExpr: string, run: () => void): void + } + interface Cron { /** - * Stdout and Stderr specify the process's standard output and error. - * - * If either is nil, Run connects the corresponding file descriptor - * to the null device (os.DevNull). - * - * If either is an *os.File, the corresponding output from the process - * is connected directly to that file. - * - * Otherwise, during the execution of the command a separate goroutine - * reads from the process over a pipe and delivers that data to the - * corresponding Writer. In this case, Wait does not complete until the - * goroutine reaches EOF or encounters an error or a nonzero WaitDelay - * expires. - * - * Regardless of WaitDelay, Wait can block until a Write to - * Stdout or Stderr completes. If you need to use a blocking io.Writer, - * use the StdoutPipe or StderrPipe method to get a pipe, - * copy from the pipe to the Writer, and arrange to close the - * Writer after Wait returns. + * Add registers a single cron job. * - * If Stdout and Stderr are the same writer, and have a type that can - * be compared with ==, at most one goroutine at a time will call Write. - */ - stdout: io.Writer - stderr: io.Writer - /** - * ExtraFiles specifies additional open files to be inherited by the - * new process. It does not include standard input, standard output, or - * standard error. If non-nil, entry i becomes file descriptor 3+i. + * If there is already a job with the provided id, then the old job + * will be replaced with the new one. * - * ExtraFiles is not supported on Windows. - */ - extraFiles: Array<(os.File | undefined)> - /** - * SysProcAttr holds optional, operating system-specific attributes. - * Run passes it to os.StartProcess as the os.ProcAttr's Sys field. - */ - sysProcAttr?: syscall.SysProcAttr - /** - * Process is the underlying process, once started. + * cronExpr is a regular cron expression, eg. "0 *\/3 * * *" (aka. at minute 0 past every 3rd hour). + * Check cron.NewSchedule() for the supported tokens. */ - process?: os.Process + add(jobId: string, cronExpr: string, fn: () => void): void + } + interface Cron { /** - * ProcessState contains information about an exited process. - * If the process was started successfully, Wait or Run will - * populate its ProcessState when the command completes. + * Remove removes a single cron job by its id. */ - processState?: os.ProcessState - err: Error // LookPath error, if any. + remove(jobId: string): void + } + interface Cron { /** - * If Cancel is non-nil, the command must have been created with - * CommandContext and Cancel will be called when the command's - * Context is done. By default, CommandContext sets Cancel to - * call the Kill method on the command's Process. - * - * Typically a custom Cancel will send a signal to the command's - * Process, but it may instead take other actions to initiate cancellation, - * such as closing a stdin or stdout pipe or sending a shutdown request on a - * network socket. - * - * If the command exits with a success status after Cancel is - * called, and Cancel does not return an error equivalent to - * os.ErrProcessDone, then Wait and similar methods will return a non-nil - * error: either an error wrapping the one returned by Cancel, - * or the error from the Context. - * (If the command exits with a non-success status, or Cancel - * returns an error that wraps os.ErrProcessDone, Wait and similar methods - * continue to return the command's usual exit status.) - * - * If Cancel is set to nil, nothing will happen immediately when the command's - * Context is done, but a nonzero WaitDelay will still take effect. That may - * be useful, for example, to work around deadlocks in commands that do not - * support shutdown signals but are expected to always finish quickly. - * - * Cancel will not be called if Start returns a non-nil error. + * RemoveAll removes all registered cron jobs. */ - cancel: () => void + removeAll(): void + } + interface Cron { /** - * If WaitDelay is non-zero, it bounds the time spent waiting on two sources - * of unexpected delay in Wait: a child process that fails to exit after the - * associated Context is canceled, and a child process that exits but leaves - * its I/O pipes unclosed. - * - * The WaitDelay timer starts when either the associated Context is done or a - * call to Wait observes that the child process has exited, whichever occurs - * first. When the delay has elapsed, the command shuts down the child process - * and/or its I/O pipes. - * - * If the child process has failed to exit — perhaps because it ignored or - * failed to receive a shutdown signal from a Cancel function, or because no - * Cancel function was set — then it will be terminated using os.Process.Kill. - * - * Then, if the I/O pipes communicating with the child process are still open, - * those pipes are closed in order to unblock any goroutines currently blocked - * on Read or Write calls. - * - * If pipes are closed due to WaitDelay, no Cancel call has occurred, - * and the command has otherwise exited with a successful status, Wait and - * similar methods will return ErrWaitDelay instead of nil. - * - * If WaitDelay is zero (the default), I/O pipes will be read until EOF, - * which might not occur until orphaned subprocesses of the command have - * also closed their descriptors for the pipes. + * Total returns the current total number of registered cron jobs. */ - waitDelay: time.Duration + total(): number } - interface Cmd { + interface Cron { /** - * String returns a human-readable description of c. - * It is intended only for debugging. - * In particular, it is not suitable for use as input to a shell. - * The output of String may vary across Go releases. + * Jobs returns a shallow copy of the currently registered cron jobs. */ - string(): string + jobs(): Array<(Job | undefined)> } - interface Cmd { + interface Cron { /** - * Run starts the specified command and waits for it to complete. - * - * The returned error is nil if the command runs, has no problems - * copying stdin, stdout, and stderr, and exits with a zero exit - * status. - * - * If the command starts but does not complete successfully, the error is of - * type [*ExitError]. Other error types may be returned for other situations. + * Stop stops the current cron ticker (if not already). * - * If the calling goroutine has locked the operating system thread - * with [runtime.LockOSThread] and modified any inheritable OS-level - * thread state (for example, Linux or Plan 9 name spaces), the new - * process will inherit the caller's thread state. + * You can resume the ticker by calling Start(). */ - run(): void + stop(): void } - interface Cmd { + interface Cron { /** - * Start starts the specified command but does not wait for it to complete. - * - * If Start returns successfully, the c.Process field will be set. + * Start starts the cron ticker. * - * After a successful call to Start the [Cmd.Wait] method must be called in - * order to release associated system resources. + * Calling Start() on already started cron will restart the ticker. */ start(): void } - interface Cmd { + interface Cron { /** - * Wait waits for the command to exit and waits for any copying to - * stdin or copying from stdout or stderr to complete. - * - * The command must have been started by [Cmd.Start]. - * - * The returned error is nil if the command runs, has no problems - * copying stdin, stdout, and stderr, and exits with a zero exit - * status. - * - * If the command fails to run or doesn't complete successfully, the - * error is of type [*ExitError]. Other error types may be - * returned for I/O problems. - * - * If any of c.Stdin, c.Stdout or c.Stderr are not an [*os.File], Wait also waits - * for the respective I/O loop copying to or from the process to complete. - * - * Wait must not be called concurrently from multiple goroutines. - * A custom Cmd.Cancel function should not call Wait. - * - * Wait releases any resources associated with the [Cmd]. - */ - wait(): void - } - interface Cmd { - /** - * Output runs the command and returns its standard output. - * Any returned error will usually be of type [*ExitError]. - * If c.Stderr was nil and the returned error is of type - * [*ExitError], Output populates the Stderr field of the - * returned error. - */ - output(): string|Array - } - interface Cmd { - /** - * CombinedOutput runs the command and returns its combined standard - * output and standard error. - */ - combinedOutput(): string|Array - } - interface Cmd { - /** - * StdinPipe returns a pipe that will be connected to the command's - * standard input when the command starts. - * The pipe will be closed automatically after [Cmd.Wait] sees the command exit. - * A caller need only call Close to force the pipe to close sooner. - * For example, if the command being run will not exit until standard input - * is closed, the caller must close the pipe. - */ - stdinPipe(): io.WriteCloser - } - interface Cmd { - /** - * StdoutPipe returns a pipe that will be connected to the command's - * standard output when the command starts. - * - * [Cmd.Wait] will close the pipe after seeing the command exit, so most callers - * need not close the pipe themselves. It is thus incorrect to call Wait - * before all reads from the pipe have completed. - * For the same reason, it is incorrect to call [Cmd.Run] when using StdoutPipe. - * See the example for idiomatic usage. - */ - stdoutPipe(): io.ReadCloser - } - interface Cmd { - /** - * StderrPipe returns a pipe that will be connected to the command's - * standard error when the command starts. - * - * [Cmd.Wait] will close the pipe after seeing the command exit, so most callers - * need not close the pipe themselves. It is thus incorrect to call Wait - * before all reads from the pipe have completed. - * For the same reason, it is incorrect to use [Cmd.Run] when using StderrPipe. - * See the StdoutPipe example for idiomatic usage. - */ - stderrPipe(): io.ReadCloser - } - interface Cmd { - /** - * Environ returns a copy of the environment in which the command would be run - * as it is currently configured. + * HasStarted checks whether the current Cron ticker has been started. */ - environ(): Array + hasStarted(): boolean } } /** - * Package sql provides a generic interface around SQL (or SQL-like) - * databases. + * Package syntax parses regular expressions into parse trees and compiles + * parse trees into programs. Most clients of regular expressions will use the + * facilities of package [regexp] (such as [regexp.Compile] and [regexp.Match]) instead of this package. * - * The sql package must be used in conjunction with a database driver. - * See https://golang.org/s/sqldrivers for a list of drivers. + * # Syntax * - * Drivers that do not support context cancellation will not return until - * after the query is completed. + * The regular expression syntax understood by this package when parsing with the [Perl] flag is as follows. + * Parts of the syntax can be disabled by passing alternate flags to [Parse]. * - * For usage examples, see the wiki page at - * https://golang.org/s/sqlwiki. + * Single characters: + * + * ``` + * . any character, possibly including newline (flag s=true) + * [xyz] character class + * [^xyz] negated character class + * \d Perl character class + * \D negated Perl character class + * [[:alpha:]] ASCII character class + * [[:^alpha:]] negated ASCII character class + * \pN Unicode character class (one-letter name) + * \p{Greek} Unicode character class + * \PN negated Unicode character class (one-letter name) + * \P{Greek} negated Unicode character class + * ``` + * + * Composites: + * + * ``` + * xy x followed by y + * x|y x or y (prefer x) + * ``` + * + * Repetitions: + * + * ``` + * x* zero or more x, prefer more + * x+ one or more x, prefer more + * x? zero or one x, prefer one + * x{n,m} n or n+1 or ... or m x, prefer more + * x{n,} n or more x, prefer more + * x{n} exactly n x + * x*? zero or more x, prefer fewer + * x+? one or more x, prefer fewer + * x?? zero or one x, prefer zero + * x{n,m}? n or n+1 or ... or m x, prefer fewer + * x{n,}? n or more x, prefer fewer + * x{n}? exactly n x + * ``` + * + * Implementation restriction: The counting forms x{n,m}, x{n,}, and x{n} + * reject forms that create a minimum or maximum repetition count above 1000. + * Unlimited repetitions are not subject to this restriction. + * + * Grouping: + * + * ``` + * (re) numbered capturing group (submatch) + * (?Pre) named & numbered capturing group (submatch) + * (?re) named & numbered capturing group (submatch) + * (?:re) non-capturing group + * (?flags) set flags within current group; non-capturing + * (?flags:re) set flags during re; non-capturing + * + * Flag syntax is xyz (set) or -xyz (clear) or xy-z (set xy, clear z). The flags are: + * + * i case-insensitive (default false) + * m multi-line mode: ^ and $ match begin/end line in addition to begin/end text (default false) + * s let . match \n (default false) + * U ungreedy: swap meaning of x* and x*?, x+ and x+?, etc (default false) + * ``` + * + * Empty strings: + * + * ``` + * ^ at beginning of text or line (flag m=true) + * $ at end of text (like \z not \Z) or line (flag m=true) + * \A at beginning of text + * \b at ASCII word boundary (\w on one side and \W, \A, or \z on the other) + * \B not at ASCII word boundary + * \z at end of text + * ``` + * + * Escape sequences: + * + * ``` + * \a bell (== \007) + * \f form feed (== \014) + * \t horizontal tab (== \011) + * \n newline (== \012) + * \r carriage return (== \015) + * \v vertical tab character (== \013) + * \* literal *, for any punctuation character * + * \123 octal character code (up to three digits) + * \x7F hex character code (exactly two digits) + * \x{10FFFF} hex character code + * \Q...\E literal text ... even if ... has punctuation + * ``` + * + * Character class elements: + * + * ``` + * x single character + * A-Z character range (inclusive) + * \d Perl character class + * [:foo:] ASCII character class foo + * \p{Foo} Unicode character class Foo + * \pF Unicode character class F (one-letter name) + * ``` + * + * Named character classes as character class elements: + * + * ``` + * [\d] digits (== \d) + * [^\d] not digits (== \D) + * [\D] not digits (== \D) + * [^\D] not not digits (== \d) + * [[:name:]] named ASCII class inside character class (== [:name:]) + * [^[:name:]] named ASCII class inside negated character class (== [:^name:]) + * [\p{Name}] named Unicode property inside character class (== \p{Name}) + * [^\p{Name}] named Unicode property inside negated character class (== \P{Name}) + * ``` + * + * Perl character classes (all ASCII-only): + * + * ``` + * \d digits (== [0-9]) + * \D not digits (== [^0-9]) + * \s whitespace (== [\t\n\f\r ]) + * \S not whitespace (== [^\t\n\f\r ]) + * \w word characters (== [0-9A-Za-z_]) + * \W not word characters (== [^0-9A-Za-z_]) + * ``` + * + * ASCII character classes: + * + * ``` + * [[:alnum:]] alphanumeric (== [0-9A-Za-z]) + * [[:alpha:]] alphabetic (== [A-Za-z]) + * [[:ascii:]] ASCII (== [\x00-\x7F]) + * [[:blank:]] blank (== [\t ]) + * [[:cntrl:]] control (== [\x00-\x1F\x7F]) + * [[:digit:]] digits (== [0-9]) + * [[:graph:]] graphical (== [!-~] == [A-Za-z0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~]) + * [[:lower:]] lower case (== [a-z]) + * [[:print:]] printable (== [ -~] == [ [:graph:]]) + * [[:punct:]] punctuation (== [!-/:-@[-`{-~]) + * [[:space:]] whitespace (== [\t\n\v\f\r ]) + * [[:upper:]] upper case (== [A-Z]) + * [[:word:]] word characters (== [0-9A-Za-z_]) + * [[:xdigit:]] hex digit (== [0-9A-Fa-f]) + * ``` + * + * Unicode character classes are those in [unicode.Categories], + * [unicode.CategoryAliases], and [unicode.Scripts]. */ -namespace sql { +namespace syntax { /** - * TxOptions holds the transaction options to be used in [DB.BeginTx]. + * Flags control the behavior of the parser and record information about regexp context. */ - interface TxOptions { - /** - * Isolation is the transaction isolation level. - * If zero, the driver or database's default level is used. - */ - isolation: IsolationLevel - readOnly: boolean - } - /** - * NullString represents a string that may be null. - * NullString implements the [Scanner] interface so - * it can be used as a scan destination: - * - * ``` - * var s NullString - * err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&s) - * ... - * if s.Valid { - * // use s.String - * } else { - * // NULL value - * } - * ``` - */ - interface NullString { - string: string - valid: boolean // Valid is true if String is not NULL - } - interface NullString { - /** - * Scan implements the [Scanner] interface. - */ - scan(value: any): void - } - interface NullString { - /** - * Value implements the [driver.Valuer] interface. - */ - value(): any - } - /** - * DB is a database handle representing a pool of zero or more - * underlying connections. It's safe for concurrent use by multiple - * goroutines. - * - * The sql package creates and frees connections automatically; it - * also maintains a free pool of idle connections. If the database has - * a concept of per-connection state, such state can be reliably observed - * within a transaction ([Tx]) or connection ([Conn]). Once [DB.Begin] is called, the - * returned [Tx] is bound to a single connection. Once [Tx.Commit] or - * [Tx.Rollback] is called on the transaction, that transaction's - * connection is returned to [DB]'s idle connection pool. The pool size - * can be controlled with [DB.SetMaxIdleConns]. - */ - interface DB { - } - interface DB { - /** - * PingContext verifies a connection to the database is still alive, - * establishing a connection if necessary. - */ - pingContext(ctx: context.Context): void - } - interface DB { - /** - * Ping verifies a connection to the database is still alive, - * establishing a connection if necessary. - * - * Ping uses [context.Background] internally; to specify the context, use - * [DB.PingContext]. - */ - ping(): void - } - interface DB { - /** - * Close closes the database and prevents new queries from starting. - * Close then waits for all queries that have started processing on the server - * to finish. - * - * It is rare to Close a [DB], as the [DB] handle is meant to be - * long-lived and shared between many goroutines. - */ - close(): void - } - interface DB { - /** - * SetMaxIdleConns sets the maximum number of connections in the idle - * connection pool. - * - * If MaxOpenConns is greater than 0 but less than the new MaxIdleConns, - * then the new MaxIdleConns will be reduced to match the MaxOpenConns limit. - * - * If n <= 0, no idle connections are retained. - * - * The default max idle connections is currently 2. This may change in - * a future release. - */ - setMaxIdleConns(n: number): void - } - interface DB { - /** - * SetMaxOpenConns sets the maximum number of open connections to the database. - * - * If MaxIdleConns is greater than 0 and the new MaxOpenConns is less than - * MaxIdleConns, then MaxIdleConns will be reduced to match the new - * MaxOpenConns limit. - * - * If n <= 0, then there is no limit on the number of open connections. - * The default is 0 (unlimited). - */ - setMaxOpenConns(n: number): void - } - interface DB { - /** - * SetConnMaxLifetime sets the maximum amount of time a connection may be reused. - * - * Expired connections may be closed lazily before reuse. - * - * If d <= 0, connections are not closed due to a connection's age. - */ - setConnMaxLifetime(d: time.Duration): void - } - interface DB { - /** - * SetConnMaxIdleTime sets the maximum amount of time a connection may be idle. - * - * Expired connections may be closed lazily before reuse. - * - * If d <= 0, connections are not closed due to a connection's idle time. - */ - setConnMaxIdleTime(d: time.Duration): void - } - interface DB { - /** - * Stats returns database statistics. - */ - stats(): DBStats - } - interface DB { - /** - * PrepareContext creates a prepared statement for later queries or executions. - * Multiple queries or executions may be run concurrently from the - * returned statement. - * The caller must call the statement's [*Stmt.Close] method - * when the statement is no longer needed. - * - * The provided context is used for the preparation of the statement, not for the - * execution of the statement. - */ - prepareContext(ctx: context.Context, query: string): (Stmt) - } - interface DB { - /** - * Prepare creates a prepared statement for later queries or executions. - * Multiple queries or executions may be run concurrently from the - * returned statement. - * The caller must call the statement's [*Stmt.Close] method - * when the statement is no longer needed. - * - * Prepare uses [context.Background] internally; to specify the context, use - * [DB.PrepareContext]. - */ - prepare(query: string): (Stmt) - } - interface DB { - /** - * ExecContext executes a query without returning any rows. - * The args are for any placeholder parameters in the query. - */ - execContext(ctx: context.Context, query: string, ...args: any[]): Result - } - interface DB { - /** - * Exec executes a query without returning any rows. - * The args are for any placeholder parameters in the query. - * - * Exec uses [context.Background] internally; to specify the context, use - * [DB.ExecContext]. - */ - exec(query: string, ...args: any[]): Result - } - interface DB { - /** - * QueryContext executes a query that returns rows, typically a SELECT. - * The args are for any placeholder parameters in the query. - */ - queryContext(ctx: context.Context, query: string, ...args: any[]): (Rows) - } - interface DB { - /** - * Query executes a query that returns rows, typically a SELECT. - * The args are for any placeholder parameters in the query. - * - * Query uses [context.Background] internally; to specify the context, use - * [DB.QueryContext]. - */ - query(query: string, ...args: any[]): (Rows) - } - interface DB { - /** - * QueryRowContext executes a query that is expected to return at most one row. - * QueryRowContext always returns a non-nil value. Errors are deferred until - * [Row]'s Scan method is called. - * If the query selects no rows, the [*Row.Scan] will return [ErrNoRows]. - * Otherwise, [*Row.Scan] scans the first selected row and discards - * the rest. - */ - queryRowContext(ctx: context.Context, query: string, ...args: any[]): (Row) - } - interface DB { - /** - * QueryRow executes a query that is expected to return at most one row. - * QueryRow always returns a non-nil value. Errors are deferred until - * [Row]'s Scan method is called. - * If the query selects no rows, the [*Row.Scan] will return [ErrNoRows]. - * Otherwise, [*Row.Scan] scans the first selected row and discards - * the rest. - * - * QueryRow uses [context.Background] internally; to specify the context, use - * [DB.QueryRowContext]. - */ - queryRow(query: string, ...args: any[]): (Row) - } - interface DB { - /** - * BeginTx starts a transaction. - * - * The provided context is used until the transaction is committed or rolled back. - * If the context is canceled, the sql package will roll back - * the transaction. [Tx.Commit] will return an error if the context provided to - * BeginTx is canceled. - * - * The provided [TxOptions] is optional and may be nil if defaults should be used. - * If a non-default isolation level is used that the driver doesn't support, - * an error will be returned. - */ - beginTx(ctx: context.Context, opts: TxOptions): (Tx) - } - interface DB { - /** - * Begin starts a transaction. The default isolation level is dependent on - * the driver. - * - * Begin uses [context.Background] internally; to specify the context, use - * [DB.BeginTx]. - */ - begin(): (Tx) - } - interface DB { - /** - * Driver returns the database's underlying driver. - */ - driver(): any - } - interface DB { - /** - * Conn returns a single connection by either opening a new connection - * or returning an existing connection from the connection pool. Conn will - * block until either a connection is returned or ctx is canceled. - * Queries run on the same Conn will be run in the same database session. - * - * Every Conn must be returned to the database pool after use by - * calling [Conn.Close]. - */ - conn(ctx: context.Context): (Conn) - } + interface Flags extends Number{} +} + +/** + * Package context defines the Context type, which carries deadlines, + * cancellation signals, and other request-scoped values across API boundaries + * and between processes. + * + * Incoming requests to a server should create a [Context], and outgoing + * calls to servers should accept a Context. The chain of function + * calls between them must propagate the Context, optionally replacing + * it with a derived Context created using [WithCancel], [WithDeadline], + * [WithTimeout], or [WithValue]. + * + * A Context may be canceled to indicate that work done on its behalf should stop. + * A Context with a deadline is canceled after the deadline passes. + * When a Context is canceled, all Contexts derived from it are also canceled. + * + * The [WithCancel], [WithDeadline], and [WithTimeout] functions take a + * Context (the parent) and return a derived Context (the child) and a + * [CancelFunc]. Calling the CancelFunc directly cancels the child and its + * children, removes the parent's reference to the child, and stops + * any associated timers. Failing to call the CancelFunc leaks the + * child and its children until the parent is canceled. The go vet tool + * checks that CancelFuncs are used on all control-flow paths. + * + * The [WithCancelCause] function returns a [CancelCauseFunc], which takes + * an error and records it as the cancellation cause. [WithDeadlineCause] + * and [WithTimeoutCause] take a cause to use when the deadline expires. + * Calling [Cause] on the canceled context or any of its children retrieves + * the cause. If no cause is specified, Cause(ctx) returns the same value + * as ctx.Err(). + * + * Programs that use Contexts should follow these rules to keep interfaces + * consistent across packages and enable static analysis tools to check context + * propagation: + * + * Do not store Contexts inside a struct type; instead, pass a Context + * explicitly to each function that needs it. This is discussed further in + * https://go.dev/blog/context-and-structs. The Context should be the first + * parameter, typically named ctx: + * + * ``` + * func DoSomething(ctx context.Context, arg Arg) error { + * // ... use ctx ... + * } + * ``` + * + * Do not pass a nil [Context], even if a function permits it. Pass [context.TODO] + * if you are unsure about which Context to use. + * + * Use context Values only for request-scoped data that transits processes and + * APIs, not for passing optional parameters to functions. + * + * The same Context may be passed to functions running in different goroutines; + * Contexts are safe for simultaneous use by multiple goroutines. + * + * See https://go.dev/blog/context for example code for a server that uses + * Contexts. + */ +namespace context { /** - * Tx is an in-progress database transaction. - * - * A transaction must end with a call to [Tx.Commit] or [Tx.Rollback]. - * - * After a call to [Tx.Commit] or [Tx.Rollback], all operations on the - * transaction fail with [ErrTxDone]. + * A Context carries a deadline, a cancellation signal, and other values across + * API boundaries. * - * The statements prepared for a transaction by calling - * the transaction's [Tx.Prepare] or [Tx.Stmt] methods are closed - * by the call to [Tx.Commit] or [Tx.Rollback]. + * Context's methods may be called by multiple goroutines simultaneously. */ - interface Tx { - } - interface Tx { - /** - * Commit commits the transaction. - */ - commit(): void - } - interface Tx { - /** - * Rollback aborts the transaction. - */ - rollback(): void - } - interface Tx { - /** - * PrepareContext creates a prepared statement for use within a transaction. - * - * The returned statement operates within the transaction and will be closed - * when the transaction has been committed or rolled back. - * - * To use an existing prepared statement on this transaction, see [Tx.Stmt]. - * - * The provided context will be used for the preparation of the context, not - * for the execution of the returned statement. The returned statement - * will run in the transaction context. - */ - prepareContext(ctx: context.Context, query: string): (Stmt) - } - interface Tx { - /** - * Prepare creates a prepared statement for use within a transaction. - * - * The returned statement operates within the transaction and will be closed - * when the transaction has been committed or rolled back. - * - * To use an existing prepared statement on this transaction, see [Tx.Stmt]. - * - * Prepare uses [context.Background] internally; to specify the context, use - * [Tx.PrepareContext]. - */ - prepare(query: string): (Stmt) - } - interface Tx { - /** - * StmtContext returns a transaction-specific prepared statement from - * an existing statement. - * - * Example: - * - * ``` - * updateMoney, err := db.Prepare("UPDATE balance SET money=money+? WHERE id=?") - * ... - * tx, err := db.Begin() - * ... - * res, err := tx.StmtContext(ctx, updateMoney).Exec(123.45, 98293203) - * ``` - * - * The provided context is used for the preparation of the statement, not for the - * execution of the statement. - * - * The returned statement operates within the transaction and will be closed - * when the transaction has been committed or rolled back. - */ - stmtContext(ctx: context.Context, stmt: Stmt): (Stmt) - } - interface Tx { - /** - * Stmt returns a transaction-specific prepared statement from - * an existing statement. - * - * Example: - * - * ``` - * updateMoney, err := db.Prepare("UPDATE balance SET money=money+? WHERE id=?") - * ... - * tx, err := db.Begin() - * ... - * res, err := tx.Stmt(updateMoney).Exec(123.45, 98293203) - * ``` - * - * The returned statement operates within the transaction and will be closed - * when the transaction has been committed or rolled back. - * - * Stmt uses [context.Background] internally; to specify the context, use - * [Tx.StmtContext]. - */ - stmt(stmt: Stmt): (Stmt) - } - interface Tx { - /** - * ExecContext executes a query that doesn't return rows. - * For example: an INSERT and UPDATE. - */ - execContext(ctx: context.Context, query: string, ...args: any[]): Result - } - interface Tx { - /** - * Exec executes a query that doesn't return rows. - * For example: an INSERT and UPDATE. - * - * Exec uses [context.Background] internally; to specify the context, use - * [Tx.ExecContext]. - */ - exec(query: string, ...args: any[]): Result - } - interface Tx { + interface Context { + [key:string]: any; /** - * QueryContext executes a query that returns rows, typically a SELECT. + * Deadline returns the time when work done on behalf of this context + * should be canceled. Deadline returns ok==false when no deadline is + * set. Successive calls to Deadline return the same results. */ - queryContext(ctx: context.Context, query: string, ...args: any[]): (Rows) - } - interface Tx { + deadline(): [time.Time, boolean] /** - * Query executes a query that returns rows, typically a SELECT. + * Done returns a channel that's closed when work done on behalf of this + * context should be canceled. Done may return nil if this context can + * never be canceled. Successive calls to Done return the same value. + * The close of the Done channel may happen asynchronously, + * after the cancel function returns. * - * Query uses [context.Background] internally; to specify the context, use - * [Tx.QueryContext]. - */ - query(query: string, ...args: any[]): (Rows) - } - interface Tx { - /** - * QueryRowContext executes a query that is expected to return at most one row. - * QueryRowContext always returns a non-nil value. Errors are deferred until - * [Row]'s Scan method is called. - * If the query selects no rows, the [*Row.Scan] will return [ErrNoRows]. - * Otherwise, the [*Row.Scan] scans the first selected row and discards - * the rest. - */ - queryRowContext(ctx: context.Context, query: string, ...args: any[]): (Row) - } - interface Tx { - /** - * QueryRow executes a query that is expected to return at most one row. - * QueryRow always returns a non-nil value. Errors are deferred until - * [Row]'s Scan method is called. - * If the query selects no rows, the [*Row.Scan] will return [ErrNoRows]. - * Otherwise, the [*Row.Scan] scans the first selected row and discards - * the rest. + * WithCancel arranges for Done to be closed when cancel is called; + * WithDeadline arranges for Done to be closed when the deadline + * expires; WithTimeout arranges for Done to be closed when the timeout + * elapses. * - * QueryRow uses [context.Background] internally; to specify the context, use - * [Tx.QueryRowContext]. - */ - queryRow(query: string, ...args: any[]): (Row) - } - /** - * Stmt is a prepared statement. - * A Stmt is safe for concurrent use by multiple goroutines. - * - * If a Stmt is prepared on a [Tx] or [Conn], it will be bound to a single - * underlying connection forever. If the [Tx] or [Conn] closes, the Stmt will - * become unusable and all operations will return an error. - * If a Stmt is prepared on a [DB], it will remain usable for the lifetime of the - * [DB]. When the Stmt needs to execute on a new underlying connection, it will - * prepare itself on the new connection automatically. - */ - interface Stmt { - } - interface Stmt { - /** - * ExecContext executes a prepared statement with the given arguments and - * returns a [Result] summarizing the effect of the statement. - */ - execContext(ctx: context.Context, ...args: any[]): Result - } - interface Stmt { - /** - * Exec executes a prepared statement with the given arguments and - * returns a [Result] summarizing the effect of the statement. + * Done is provided for use in select statements: * - * Exec uses [context.Background] internally; to specify the context, use - * [Stmt.ExecContext]. - */ - exec(...args: any[]): Result - } - interface Stmt { - /** - * QueryContext executes a prepared query statement with the given arguments - * and returns the query results as a [*Rows]. - */ - queryContext(ctx: context.Context, ...args: any[]): (Rows) - } - interface Stmt { - /** - * Query executes a prepared query statement with the given arguments - * and returns the query results as a *Rows. + * // Stream generates values with DoSomething and sends them to out + * // until DoSomething returns an error or ctx.Done is closed. + * func Stream(ctx context.Context, out chan<- Value) error { + * for { + * v, err := DoSomething(ctx) + * if err != nil { + * return err + * } + * select { + * case <-ctx.Done(): + * return ctx.Err() + * case out <- v: + * } + * } + * } * - * Query uses [context.Background] internally; to specify the context, use - * [Stmt.QueryContext]. + * See https://go.dev/blog/pipelines for more examples of how to use + * a Done channel for cancellation. */ - query(...args: any[]): (Rows) - } - interface Stmt { + done(): undefined /** - * QueryRowContext executes a prepared query statement with the given arguments. - * If an error occurs during the execution of the statement, that error will - * be returned by a call to Scan on the returned [*Row], which is always non-nil. - * If the query selects no rows, the [*Row.Scan] will return [ErrNoRows]. - * Otherwise, the [*Row.Scan] scans the first selected row and discards - * the rest. + * If Done is not yet closed, Err returns nil. + * If Done is closed, Err returns a non-nil error explaining why: + * DeadlineExceeded if the context's deadline passed, + * or Canceled if the context was canceled for some other reason. + * After Err returns a non-nil error, successive calls to Err return the same error. */ - queryRowContext(ctx: context.Context, ...args: any[]): (Row) - } - interface Stmt { + err(): void /** - * QueryRow executes a prepared query statement with the given arguments. - * If an error occurs during the execution of the statement, that error will - * be returned by a call to Scan on the returned [*Row], which is always non-nil. - * If the query selects no rows, the [*Row.Scan] will return [ErrNoRows]. - * Otherwise, the [*Row.Scan] scans the first selected row and discards - * the rest. + * Value returns the value associated with this context for key, or nil + * if no value is associated with key. Successive calls to Value with + * the same key returns the same result. * - * Example usage: + * Use context values only for request-scoped data that transits + * processes and API boundaries, not for passing optional parameters to + * functions. + * + * A key identifies a specific value in a Context. Functions that wish + * to store values in Context typically allocate a key in a global + * variable then use that key as the argument to context.WithValue and + * Context.Value. A key can be any type that supports equality; + * packages should define keys as an unexported type to avoid + * collisions. + * + * Packages that define a Context key should provide type-safe accessors + * for the values stored using that key: * * ``` - * var name string - * err := nameByUseridStmt.QueryRow(id).Scan(&name) - * ``` + * // Package user defines a User type that's stored in Contexts. + * package user * - * QueryRow uses [context.Background] internally; to specify the context, use - * [Stmt.QueryRowContext]. - */ - queryRow(...args: any[]): (Row) - } - interface Stmt { - /** - * Close closes the statement. + * import "context" + * + * // User is the type of value stored in the Contexts. + * type User struct {...} + * + * // key is an unexported type for keys defined in this package. + * // This prevents collisions with keys defined in other packages. + * type key int + * + * // userKey is the key for user.User values in Contexts. It is + * // unexported; clients use user.NewContext and user.FromContext + * // instead of using this key directly. + * var userKey key + * + * // NewContext returns a new Context that carries value u. + * func NewContext(ctx context.Context, u *User) context.Context { + * return context.WithValue(ctx, userKey, u) + * } + * + * // FromContext returns the User value stored in ctx, if any. + * func FromContext(ctx context.Context) (*User, bool) { + * u, ok := ctx.Value(userKey).(*User) + * return u, ok + * } + * ``` */ - close(): void + value(key: any): any } +} + +/** + * Package bufio implements buffered I/O. It wraps an io.Reader or io.Writer + * object, creating another object (Reader or Writer) that also implements + * the interface but provides buffering and some help for textual I/O. + */ +namespace bufio { /** - * Rows is the result of a query. Its cursor starts before the first row - * of the result set. Use [Rows.Next] to advance from row to row. + * ReadWriter stores pointers to a [Reader] and a [Writer]. + * It implements [io.ReadWriter]. */ - interface Rows { + type _skWqRsr = Reader&Writer + interface ReadWriter extends _skWqRsr { } - interface Rows { +} + +/** + * Package net provides a portable interface for network I/O, including + * TCP/IP, UDP, domain name resolution, and Unix domain sockets. + * + * Although the package provides access to low-level networking + * primitives, most clients will need only the basic interface provided + * by the [Dial], [Listen], and Accept functions and the associated + * [Conn] and [Listener] interfaces. The crypto/tls package uses + * the same interfaces and similar Dial and Listen functions. + * + * The Dial function connects to a server: + * + * ``` + * conn, err := net.Dial("tcp", "golang.org:80") + * if err != nil { + * // handle error + * } + * fmt.Fprintf(conn, "GET / HTTP/1.0\r\n\r\n") + * status, err := bufio.NewReader(conn).ReadString('\n') + * // ... + * ``` + * + * The Listen function creates servers: + * + * ``` + * ln, err := net.Listen("tcp", ":8080") + * if err != nil { + * // handle error + * } + * for { + * conn, err := ln.Accept() + * if err != nil { + * // handle error + * } + * go handleConnection(conn) + * } + * ``` + * + * # Name Resolution + * + * The method for resolving domain names, whether indirectly with functions like Dial + * or directly with functions like [LookupHost] and [LookupAddr], varies by operating system. + * + * On Unix systems, the resolver has two options for resolving names. + * It can use a pure Go resolver that sends DNS requests directly to the servers + * listed in /etc/resolv.conf, or it can use a cgo-based resolver that calls C + * library routines such as getaddrinfo and getnameinfo. + * + * On Unix the pure Go resolver is preferred over the cgo resolver, because a blocked DNS + * request consumes only a goroutine, while a blocked C call consumes an operating system thread. + * When cgo is available, the cgo-based resolver is used instead under a variety of + * conditions: on systems that do not let programs make direct DNS requests (OS X), + * when the LOCALDOMAIN environment variable is present (even if empty), + * when the RES_OPTIONS or HOSTALIASES environment variable is non-empty, + * when the ASR_CONFIG environment variable is non-empty (OpenBSD only), + * when /etc/resolv.conf or /etc/nsswitch.conf specify the use of features that the + * Go resolver does not implement. + * + * On all systems (except Plan 9), when the cgo resolver is being used + * this package applies a concurrent cgo lookup limit to prevent the system + * from running out of system threads. Currently, it is limited to 500 concurrent lookups. + * + * The resolver decision can be overridden by setting the netdns value of the + * GODEBUG environment variable (see package runtime) to go or cgo, as in: + * + * ``` + * export GODEBUG=netdns=go # force pure Go resolver + * export GODEBUG=netdns=cgo # force native resolver (cgo, win32) + * ``` + * + * The decision can also be forced while building the Go source tree + * by setting the netgo or netcgo build tag. + * The netgo build tag disables entirely the use of the native (CGO) resolver, + * meaning the Go resolver is the only one that can be used. + * With the netcgo build tag the native and the pure Go resolver are compiled into the binary, + * but the native (CGO) resolver is preferred over the Go resolver. + * With netcgo, the Go resolver can still be forced at runtime with GODEBUG=netdns=go. + * + * A numeric netdns setting, as in GODEBUG=netdns=1, causes the resolver + * to print debugging information about its decisions. + * To force a particular resolver while also printing debugging information, + * join the two settings by a plus sign, as in GODEBUG=netdns=go+1. + * + * The Go resolver will send an EDNS0 additional header with a DNS request, + * to signal a willingness to accept a larger DNS packet size. + * This can reportedly cause sporadic failures with the DNS server run + * by some modems and routers. Setting GODEBUG=netedns0=0 will disable + * sending the additional header. + * + * On macOS, if Go code that uses the net package is built with + * -buildmode=c-archive, linking the resulting archive into a C program + * requires passing -lresolv when linking the C code. + * + * On Plan 9, the resolver always accesses /net/cs and /net/dns. + * + * On Windows, in Go 1.18.x and earlier, the resolver always used C + * library functions, such as GetAddrInfo and DnsQuery. + */ +namespace net { + /** + * Conn is a generic stream-oriented network connection. + * + * Multiple goroutines may invoke methods on a Conn simultaneously. + */ + interface Conn { + [key:string]: any; /** - * Next prepares the next result row for reading with the [Rows.Scan] method. It - * returns true on success, or false if there is no next result row or an error - * happened while preparing it. [Rows.Err] should be consulted to distinguish between - * the two cases. - * - * Every call to [Rows.Scan], even the first one, must be preceded by a call to [Rows.Next]. + * Read reads data from the connection. + * Read can be made to time out and return an error after a fixed + * time limit; see SetDeadline and SetReadDeadline. */ - next(): boolean - } - interface Rows { + read(b: string|Array): number /** - * NextResultSet prepares the next result set for reading. It reports whether - * there is further result sets, or false if there is no further result set - * or if there is an error advancing to it. The [Rows.Err] method should be consulted - * to distinguish between the two cases. - * - * After calling NextResultSet, the [Rows.Next] method should always be called before - * scanning. If there are further result sets they may not have rows in the result - * set. + * Write writes data to the connection. + * Write can be made to time out and return an error after a fixed + * time limit; see SetDeadline and SetWriteDeadline. */ - nextResultSet(): boolean - } - interface Rows { + write(b: string|Array): number /** - * Err returns the error, if any, that was encountered during iteration. - * Err may be called after an explicit or implicit [Rows.Close]. + * Close closes the connection. + * Any blocked Read or Write operations will be unblocked and return errors. + * Close may or may not block until any buffered data is sent; + * for TCP connections see [*TCPConn.SetLinger]. */ - err(): void - } - interface Rows { + close(): void /** - * Columns returns the column names. - * Columns returns an error if the rows are closed. + * LocalAddr returns the local network address, if known. */ - columns(): Array - } - interface Rows { + localAddr(): Addr /** - * ColumnTypes returns column information such as column type, length, - * and nullable. Some information may not be available from some drivers. + * RemoteAddr returns the remote network address, if known. */ - columnTypes(): Array<(ColumnType | undefined)> - } - interface Rows { + remoteAddr(): Addr /** - * Scan copies the columns in the current row into the values pointed - * at by dest. The number of values in dest must be the same as the - * number of columns in [Rows]. - * - * Scan converts columns read from the database into the following - * common Go types and special types provided by the sql package: - * - * ``` - * *string - * *[]byte - * *int, *int8, *int16, *int32, *int64 - * *uint, *uint8, *uint16, *uint32, *uint64 - * *bool - * *float32, *float64 - * *interface{} - * *RawBytes - * *Rows (cursor value) - * any type implementing Scanner (see Scanner docs) - * ``` - * - * In the most simple case, if the type of the value from the source - * column is an integer, bool or string type T and dest is of type *T, - * Scan simply assigns the value through the pointer. - * - * Scan also converts between string and numeric types, as long as no - * information would be lost. While Scan stringifies all numbers - * scanned from numeric database columns into *string, scans into - * numeric types are checked for overflow. For example, a float64 with - * value 300 or a string with value "300" can scan into a uint16, but - * not into a uint8, though float64(255) or "255" can scan into a - * uint8. One exception is that scans of some float64 numbers to - * strings may lose information when stringifying. In general, scan - * floating point columns into *float64. - * - * If a dest argument has type *[]byte, Scan saves in that argument a - * copy of the corresponding data. The copy is owned by the caller and - * can be modified and held indefinitely. The copy can be avoided by - * using an argument of type [*RawBytes] instead; see the documentation - * for [RawBytes] for restrictions on its use. - * - * If an argument has type *interface{}, Scan copies the value - * provided by the underlying driver without conversion. When scanning - * from a source value of type []byte to *interface{}, a copy of the - * slice is made and the caller owns the result. - * - * Source values of type [time.Time] may be scanned into values of type - * *time.Time, *interface{}, *string, or *[]byte. When converting to - * the latter two, [time.RFC3339Nano] is used. + * SetDeadline sets the read and write deadlines associated + * with the connection. It is equivalent to calling both + * SetReadDeadline and SetWriteDeadline. * - * Source values of type bool may be scanned into types *bool, - * *interface{}, *string, *[]byte, or [*RawBytes]. + * A deadline is an absolute time after which I/O operations + * fail instead of blocking. The deadline applies to all future + * and pending I/O, not just the immediately following call to + * Read or Write. After a deadline has been exceeded, the + * connection can be refreshed by setting a deadline in the future. * - * For scanning into *bool, the source may be true, false, 1, 0, or - * string inputs parseable by [strconv.ParseBool]. + * If the deadline is exceeded a call to Read or Write or to other + * I/O methods will return an error that wraps os.ErrDeadlineExceeded. + * This can be tested using errors.Is(err, os.ErrDeadlineExceeded). + * The error's Timeout method will return true, but note that there + * are other possible errors for which the Timeout method will + * return true even if the deadline has not been exceeded. * - * Scan can also convert a cursor returned from a query, such as - * "select cursor(select * from my_table) from dual", into a - * [*Rows] value that can itself be scanned from. The parent - * select query will close any cursor [*Rows] if the parent [*Rows] is closed. + * An idle timeout can be implemented by repeatedly extending + * the deadline after successful Read or Write calls. * - * If any of the first arguments implementing [Scanner] returns an error, - * that error will be wrapped in the returned error. + * A zero value for t means I/O operations will not time out. */ - scan(...dest: any[]): void - } - interface Rows { + setDeadline(t: time.Time): void /** - * Close closes the [Rows], preventing further enumeration. If [Rows.Next] is called - * and returns false and there are no further result sets, - * the [Rows] are closed automatically and it will suffice to check the - * result of [Rows.Err]. Close is idempotent and does not affect the result of [Rows.Err]. + * SetReadDeadline sets the deadline for future Read calls + * and any currently-blocked Read call. + * A zero value for t means Read will not time out. */ - close(): void + setReadDeadline(t: time.Time): void + /** + * SetWriteDeadline sets the deadline for future Write calls + * and any currently-blocked Write call. + * Even if write times out, it may return n > 0, indicating that + * some of the data was successfully written. + * A zero value for t means Write will not time out. + */ + setWriteDeadline(t: time.Time): void } /** - * A Result summarizes an executed SQL command. + * A Listener is a generic network listener for stream-oriented protocols. + * + * Multiple goroutines may invoke methods on a Listener simultaneously. */ - interface Result { + interface Listener { [key:string]: any; /** - * LastInsertId returns the integer generated by the database - * in response to a command. Typically this will be from an - * "auto increment" column when inserting a new row. Not all - * databases support this feature, and the syntax of such - * statements varies. + * Accept waits for and returns the next connection to the listener. */ - lastInsertId(): number + accept(): Conn /** - * RowsAffected returns the number of rows affected by an - * update, insert, or delete. Not every database or database - * driver may support this. + * Close closes the listener. + * Any blocked Accept operations will be unblocked and return errors. */ - rowsAffected(): number + close(): void + /** + * Addr returns the listener's network address. + */ + addr(): Addr } + // @ts-ignore + import _cgopackage = cgo } /** - * Package syntax parses regular expressions into parse trees and compiles - * parse trees into programs. Most clients of regular expressions will use the - * facilities of package [regexp] (such as [regexp.Compile] and [regexp.Match]) instead of this package. + * Package multipart implements MIME multipart parsing, as defined in RFC + * 2046. * - * # Syntax + * The implementation is sufficient for HTTP (RFC 2388) and the multipart + * bodies generated by popular browsers. * - * The regular expression syntax understood by this package when parsing with the [Perl] flag is as follows. - * Parts of the syntax can be disabled by passing alternate flags to [Parse]. + * # Limits * - * Single characters: + * To protect against malicious inputs, this package sets limits on the size + * of the MIME data it processes. * - * ``` - * . any character, possibly including newline (flag s=true) - * [xyz] character class - * [^xyz] negated character class - * \d Perl character class - * \D negated Perl character class - * [[:alpha:]] ASCII character class - * [[:^alpha:]] negated ASCII character class - * \pN Unicode character class (one-letter name) - * \p{Greek} Unicode character class - * \PN negated Unicode character class (one-letter name) - * \P{Greek} negated Unicode character class - * ``` + * [Reader.NextPart] and [Reader.NextRawPart] limit the number of headers in a + * part to 10000 and [Reader.ReadForm] limits the total number of headers in all + * FileHeaders to 10000. + * These limits may be adjusted with the GODEBUG=multipartmaxheaders= + * setting. * - * Composites: + * Reader.ReadForm further limits the number of parts in a form to 1000. + * This limit may be adjusted with the GODEBUG=multipartmaxparts= + * setting. + */ +namespace multipart { + /** + * A FileHeader describes a file part of a multipart request. + */ + interface FileHeader { + filename: string + header: textproto.MIMEHeader + size: number + } + interface FileHeader { + /** + * Open opens and returns the [FileHeader]'s associated File. + */ + open(): File + } +} + +/** + * Package http provides HTTP client and server implementations. + * + * [Get], [Head], [Post], and [PostForm] make HTTP (or HTTPS) requests: * * ``` - * xy x followed by y - * x|y x or y (prefer x) + * resp, err := http.Get("http://example.com/") + * ... + * resp, err := http.Post("http://example.com/upload", "image/jpeg", &buf) + * ... + * resp, err := http.PostForm("http://example.com/form", + * url.Values{"key": {"Value"}, "id": {"123"}}) * ``` * - * Repetitions: + * The caller must close the response body when finished with it: * * ``` - * x* zero or more x, prefer more - * x+ one or more x, prefer more - * x? zero or one x, prefer one - * x{n,m} n or n+1 or ... or m x, prefer more - * x{n,} n or more x, prefer more - * x{n} exactly n x - * x*? zero or more x, prefer fewer - * x+? one or more x, prefer fewer - * x?? zero or one x, prefer zero - * x{n,m}? n or n+1 or ... or m x, prefer fewer - * x{n,}? n or more x, prefer fewer - * x{n}? exactly n x + * resp, err := http.Get("http://example.com/") + * if err != nil { + * // handle error + * } + * defer resp.Body.Close() + * body, err := io.ReadAll(resp.Body) + * // ... * ``` * - * Implementation restriction: The counting forms x{n,m}, x{n,}, and x{n} - * reject forms that create a minimum or maximum repetition count above 1000. - * Unlimited repetitions are not subject to this restriction. - * - * Grouping: - * - * ``` - * (re) numbered capturing group (submatch) - * (?Pre) named & numbered capturing group (submatch) - * (?re) named & numbered capturing group (submatch) - * (?:re) non-capturing group - * (?flags) set flags within current group; non-capturing - * (?flags:re) set flags during re; non-capturing + * # Clients and Transports * - * Flag syntax is xyz (set) or -xyz (clear) or xy-z (set xy, clear z). The flags are: + * For control over HTTP client headers, redirect policy, and other + * settings, create a [Client]: * - * i case-insensitive (default false) - * m multi-line mode: ^ and $ match begin/end line in addition to begin/end text (default false) - * s let . match \n (default false) - * U ungreedy: swap meaning of x* and x*?, x+ and x+?, etc (default false) * ``` + * client := &http.Client{ + * CheckRedirect: redirectPolicyFunc, + * } * - * Empty strings: + * resp, err := client.Get("http://example.com") + * // ... * - * ``` - * ^ at beginning of text or line (flag m=true) - * $ at end of text (like \z not \Z) or line (flag m=true) - * \A at beginning of text - * \b at ASCII word boundary (\w on one side and \W, \A, or \z on the other) - * \B not at ASCII word boundary - * \z at end of text + * req, err := http.NewRequest("GET", "http://example.com", nil) + * // ... + * req.Header.Add("If-None-Match", `W/"wyzzy"`) + * resp, err := client.Do(req) + * // ... * ``` * - * Escape sequences: + * For control over proxies, TLS configuration, keep-alives, + * compression, and other settings, create a [Transport]: * * ``` - * \a bell (== \007) - * \f form feed (== \014) - * \t horizontal tab (== \011) - * \n newline (== \012) - * \r carriage return (== \015) - * \v vertical tab character (== \013) - * \* literal *, for any punctuation character * - * \123 octal character code (up to three digits) - * \x7F hex character code (exactly two digits) - * \x{10FFFF} hex character code - * \Q...\E literal text ... even if ... has punctuation + * tr := &http.Transport{ + * MaxIdleConns: 10, + * IdleConnTimeout: 30 * time.Second, + * DisableCompression: true, + * } + * client := &http.Client{Transport: tr} + * resp, err := client.Get("https://example.com") * ``` * - * Character class elements: + * Clients and Transports are safe for concurrent use by multiple + * goroutines and for efficiency should only be created once and re-used. * - * ``` - * x single character - * A-Z character range (inclusive) - * \d Perl character class - * [:foo:] ASCII character class foo - * \p{Foo} Unicode character class Foo - * \pF Unicode character class F (one-letter name) - * ``` + * # Servers * - * Named character classes as character class elements: + * ListenAndServe starts an HTTP server with a given address and handler. + * The handler is usually nil, which means to use [DefaultServeMux]. + * [Handle] and [HandleFunc] add handlers to [DefaultServeMux]: * * ``` - * [\d] digits (== \d) - * [^\d] not digits (== \D) - * [\D] not digits (== \D) - * [^\D] not not digits (== \d) - * [[:name:]] named ASCII class inside character class (== [:name:]) - * [^[:name:]] named ASCII class inside negated character class (== [:^name:]) - * [\p{Name}] named Unicode property inside character class (== \p{Name}) - * [^\p{Name}] named Unicode property inside negated character class (== \P{Name}) + * http.Handle("/foo", fooHandler) + * + * http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) { + * fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path)) + * }) + * + * log.Fatal(http.ListenAndServe(":8080", nil)) * ``` * - * Perl character classes (all ASCII-only): + * More control over the server's behavior is available by creating a + * custom Server: * * ``` - * \d digits (== [0-9]) - * \D not digits (== [^0-9]) - * \s whitespace (== [\t\n\f\r ]) - * \S not whitespace (== [^\t\n\f\r ]) - * \w word characters (== [0-9A-Za-z_]) - * \W not word characters (== [^0-9A-Za-z_]) + * s := &http.Server{ + * Addr: ":8080", + * Handler: myHandler, + * ReadTimeout: 10 * time.Second, + * WriteTimeout: 10 * time.Second, + * MaxHeaderBytes: 1 << 20, + * } + * log.Fatal(s.ListenAndServe()) * ``` * - * ASCII character classes: + * # HTTP/2 + * + * The http package has transparent support for the HTTP/2 protocol. + * + * [Server] and [DefaultTransport] automatically enable HTTP/2 support + * when using HTTPS. [Transport] does not enable HTTP/2 by default. + * + * To enable or disable support for HTTP/1, HTTP/2, and/or unencrypted HTTP/2, + * see the [Server.Protocols] and [Transport.Protocols] configuration fields. + * + * To configure advanced HTTP/2 features, see the [Server.HTTP2] and + * [Transport.HTTP2] configuration fields. + * + * Alternatively, the following GODEBUG settings are currently supported: * * ``` - * [[:alnum:]] alphanumeric (== [0-9A-Za-z]) - * [[:alpha:]] alphabetic (== [A-Za-z]) - * [[:ascii:]] ASCII (== [\x00-\x7F]) - * [[:blank:]] blank (== [\t ]) - * [[:cntrl:]] control (== [\x00-\x1F\x7F]) - * [[:digit:]] digits (== [0-9]) - * [[:graph:]] graphical (== [!-~] == [A-Za-z0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~]) - * [[:lower:]] lower case (== [a-z]) - * [[:print:]] printable (== [ -~] == [ [:graph:]]) - * [[:punct:]] punctuation (== [!-/:-@[-`{-~]) - * [[:space:]] whitespace (== [\t\n\v\f\r ]) - * [[:upper:]] upper case (== [A-Z]) - * [[:word:]] word characters (== [0-9A-Za-z_]) - * [[:xdigit:]] hex digit (== [0-9A-Fa-f]) + * GODEBUG=http2client=0 # disable HTTP/2 client support + * GODEBUG=http2server=0 # disable HTTP/2 server support + * GODEBUG=http2debug=1 # enable verbose HTTP/2 debug logs + * GODEBUG=http2debug=2 # ... even more verbose, with frame dumps * ``` * - * Unicode character classes are those in [unicode.Categories], - * [unicode.CategoryAliases], and [unicode.Scripts]. - */ -namespace syntax { - /** - * Flags control the behavior of the parser and record information about regexp context. - */ - interface Flags extends Number{} -} - -/** - * Package bufio implements buffered I/O. It wraps an io.Reader or io.Writer - * object, creating another object (Reader or Writer) that also implements - * the interface but provides buffering and some help for textual I/O. + * The "omithttp2" build tag may be used to disable the HTTP/2 implementation + * contained in the http package. */ -namespace bufio { - /** - * ReadWriter stores pointers to a [Reader] and a [Writer]. - * It implements [io.ReadWriter]. - */ - type _soDNoFP = Reader&Writer - interface ReadWriter extends _soDNoFP { - } -} - -namespace store { +namespace http { /** - * Store defines a concurrent safe in memory key-value data store. + * PushOptions describes options for [Pusher.Push]. */ - interface Store { - } - interface Store { + interface PushOptions { /** - * Reset clears the store and replaces the store data with a - * shallow copy of the provided newData. + * Method specifies the HTTP method for the promised request. + * If set, it must be "GET" or "HEAD". Empty means "GET". */ - reset(newData: _TygojaDict): void - } - interface Store { + method: string /** - * Length returns the current number of elements in the store. + * Header specifies additional promised request headers. This cannot + * include HTTP/2 pseudo header fields like ":path" and ":scheme", + * which will be added automatically. */ - length(): number + header: Header } - interface Store { + // @ts-ignore + import urlpkg = url + /** + * A Request represents an HTTP request received by a server + * or to be sent by a client. + * + * The field semantics differ slightly between client and server + * usage. In addition to the notes on the fields below, see the + * documentation for [Request.Write] and [RoundTripper]. + */ + interface Request { /** - * RemoveAll removes all the existing store entries. + * Method specifies the HTTP method (GET, POST, PUT, etc.). + * For client requests, an empty string means GET. */ - removeAll(): void - } - interface Store { + method: string /** - * Remove removes a single entry from the store. + * URL specifies either the URI being requested (for server + * requests) or the URL to access (for client requests). * - * Remove does nothing if key doesn't exist in the store. - */ - remove(key: K): void - } - interface Store { - /** - * Has checks if element with the specified key exist or not. + * For server requests, the URL is parsed from the URI + * supplied on the Request-Line as stored in RequestURI. For + * most requests, fields other than Path and RawQuery will be + * empty. (See RFC 7230, Section 5.3) + * + * For client requests, the URL's Host specifies the server to + * connect to, while the Request's Host field optionally + * specifies the Host header value to send in the HTTP + * request. */ - has(key: K): boolean - } - interface Store { + url?: url.URL /** - * Get returns a single element value from the store. + * The protocol version for incoming server requests. * - * If key is not set, the zero T value is returned. + * For client requests, these fields are ignored. The HTTP + * client code always uses either HTTP/1.1 or HTTP/2. + * See the docs on Transport for details. */ - get(key: K): T - } - interface Store { + proto: string // "HTTP/1.0" + protoMajor: number // 1 + protoMinor: number // 0 /** - * GetOk is similar to Get but returns also a boolean indicating whether the key exists or not. + * Header contains the request header fields either received + * by the server or to be sent by the client. + * + * If a server received a request with header lines, + * + * ``` + * Host: example.com + * accept-encoding: gzip, deflate + * Accept-Language: en-us + * fOO: Bar + * foo: two + * ``` + * + * then + * + * ``` + * Header = map[string][]string{ + * "Accept-Encoding": {"gzip, deflate"}, + * "Accept-Language": {"en-us"}, + * "Foo": {"Bar", "two"}, + * } + * ``` + * + * For incoming requests, the Host header is promoted to the + * Request.Host field and removed from the Header map. + * + * HTTP defines that header names are case-insensitive. The + * request parser implements this by using CanonicalHeaderKey, + * making the first character and any characters following a + * hyphen uppercase and the rest lowercase. + * + * For client requests, certain headers such as Content-Length + * and Connection are automatically written when needed and + * values in Header may be ignored. See the documentation + * for the Request.Write method. */ - getOk(key: K): [T, boolean] - } - interface Store { + header: Header /** - * GetAll returns a shallow copy of the current store data. + * Body is the request's body. + * + * For client requests, a nil body means the request has no + * body, such as a GET request. The HTTP Client's Transport + * is responsible for calling the Close method. + * + * For server requests, the Request Body is always non-nil + * but will return EOF immediately when no body is present. + * The Server will close the request body. The ServeHTTP + * Handler does not need to. + * + * Body must allow Read to be called concurrently with Close. + * In particular, calling Close should unblock a Read waiting + * for input. */ - getAll(): _TygojaDict - } - interface Store { + body: io.ReadCloser /** - * Keys returns a slice with all of the store keys. + * GetBody defines an optional func to return a new copy of + * Body. It is used for client requests when a redirect requires + * reading the body more than once. Use of GetBody still + * requires setting Body. + * + * For server requests, it is unused. */ - keys(): Array - } - interface Store { + getBody: () => io.ReadCloser /** - * Values returns a slice with all of the store values. + * ContentLength records the length of the associated content. + * The value -1 indicates that the length is unknown. + * Values >= 0 indicate that the given number of bytes may + * be read from Body. + * + * For client requests, a value of 0 with a non-nil Body is + * also treated as unknown. */ - values(): Array - } - interface Store { + contentLength: number /** - * Set sets (or overwrite if already exists) a new value for key. + * TransferEncoding lists the transfer encodings from outermost to + * innermost. An empty list denotes the "identity" encoding. + * TransferEncoding can usually be ignored; chunked encoding is + * automatically added and removed as necessary when sending and + * receiving requests. */ - set(key: K, value: T): void - } - interface Store { + transferEncoding: Array /** - * SetFunc sets (or overwrite if already exists) a new value resolved - * from the function callback for the provided key. + * Close indicates whether to close the connection after + * replying to this request (for servers) or after sending this + * request and reading its response (for clients). * - * The function callback receives as argument the old store element value (if exists). - * If there is no old store element, the argument will be the T zero value. + * For server requests, the HTTP server handles this automatically + * and this field is not needed by Handlers. * - * Example: + * For client requests, setting this field prevents re-use of + * TCP connections between requests to the same hosts, as if + * Transport.DisableKeepAlives were set. + */ + close: boolean + /** + * For server requests, Host specifies the host on which the + * URL is sought. For HTTP/1 (per RFC 7230, section 5.4), this + * is either the value of the "Host" header or the host name + * given in the URL itself. For HTTP/2, it is the value of the + * ":authority" pseudo-header field. + * It may be of the form "host:port". For international domain + * names, Host may be in Punycode or Unicode form. Use + * golang.org/x/net/idna to convert it to either format if + * needed. + * To prevent DNS rebinding attacks, server Handlers should + * validate that the Host header has a value for which the + * Handler considers itself authoritative. The included + * ServeMux supports patterns registered to particular host + * names and thus protects its registered Handlers. * - * ``` - * s := store.New[string, int](nil) - * s.SetFunc("count", func(old int) int { - * return old + 1 - * }) - * ``` + * For client requests, Host optionally overrides the Host + * header to send. If empty, the Request.Write method uses + * the value of URL.Host. Host may contain an international + * domain name. */ - setFunc(key: K, fn: (old: T) => T): void - } - interface Store { + host: string /** - * GetOrSet retrieves a single existing value for the provided key - * or stores a new one if it doesn't exist. + * Form contains the parsed form data, including both the URL + * field's query parameters and the PATCH, POST, or PUT form data. + * This field is only available after ParseForm is called. + * The HTTP client ignores Form and uses Body instead. */ - getOrSet(key: K, setFunc: () => T): T - } - interface Store { + form: url.Values /** - * SetIfLessThanLimit sets (or overwrite if already exist) a new value for key. + * PostForm contains the parsed form data from PATCH, POST + * or PUT body parameters. * - * This method is similar to Set() but **it will skip adding new elements** - * to the store if the store length has reached the specified limit. - * false is returned if maxAllowedElements limit is reached. + * This field is only available after ParseForm is called. + * The HTTP client ignores PostForm and uses Body instead. */ - setIfLessThanLimit(key: K, value: T, maxAllowedElements: number): boolean - } - interface Store { + postForm: url.Values /** - * UnmarshalJSON implements [json.Unmarshaler] and imports the - * provided JSON data into the store. - * - * The store entries that match with the ones from the data will be overwritten with the new value. + * MultipartForm is the parsed multipart form, including file uploads. + * This field is only available after ParseMultipartForm is called. + * The HTTP client ignores MultipartForm and uses Body instead. */ - unmarshalJSON(data: string|Array): void - } - interface Store { + multipartForm?: multipart.Form /** - * MarshalJSON implements [json.Marshaler] and export the current - * store data into valid JSON. + * Trailer specifies additional headers that are sent after the request + * body. + * + * For server requests, the Trailer map initially contains only the + * trailer keys, with nil values. (The client declares which trailers it + * will later send.) While the handler is reading from Body, it must + * not reference Trailer. After reading from Body returns EOF, Trailer + * can be read again and will contain non-nil values, if they were sent + * by the client. + * + * For client requests, Trailer must be initialized to a map containing + * the trailer keys to later send. The values may be nil or their final + * values. The ContentLength must be 0 or -1, to send a chunked request. + * After the HTTP request is sent the map values can be updated while + * the request body is read. Once the body returns EOF, the caller must + * not mutate Trailer. + * + * Writing a request whose Trailer contains a key with invalid bytes + * (such as CR or LF), or such a value present when Write begins, + * returns an error. + * + * Few HTTP clients, servers, or proxies support HTTP trailers. */ - marshalJSON(): string|Array - } -} - -/** - * Package net provides a portable interface for network I/O, including - * TCP/IP, UDP, domain name resolution, and Unix domain sockets. - * - * Although the package provides access to low-level networking - * primitives, most clients will need only the basic interface provided - * by the [Dial], [Listen], and Accept functions and the associated - * [Conn] and [Listener] interfaces. The crypto/tls package uses - * the same interfaces and similar Dial and Listen functions. - * - * The Dial function connects to a server: - * - * ``` - * conn, err := net.Dial("tcp", "golang.org:80") - * if err != nil { - * // handle error - * } - * fmt.Fprintf(conn, "GET / HTTP/1.0\r\n\r\n") - * status, err := bufio.NewReader(conn).ReadString('\n') - * // ... - * ``` - * - * The Listen function creates servers: - * - * ``` - * ln, err := net.Listen("tcp", ":8080") - * if err != nil { - * // handle error - * } - * for { - * conn, err := ln.Accept() - * if err != nil { - * // handle error - * } - * go handleConnection(conn) - * } - * ``` - * - * # Name Resolution - * - * The method for resolving domain names, whether indirectly with functions like Dial - * or directly with functions like [LookupHost] and [LookupAddr], varies by operating system. - * - * On Unix systems, the resolver has two options for resolving names. - * It can use a pure Go resolver that sends DNS requests directly to the servers - * listed in /etc/resolv.conf, or it can use a cgo-based resolver that calls C - * library routines such as getaddrinfo and getnameinfo. - * - * On Unix the pure Go resolver is preferred over the cgo resolver, because a blocked DNS - * request consumes only a goroutine, while a blocked C call consumes an operating system thread. - * When cgo is available, the cgo-based resolver is used instead under a variety of - * conditions: on systems that do not let programs make direct DNS requests (OS X), - * when the LOCALDOMAIN environment variable is present (even if empty), - * when the RES_OPTIONS or HOSTALIASES environment variable is non-empty, - * when the ASR_CONFIG environment variable is non-empty (OpenBSD only), - * when /etc/resolv.conf or /etc/nsswitch.conf specify the use of features that the - * Go resolver does not implement. - * - * On all systems (except Plan 9), when the cgo resolver is being used - * this package applies a concurrent cgo lookup limit to prevent the system - * from running out of system threads. Currently, it is limited to 500 concurrent lookups. - * - * The resolver decision can be overridden by setting the netdns value of the - * GODEBUG environment variable (see package runtime) to go or cgo, as in: - * - * ``` - * export GODEBUG=netdns=go # force pure Go resolver - * export GODEBUG=netdns=cgo # force native resolver (cgo, win32) - * ``` - * - * The decision can also be forced while building the Go source tree - * by setting the netgo or netcgo build tag. - * The netgo build tag disables entirely the use of the native (CGO) resolver, - * meaning the Go resolver is the only one that can be used. - * With the netcgo build tag the native and the pure Go resolver are compiled into the binary, - * but the native (CGO) resolver is preferred over the Go resolver. - * With netcgo, the Go resolver can still be forced at runtime with GODEBUG=netdns=go. - * - * A numeric netdns setting, as in GODEBUG=netdns=1, causes the resolver - * to print debugging information about its decisions. - * To force a particular resolver while also printing debugging information, - * join the two settings by a plus sign, as in GODEBUG=netdns=go+1. - * - * The Go resolver will send an EDNS0 additional header with a DNS request, - * to signal a willingness to accept a larger DNS packet size. - * This can reportedly cause sporadic failures with the DNS server run - * by some modems and routers. Setting GODEBUG=netedns0=0 will disable - * sending the additional header. - * - * On macOS, if Go code that uses the net package is built with - * -buildmode=c-archive, linking the resulting archive into a C program - * requires passing -lresolv when linking the C code. - * - * On Plan 9, the resolver always accesses /net/cs and /net/dns. - * - * On Windows, in Go 1.18.x and earlier, the resolver always used C - * library functions, such as GetAddrInfo and DnsQuery. - */ -namespace net { - /** - * Conn is a generic stream-oriented network connection. - * - * Multiple goroutines may invoke methods on a Conn simultaneously. - */ - interface Conn { - [key:string]: any; + trailer: Header + /** + * RemoteAddr allows HTTP servers and other software to record + * the network address that sent the request, usually for + * logging. This field is not filled in by ReadRequest and + * has no defined format. The HTTP server in this package + * sets RemoteAddr to an "IP:port" address before invoking a + * handler. + * This field is ignored by the HTTP client. + */ + remoteAddr: string /** - * Read reads data from the connection. - * Read can be made to time out and return an error after a fixed - * time limit; see SetDeadline and SetReadDeadline. + * RequestURI is the unmodified request-target of the + * Request-Line (RFC 7230, Section 3.1.1) as sent by the client + * to a server. Usually the URL field should be used instead. + * It is an error to set this field in an HTTP client request. */ - read(b: string|Array): number + requestURI: string /** - * Write writes data to the connection. - * Write can be made to time out and return an error after a fixed - * time limit; see SetDeadline and SetWriteDeadline. + * TLS allows HTTP servers and other software to record + * information about the TLS connection on which the request + * was received. This field is not filled in by ReadRequest. + * The HTTP server in this package sets the field for + * TLS-enabled connections before invoking a handler; + * otherwise it leaves the field nil. + * This field is ignored by the HTTP client. */ - write(b: string|Array): number + tls?: any /** - * Close closes the connection. - * Any blocked Read or Write operations will be unblocked and return errors. - * Close may or may not block until any buffered data is sent; - * for TCP connections see [*TCPConn.SetLinger]. + * Cancel is an optional channel whose closure indicates that the client + * request should be regarded as canceled. Not all implementations of + * RoundTripper may support Cancel. + * + * For server requests, this field is not applicable. + * + * Deprecated: Set the Request's context with NewRequestWithContext + * instead. If a Request's Cancel field and context are both + * set, it is undefined whether Cancel is respected. */ - close(): void + cancel: undefined /** - * LocalAddr returns the local network address, if known. + * Response is the redirect response which caused this request + * to be created. This field is only populated during client + * redirects. */ - localAddr(): Addr + response?: Response /** - * RemoteAddr returns the remote network address, if known. + * Pattern is the [ServeMux] pattern that matched the request. + * It is empty if the request was not matched against a pattern. */ - remoteAddr(): Addr + pattern: string + } + interface Request { /** - * SetDeadline sets the read and write deadlines associated - * with the connection. It is equivalent to calling both - * SetReadDeadline and SetWriteDeadline. - * - * A deadline is an absolute time after which I/O operations - * fail instead of blocking. The deadline applies to all future - * and pending I/O, not just the immediately following call to - * Read or Write. After a deadline has been exceeded, the - * connection can be refreshed by setting a deadline in the future. + * Context returns the request's context. To change the context, use + * [Request.Clone] or [Request.WithContext]. * - * If the deadline is exceeded a call to Read or Write or to other - * I/O methods will return an error that wraps os.ErrDeadlineExceeded. - * This can be tested using errors.Is(err, os.ErrDeadlineExceeded). - * The error's Timeout method will return true, but note that there - * are other possible errors for which the Timeout method will - * return true even if the deadline has not been exceeded. + * The returned context is always non-nil; it defaults to the + * background context. * - * An idle timeout can be implemented by repeatedly extending - * the deadline after successful Read or Write calls. + * For outgoing client requests, the context controls cancellation. * - * A zero value for t means I/O operations will not time out. - */ - setDeadline(t: time.Time): void - /** - * SetReadDeadline sets the deadline for future Read calls - * and any currently-blocked Read call. - * A zero value for t means Read will not time out. + * For incoming server requests, the context is canceled when the + * client's connection closes, the request is canceled (with HTTP/2), + * or when the ServeHTTP method returns. */ - setReadDeadline(t: time.Time): void + context(): context.Context + } + interface Request { /** - * SetWriteDeadline sets the deadline for future Write calls - * and any currently-blocked Write call. - * Even if write times out, it may return n > 0, indicating that - * some of the data was successfully written. - * A zero value for t means Write will not time out. + * WithContext returns a shallow copy of r with its context changed + * to ctx. The provided ctx must be non-nil. + * + * For outgoing client request, the context controls the entire + * lifetime of a request and its response: obtaining a connection, + * sending the request, and reading the response headers and body. + * + * To create a new request with a context, use [NewRequestWithContext]. + * To make a deep copy of a request with a new context, use [Request.Clone]. */ - setWriteDeadline(t: time.Time): void + withContext(ctx: context.Context): (Request) } - /** - * A Listener is a generic network listener for stream-oriented protocols. - * - * Multiple goroutines may invoke methods on a Listener simultaneously. - */ - interface Listener { - [key:string]: any; + interface Request { /** - * Accept waits for and returns the next connection to the listener. + * Clone returns a deep copy of r with its context changed to ctx. + * The provided ctx must be non-nil. + * + * Clone only makes a shallow copy of the Body field. + * + * For an outgoing client request, the context controls the entire + * lifetime of a request and its response: obtaining a connection, + * sending the request, and reading the response headers and body. */ - accept(): Conn + clone(ctx: context.Context): (Request) + } + interface Request { /** - * Close closes the listener. - * Any blocked Accept operations will be unblocked and return errors. + * ProtoAtLeast reports whether the HTTP protocol used + * in the request is at least major.minor. */ - close(): void + protoAtLeast(major: number, minor: number): boolean + } + interface Request { /** - * Addr returns the listener's network address. + * UserAgent returns the client's User-Agent, if sent in the request. */ - addr(): Addr + userAgent(): string } - // @ts-ignore - import _cgopackage = cgo -} - -/** - * Package jwt is a Go implementation of JSON Web Tokens: http://self-issued.info/docs/draft-jones-json-web-token.html - * - * See README.md for more info. - */ -namespace jwt { - /** - * MapClaims is a claims type that uses the map[string]any for JSON - * decoding. This is the default claims type if you don't supply one - */ - interface MapClaims extends _TygojaDict{} - interface MapClaims { + interface Request { /** - * GetExpirationTime implements the Claims interface. + * Cookies parses and returns the HTTP cookies sent with the request. */ - getExpirationTime(): (NumericDate) + cookies(): Array<(Cookie | undefined)> } - interface MapClaims { + interface Request { /** - * GetNotBefore implements the Claims interface. + * CookiesNamed parses and returns the named HTTP cookies sent with the request + * or an empty slice if none matched. */ - getNotBefore(): (NumericDate) + cookiesNamed(name: string): Array<(Cookie | undefined)> } - interface MapClaims { + interface Request { /** - * GetIssuedAt implements the Claims interface. + * Cookie returns the named cookie provided in the request or + * [ErrNoCookie] if not found. + * If multiple cookies match the given name, only one cookie will + * be returned. */ - getIssuedAt(): (NumericDate) + cookie(name: string): (Cookie) } - interface MapClaims { + interface Request { /** - * GetAudience implements the Claims interface. + * AddCookie adds a cookie to the request. Per RFC 6265 section 5.4, + * AddCookie does not attach more than one [Cookie] header field. That + * means all cookies, if any, are written into the same line, + * separated by semicolon. + * AddCookie only sanitizes c's name and value, and does not sanitize + * a Cookie header already present in the request. */ - getAudience(): ClaimStrings + addCookie(c: Cookie): void } - interface MapClaims { + interface Request { /** - * GetIssuer implements the Claims interface. + * Referer returns the referring URL, if sent in the request. + * + * Referer is misspelled as in the request itself, a mistake from the + * earliest days of HTTP. This value can also be fetched from the + * [Header] map as Header["Referer"]; the benefit of making it available + * as a method is that the compiler can diagnose programs that use the + * alternate (correct English) spelling req.Referrer() but cannot + * diagnose programs that use Header["Referrer"]. */ - getIssuer(): string + referer(): string } - interface MapClaims { + interface Request { /** - * GetSubject implements the Claims interface. + * MultipartReader returns a MIME multipart reader if this is a + * multipart/form-data or a multipart/mixed POST request, else returns nil and an error. + * Use this function instead of [Request.ParseMultipartForm] to + * process the request body as a stream. */ - getSubject(): string - } -} - -/** - * Package types implements some commonly used db serializable types - * like datetime, json, etc. - */ -namespace types { - /** - * DateTime represents a [time.Time] instance in UTC that is wrapped - * and serialized using the app default date layout. - */ - interface DateTime { + multipartReader(): (multipart.Reader) } - interface DateTime { + interface Request { /** - * Time returns the internal [time.Time] instance. + * Write writes an HTTP/1.1 request, which is the header and body, in wire format. + * This method consults the following fields of the request: + * + * ``` + * Host + * URL + * Method (defaults to "GET") + * Header + * ContentLength + * TransferEncoding + * Body + * ``` + * + * If Body is present, Content-Length is <= 0 and [Request.TransferEncoding] + * hasn't been set to "identity", Write adds "Transfer-Encoding: + * chunked" to the header. Body is closed after it is sent. + * + * Header values for Host, Content-Length, Transfer-Encoding, + * and Trailer are not used; these are derived from other Request fields. + * If the Header does not contain a User-Agent value, Write uses + * "Go-http-client/1.1". */ - time(): time.Time + write(w: io.Writer): void } - interface DateTime { + interface Request { /** - * Add returns a new DateTime based on the current DateTime + the specified duration. + * WriteProxy is like [Request.Write] but writes the request in the form + * expected by an HTTP proxy. In particular, [Request.WriteProxy] writes the + * initial Request-URI line of the request with an absolute URI, per + * section 5.3 of RFC 7230, including the scheme and host. + * In either case, WriteProxy also writes a Host header, using + * either r.Host or r.URL.Host. */ - add(duration: time.Duration): DateTime + writeProxy(w: io.Writer): void } - interface DateTime { + interface Request { /** - * Sub returns a [time.Duration] by subtracting the specified DateTime from the current one. - * - * If the result exceeds the maximum (or minimum) value that can be stored in a [time.Duration], - * the maximum (or minimum) duration will be returned. + * BasicAuth returns the username and password provided in the request's + * Authorization header, if the request uses HTTP Basic Authentication. + * See RFC 2617, Section 2. */ - sub(u: DateTime): time.Duration + basicAuth(): [string, string, boolean] } - interface DateTime { + interface Request { /** - * AddDate returns a new DateTime based on the current one + duration. + * SetBasicAuth sets the request's Authorization header to use HTTP + * Basic Authentication with the provided username and password. * - * It follows the same rules as [time.AddDate]. - */ - addDate(years: number, months: number, days: number): DateTime - } - interface DateTime { - /** - * After reports whether the current DateTime instance is after u. + * With HTTP Basic Authentication the provided username and password + * are not encrypted. It should generally only be used in an HTTPS + * request. + * + * The username may not contain a colon. Some protocols may impose + * additional requirements on pre-escaping the username and + * password. For instance, when used with OAuth2, both arguments must + * be URL encoded first with [url.QueryEscape]. */ - after(u: DateTime): boolean + setBasicAuth(username: string, password: string): void } - interface DateTime { + interface Request { /** - * Before reports whether the current DateTime instance is before u. + * ParseForm populates r.Form and r.PostForm. + * + * For all requests, ParseForm parses the raw query from the URL and updates + * r.Form. + * + * For POST, PUT, and PATCH requests, it also reads the request body, parses it + * as a form and puts the results into both r.PostForm and r.Form. Request body + * parameters take precedence over URL query string values in r.Form. + * + * If the request Body's size has not already been limited by [MaxBytesReader], + * the size is capped at 10MB. + * + * For other HTTP methods, or when the Content-Type is not + * application/x-www-form-urlencoded, the request Body is not read, and + * r.PostForm is initialized to a non-nil, empty value. + * + * [Request.ParseMultipartForm] calls ParseForm automatically. + * ParseForm is idempotent. */ - before(u: DateTime): boolean + parseForm(): void } - interface DateTime { + interface Request { /** - * Compare compares the current DateTime instance with u. - * If the current instance is before u, it returns -1. - * If the current instance is after u, it returns +1. - * If they're the same, it returns 0. + * ParseMultipartForm parses a request body as multipart/form-data. + * The whole request body is parsed and up to a total of maxMemory bytes of + * its file parts are stored in memory, with the remainder stored on + * disk in temporary files. + * ParseMultipartForm calls [Request.ParseForm] if necessary. + * If ParseForm returns an error, ParseMultipartForm returns it but also + * continues parsing the request body. + * After one call to ParseMultipartForm, subsequent calls have no effect. */ - compare(u: DateTime): number + parseMultipartForm(maxMemory: number): void } - interface DateTime { + interface Request { /** - * Equal reports whether the current DateTime and u represent the same time instant. - * Two DateTime can be equal even if they are in different locations. - * For example, 6:00 +0200 and 4:00 UTC are Equal. + * FormValue returns the first value for the named component of the query. + * The precedence order: + * 1. application/x-www-form-urlencoded form body (POST, PUT, PATCH only) + * 2. query parameters (always) + * 3. multipart/form-data form body (always) + * + * FormValue calls [Request.ParseMultipartForm] and [Request.ParseForm] + * if necessary and ignores any errors returned by these functions. + * If key is not present, FormValue returns the empty string. + * To access multiple values of the same key, call ParseForm and + * then inspect [Request.Form] directly. */ - equal(u: DateTime): boolean + formValue(key: string): string } - interface DateTime { + interface Request { /** - * Unix returns the current DateTime as a Unix time, aka. - * the number of seconds elapsed since January 1, 1970 UTC. + * PostFormValue returns the first value for the named component of the POST, + * PUT, or PATCH request body. URL query parameters are ignored. + * PostFormValue calls [Request.ParseMultipartForm] and [Request.ParseForm] if necessary and ignores + * any errors returned by these functions. + * If key is not present, PostFormValue returns the empty string. */ - unix(): number + postFormValue(key: string): string } - interface DateTime { + interface Request { /** - * IsZero checks whether the current DateTime instance has zero time value. + * FormFile returns the first file for the provided form key. + * FormFile calls [Request.ParseMultipartForm] and [Request.ParseForm] if necessary. */ - isZero(): boolean + formFile(key: string): [multipart.File, (multipart.FileHeader)] } - interface DateTime { + interface Request { /** - * String serializes the current DateTime instance into a formatted - * UTC date string. + * PathValue returns the value for the named path wildcard in the [ServeMux] pattern + * that matched the request. + * It returns the empty string if the request was not matched against a pattern + * or there is no such wildcard in the pattern. * - * The zero value is serialized to an empty string. + * The value is unescaped. For example, if the pattern "/b/{bucket}" matches + * the path "/b/a%2fb", PathValue("bucket") returns "a/b". */ - string(): string + pathValue(name: string): string } - interface DateTime { + interface Request { /** - * MarshalJSON implements the [json.Marshaler] interface. + * SetPathValue sets name to value, so that subsequent calls to r.PathValue(name) + * return value. + * It does not unescape value. */ - marshalJSON(): string|Array + setPathValue(name: string, value: string): void } - interface DateTime { + /** + * A Handler responds to an HTTP request. + * + * [Handler.ServeHTTP] should write reply headers and data to the [ResponseWriter] + * and then return. Returning signals that the request is finished; it + * is not valid to use the [ResponseWriter] or read from the + * [Request.Body] after or concurrently with the completion of the + * ServeHTTP call. + * + * Depending on the HTTP client software, HTTP protocol version, and + * any intermediaries between the client and the Go server, it may not + * be possible to read from the [Request.Body] after writing to the + * [ResponseWriter]. Cautious handlers should read the [Request.Body] + * first, and then reply. + * + * Except for reading the body, handlers should not modify the + * provided Request. + * + * If ServeHTTP panics, the server (the caller of ServeHTTP) assumes + * that the effect of the panic was isolated to the active request. + * It recovers the panic, logs a stack trace to the server error log, + * and either closes the network connection or sends an HTTP/2 + * RST_STREAM, depending on the HTTP protocol. To abort a handler so + * the client sees an interrupted response but the server doesn't log + * an error, panic with the value [ErrAbortHandler]. + */ + interface Handler { + [key:string]: any; + serveHTTP(_arg0: ResponseWriter, _arg1: Request): void + } + /** + * A ResponseWriter interface is used by an HTTP handler to + * construct an HTTP response. + * + * A ResponseWriter may not be used after [Handler.ServeHTTP] has returned. + */ + interface ResponseWriter { + [key:string]: any; /** - * UnmarshalJSON implements the [json.Unmarshaler] interface. + * Header returns the header map that will be sent by + * [ResponseWriter.WriteHeader]. The [Header] map also is the mechanism with which + * [Handler] implementations can set HTTP trailers. + * + * Changing the header map after a call to [ResponseWriter.WriteHeader] (or + * [ResponseWriter.Write]) has no effect unless the HTTP status code was of the + * 1xx class or the modified headers are trailers. + * + * There are two ways to set Trailers. The preferred way is to + * predeclare in the headers which trailers you will later + * send by setting the "Trailer" header to the names of the + * trailer keys which will come later. In this case, those + * keys of the Header map are treated as if they were + * trailers. See the example. The second way, for trailer + * keys not known to the [Handler] until after the first [ResponseWriter.Write], + * is to prefix the [Header] map keys with the [TrailerPrefix] + * constant value. + * + * To suppress automatic response headers (such as "Date"), set + * their value to nil. */ - unmarshalJSON(b: string|Array): void - } - interface DateTime { + header(): Header /** - * Value implements the [driver.Valuer] interface. + * Write writes the data to the connection as part of an HTTP reply. + * + * If [ResponseWriter.WriteHeader] has not yet been called, Write calls + * WriteHeader(http.StatusOK) before writing the data. If the Header + * does not contain a Content-Type line, Write adds a Content-Type set + * to the result of passing the initial 512 bytes of written data to + * [DetectContentType]. Additionally, if the total size of all written + * data is under a few KB and there are no Flush calls, the + * Content-Length header is added automatically. + * + * Depending on the HTTP protocol version and the client, calling + * Write or WriteHeader may prevent future reads on the + * Request.Body. For HTTP/1.x requests, handlers should read any + * needed request body data before writing the response. Once the + * headers have been flushed (due to either an explicit Flusher.Flush + * call or writing enough data to trigger a flush), the request body + * may be unavailable. For HTTP/2 requests, the Go HTTP server permits + * handlers to continue to read the request body while concurrently + * writing the response. However, such behavior may not be supported + * by all HTTP/2 clients. Handlers should read before writing if + * possible to maximize compatibility. */ - value(): any - } - interface DateTime { + write(_arg0: string|Array): number /** - * Scan implements [sql.Scanner] interface to scan the provided value - * into the current DateTime instance. + * WriteHeader sends an HTTP response header with the provided + * status code. + * + * If WriteHeader is not called explicitly, the first call to Write + * will trigger an implicit WriteHeader(http.StatusOK). + * Thus explicit calls to WriteHeader are mainly used to + * send error codes or 1xx informational responses. + * + * The provided code must be a valid HTTP 1xx-5xx status code. + * Any number of 1xx headers may be written, followed by at most + * one 2xx-5xx header. 1xx headers are sent immediately, but 2xx-5xx + * headers may be buffered. Use the Flusher interface to send + * buffered data. The header map is cleared when 2xx-5xx headers are + * sent, but not with 1xx headers. + * + * The server will automatically send a 100 (Continue) header + * on the first read from the request body if the request has + * an "Expect: 100-continue" header. */ - scan(value: any): void + writeHeader(statusCode: number): void } /** - * GeoPoint defines a struct for storing geo coordinates as serialized json object - * (e.g. {lon:0,lat:0}). - * - * Note: using object notation and not a plain array to avoid the confusion - * as there doesn't seem to be a fixed standard for the coordinates order. - */ - interface GeoPoint { - lon: number - lat: number - } - interface GeoPoint { + * A Server defines parameters for running an HTTP server. + * The zero value for Server is a valid configuration. + */ + interface Server { /** - * String returns the string representation of the current GeoPoint instance. + * Addr optionally specifies the TCP address for the server to listen on, + * in the form "host:port". If empty, ":http" (port 80) is used. + * The service names are defined in RFC 6335 and assigned by IANA. + * See net.Dial for details of the address format. */ - string(): string - } - interface GeoPoint { + addr: string + handler: Handler // handler to invoke, http.DefaultServeMux if nil /** - * AsMap implements [core.mapExtractor] and returns a value suitable - * to be used in an API rule expression. + * DisableGeneralOptionsHandler, if true, passes "OPTIONS *" requests to the Handler, + * otherwise responds with 200 OK and Content-Length: 0. */ - asMap(): _TygojaDict - } - interface GeoPoint { + disableGeneralOptionsHandler: boolean /** - * Value implements the [driver.Valuer] interface. + * TLSConfig optionally provides a TLS configuration for use + * by ServeTLS and ListenAndServeTLS. Note that this value is + * cloned by ServeTLS and ListenAndServeTLS, so it's not + * possible to modify the configuration with methods like + * tls.Config.SetSessionTicketKeys. To use + * SetSessionTicketKeys, use Server.Serve with a TLS Listener + * instead. */ - value(): any - } - interface GeoPoint { + tlsConfig?: any /** - * Scan implements [sql.Scanner] interface to scan the provided value - * into the current GeoPoint instance. + * ReadTimeout is the maximum duration for reading the entire + * request, including the body. A zero or negative value means + * there will be no timeout. * - * The value argument could be nil (no-op), another GeoPoint instance, - * map or serialized json object with lat-lon props. + * Because ReadTimeout does not let Handlers make per-request + * decisions on each request body's acceptable deadline or + * upload rate, most users will prefer to use + * ReadHeaderTimeout. It is valid to use them both. */ - scan(value: any): void - } - /** - * JSONArray defines a slice that is safe for json and db read/write. - */ - interface JSONArray extends Array{} - interface JSONArray { + readTimeout: time.Duration /** - * MarshalJSON implements the [json.Marshaler] interface. + * ReadHeaderTimeout is the amount of time allowed to read + * request headers. The connection's read deadline is reset + * after reading the headers and the Handler can decide what + * is considered too slow for the body. If zero, the value of + * ReadTimeout is used. If negative, or if zero and ReadTimeout + * is zero or negative, there is no timeout. */ - marshalJSON(): string|Array - } - interface JSONArray { + readHeaderTimeout: time.Duration /** - * String returns the string representation of the current json array. + * WriteTimeout is the maximum duration before timing out + * writes of the response. It is reset whenever a new + * request's header is read. Like ReadTimeout, it does not + * let Handlers make decisions on a per-request basis. + * A zero or negative value means there will be no timeout. */ - string(): string - } - interface JSONArray { + writeTimeout: time.Duration /** - * Value implements the [driver.Valuer] interface. + * IdleTimeout is the maximum amount of time to wait for the + * next request when keep-alives are enabled. If zero, the value + * of ReadTimeout is used. If negative, or if zero and ReadTimeout + * is zero or negative, there is no timeout. */ - value(): any - } - interface JSONArray { + idleTimeout: time.Duration /** - * Scan implements [sql.Scanner] interface to scan the provided value - * into the current JSONArray[T] instance. + * MaxHeaderBytes controls the maximum number of bytes the + * server will read parsing the request header's keys and + * values, including the request line. It does not limit the + * size of the request body. + * If zero, DefaultMaxHeaderBytes is used. */ - scan(value: any): void - } - /** - * JSONMap defines a map that is safe for json and db read/write. - */ - interface JSONMap extends _TygojaDict{} - interface JSONMap { + maxHeaderBytes: number /** - * Get retrieves a single value from the current JSONMap[T]. - * - * This helper was added primarily to assist the goja integration since custom map types - * don't have direct access to the map keys (https://pkg.go.dev/github.com/dop251/goja#hdr-Maps_with_methods). + * MaxHeaderValueCount controls the maximum number of header + * values that the server is willing to parse from a request. + * If zero, DefaultMaxHeaderValueCount is used. + * Note that comma-separated values in a single header line are + * counted once, while values sent as multiple header lines are + * counted multiple times. */ - get(key: string): T - } - interface JSONMap { + maxHeaderValueCount: number /** - * Set sets a single value in the current JSONMap[T]. + * TLSNextProto optionally specifies a function to take over + * ownership of the provided TLS connection when an ALPN + * protocol upgrade has occurred. The map key is the protocol + * name negotiated. The Handler argument should be used to + * handle HTTP requests and will initialize the Request's TLS + * and RemoteAddr if not already set. The connection is + * automatically closed when the function returns. + * If TLSNextProto is not nil, HTTP/2 support is not enabled + * automatically. * - * This helper was added primarily to assist the goja integration since custom map types - * don't have direct access to the map keys (https://pkg.go.dev/github.com/dop251/goja#hdr-Maps_with_methods). + * Historically, TLSNextProto was used to disable HTTP/2 support. + * The Server.Protocols field now provides a simpler way to do this. */ - set(key: string, value: T): void - } - interface JSONMap { + tlsNextProto: _TygojaDict /** - * MarshalJSON implements the [json.Marshaler] interface. + * ConnState specifies an optional callback function that is + * called when a client connection changes state. See the + * ConnState type and associated constants for details. */ - marshalJSON(): string|Array - } - interface JSONMap { + connState: (_arg0: net.Conn, _arg1: ConnState) => void /** - * String returns the string representation of the current json map. + * ErrorLog specifies an optional logger for errors accepting + * connections, unexpected behavior from handlers, and + * underlying FileSystem errors. + * If nil, logging is done via the log package's standard logger. */ - string(): string - } - interface JSONMap { + errorLog?: any /** - * Value implements the [driver.Valuer] interface. + * BaseContext optionally specifies a function that returns + * the base context for incoming requests on this server. + * The provided Listener is the specific Listener that's + * about to start accepting requests. + * If BaseContext is nil, the default is context.Background(). + * If non-nil, it must return a non-nil context. */ - value(): any - } - interface JSONMap { + baseContext: (_arg0: net.Listener) => context.Context /** - * Scan implements [sql.Scanner] interface to scan the provided value - * into the current JSONMap[T] instance. + * ConnContext optionally specifies a function that modifies + * the context used for a new connection c. The provided ctx + * is derived from the base context and has a ServerContextKey + * value. */ - scan(value: any): void - } - /** - * JSONRaw defines a json value type that is safe for db read/write. - */ - interface JSONRaw extends Array{} - interface JSONRaw { + connContext: (ctx: context.Context, c: net.Conn) => context.Context /** - * String returns the current JSONRaw instance as a json encoded string. + * HTTP2 configures HTTP/2 connections. */ - string(): string - } - interface JSONRaw { + http2?: HTTP2Config /** - * MarshalJSON implements the [json.Marshaler] interface. + * Protocols is the set of protocols accepted by the server. + * + * If Protocols includes UnencryptedHTTP2, the server will accept + * unencrypted HTTP/2 connections. The server can serve both + * HTTP/1 and unencrypted HTTP/2 on the same address and port. + * + * If Protocols is nil, the default is usually HTTP/1 and HTTP/2. + * If TLSNextProto is non-nil and does not contain an "h2" entry, + * the default is HTTP/1 only. */ - marshalJSON(): string|Array - } - interface JSONRaw { + protocols?: Protocols /** - * UnmarshalJSON implements the [json.Unmarshaler] interface. + * DisableClientPriority specifies whether client-specified priority, as + * specified in RFC 9218, should be respected or not. + * + * This field only takes effect if using HTTP/2, and if no custom write + * scheduler is defined for the HTTP/2 server. Otherwise, this field is a + * no-op. + * + * If set to true, requests will be served in a round-robin manner, without + * prioritization. */ - unmarshalJSON(b: string|Array): void + disableClientPriority: boolean } - interface JSONRaw { + interface Server { /** - * Value implements the [driver.Valuer] interface. + * Close immediately closes all active net.Listeners and any + * connections in state [StateNew], [StateActive], or [StateIdle]. For a + * graceful shutdown, use [Server.Shutdown]. + * + * Close does not attempt to close (and does not even know about) + * any hijacked connections, such as WebSockets. + * + * Close returns any error returned from closing the [Server]'s + * underlying Listener(s). */ - value(): any + close(): void } - interface JSONRaw { + interface Server { /** - * Scan implements [sql.Scanner] interface to scan the provided value - * into the current JSONRaw instance. - */ - scan(value: any): void - } -} - -namespace search { - /** - * Result defines the returned search result structure. - */ - interface Result { - items: any - page: number - perPage: number - totalItems: number - totalPages: number + * Shutdown gracefully shuts down the server without interrupting any + * active connections. Shutdown works by first closing all open + * listeners, then closing all idle connections, and then waiting + * indefinitely for connections to return to idle and then shut down. + * If the provided context expires before the shutdown is complete, + * Shutdown returns the context's error, otherwise it returns any + * error returned from closing the [Server]'s underlying Listener(s). + * + * When Shutdown is called, [Serve], [ServeTLS], [ListenAndServe], and + * [ListenAndServeTLS] immediately return [ErrServerClosed]. Make sure the + * program doesn't exit and waits instead for Shutdown to return. + * + * Shutdown does not attempt to close nor wait for hijacked + * connections such as WebSockets. The caller of Shutdown should + * separately notify such long-lived connections of shutdown and wait + * for them to close, if desired. See [Server.RegisterOnShutdown] for a way to + * register shutdown notification functions. + * + * Once Shutdown has been called on a server, it may not be reused; + * future calls to methods such as Serve will return ErrServerClosed. + */ + shutdown(ctx: context.Context): void } - /** - * ResolverResult defines a single FieldResolver.Resolve() successfully parsed result. - */ - interface ResolverResult { + interface Server { /** - * Identifier is the plain SQL identifier/column that will be used - * in the final db expression as left or right operand. + * RegisterOnShutdown registers a function to call on [Server.Shutdown]. + * This can be used to gracefully shutdown connections that have + * undergone ALPN protocol upgrade or that have been hijacked. + * This function should start protocol-specific graceful shutdown, + * but should not wait for shutdown to complete. */ - identifier: string + registerOnShutdown(f: () => void): void + } + interface Server { /** - * NullFallback specify the preference for how NULL or empty values - * should be resolved (default to "auto"). + * ListenAndServe listens on the TCP network address s.Addr and then + * calls [Serve] to handle requests on incoming connections. + * Accepted connections are configured to enable TCP keep-alives. * - * Set to NullFallbackDisabled to prevent any COALESCE or NULL fallbacks. - * Set to NullFallbackEnforced to prefer COALESCE or NULL fallbacks when needed. + * If s.Addr is blank, ":http" is used. + * + * ListenAndServe always returns a non-nil error. After [Server.Shutdown] or [Server.Close], + * the returned error is [ErrServerClosed]. */ - nullFallback: NullFallbackPreference + listenAndServe(): void + } + interface Server { /** - * 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. + * Serve accepts incoming connections on the Listener l, creating a + * new service goroutine for each. The service goroutines read requests and + * then call s.Handler to reply to them. + * + * HTTP/2 support is only enabled if the Listener returns [*tls.Conn] + * connections and they were configured with "h2" in the TLS + * Config.NextProtos. + * + * Serve always returns a non-nil error and closes l. + * After [Server.Shutdown] or [Server.Close], the returned error is [ErrServerClosed]. */ - params: dbx.Params + serve(l: net.Listener): void + } + interface Server { /** - * MultiMatchSubQuery is an optional sub query expression that will be added - * in addition to the combined ResolverResult expression during build. + * ServeTLS accepts incoming connections on the Listener l, creating a + * new service goroutine for each. The service goroutines perform TLS + * setup and then read requests, calling s.Handler to reply to them. + * + * Files containing a certificate and matching private key for the + * server must be provided if neither the [Server]'s + * TLSConfig.Certificates, TLSConfig.GetCertificate nor + * config.GetConfigForClient are populated. + * If the certificate is signed by a certificate authority, the + * certFile should be the concatenation of the server's certificate, + * any intermediates, and the CA's certificate. + * + * ServeTLS always returns a non-nil error. After [Server.Shutdown] or [Server.Close], the + * returned error is [ErrServerClosed]. */ - multiMatchSubQuery?: MultiMatchSubquery + serveTLS(l: net.Listener, certFile: string, keyFile: string): void + } + interface Server { /** - * AfterBuild is an optional function that will be called after building - * and combining the result of both resolved operands/sides in a single expression. + * SetKeepAlivesEnabled controls whether HTTP keep-alives are enabled. + * By default, keep-alives are always enabled. Only very + * resource-constrained environments or servers in the process of + * shutting down should disable them. */ - afterBuild: (expr: dbx.Expression) => dbx.Expression - } -} - -/** - * Package multipart implements MIME multipart parsing, as defined in RFC - * 2046. - * - * The implementation is sufficient for HTTP (RFC 2388) and the multipart - * bodies generated by popular browsers. - * - * # Limits - * - * To protect against malicious inputs, this package sets limits on the size - * of the MIME data it processes. - * - * [Reader.NextPart] and [Reader.NextRawPart] limit the number of headers in a - * part to 10000 and [Reader.ReadForm] limits the total number of headers in all - * FileHeaders to 10000. - * These limits may be adjusted with the GODEBUG=multipartmaxheaders= - * setting. - * - * Reader.ReadForm further limits the number of parts in a form to 1000. - * This limit may be adjusted with the GODEBUG=multipartmaxparts= - * setting. - */ -namespace multipart { - /** - * A FileHeader describes a file part of a multipart request. - */ - interface FileHeader { - filename: string - header: textproto.MIMEHeader - size: number + setKeepAlivesEnabled(v: boolean): void } - interface FileHeader { + interface Server { /** - * Open opens and returns the [FileHeader]'s associated File. + * ListenAndServeTLS listens on the TCP network address s.Addr and + * then calls [ServeTLS] to handle requests on incoming TLS connections. + * Accepted connections are configured to enable TCP keep-alives. + * + * Filenames containing a certificate and matching private key for the + * server must be provided if neither the [Server]'s TLSConfig.Certificates + * nor TLSConfig.GetCertificate are populated. If the certificate is + * signed by a certificate authority, the certFile should be the + * concatenation of the server's certificate, any intermediates, and + * the CA's certificate. + * + * If s.Addr is blank, ":https" is used. + * + * ListenAndServeTLS always returns a non-nil error. After [Server.Shutdown] or + * [Server.Close], the returned error is [ErrServerClosed]. */ - open(): File + listenAndServeTLS(certFile: string, keyFile: string): void } } /** - * Package http provides HTTP client and server implementations. - * - * [Get], [Head], [Post], and [PostForm] make HTTP (or HTTPS) requests: - * - * ``` - * resp, err := http.Get("http://example.com/") - * ... - * resp, err := http.Post("http://example.com/upload", "image/jpeg", &buf) - * ... - * resp, err := http.PostForm("http://example.com/form", - * url.Values{"key": {"Value"}, "id": {"123"}}) - * ``` - * - * The caller must close the response body when finished with it: - * - * ``` - * resp, err := http.Get("http://example.com/") - * if err != nil { - * // handle error - * } - * defer resp.Body.Close() - * body, err := io.ReadAll(resp.Body) - * // ... - * ``` - * - * # Clients and Transports - * - * For control over HTTP client headers, redirect policy, and other - * settings, create a [Client]: - * - * ``` - * client := &http.Client{ - * CheckRedirect: redirectPolicyFunc, - * } - * - * resp, err := client.Get("http://example.com") - * // ... - * - * req, err := http.NewRequest("GET", "http://example.com", nil) - * // ... - * req.Header.Add("If-None-Match", `W/"wyzzy"`) - * resp, err := client.Do(req) - * // ... - * ``` - * - * For control over proxies, TLS configuration, keep-alives, - * compression, and other settings, create a [Transport]: - * - * ``` - * tr := &http.Transport{ - * MaxIdleConns: 10, - * IdleConnTimeout: 30 * time.Second, - * DisableCompression: true, - * } - * client := &http.Client{Transport: tr} - * resp, err := client.Get("https://example.com") - * ``` - * - * Clients and Transports are safe for concurrent use by multiple - * goroutines and for efficiency should only be created once and re-used. - * - * # Servers - * - * ListenAndServe starts an HTTP server with a given address and handler. - * The handler is usually nil, which means to use [DefaultServeMux]. - * [Handle] and [HandleFunc] add handlers to [DefaultServeMux]: - * - * ``` - * http.Handle("/foo", fooHandler) - * - * http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) { - * fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path)) - * }) - * - * log.Fatal(http.ListenAndServe(":8080", nil)) - * ``` - * - * More control over the server's behavior is available by creating a - * custom Server: - * - * ``` - * s := &http.Server{ - * Addr: ":8080", - * Handler: myHandler, - * ReadTimeout: 10 * time.Second, - * WriteTimeout: 10 * time.Second, - * MaxHeaderBytes: 1 << 20, - * } - * log.Fatal(s.ListenAndServe()) - * ``` - * - * # HTTP/2 - * - * The http package has transparent support for the HTTP/2 protocol. - * - * [Server] and [DefaultTransport] automatically enable HTTP/2 support - * when using HTTPS. [Transport] does not enable HTTP/2 by default. - * - * To enable or disable support for HTTP/1, HTTP/2, and/or unencrypted HTTP/2, - * see the [Server.Protocols] and [Transport.Protocols] configuration fields. - * - * To configure advanced HTTP/2 features, see the [Server.HTTP2] and - * [Transport.HTTP2] configuration fields. - * - * Alternatively, the following GODEBUG settings are currently supported: - * - * ``` - * GODEBUG=http2client=0 # disable HTTP/2 client support - * GODEBUG=http2server=0 # disable HTTP/2 server support - * GODEBUG=http2debug=1 # enable verbose HTTP/2 debug logs - * GODEBUG=http2debug=2 # ... even more verbose, with frame dumps - * ``` + * Package blob defines a lightweight abstration for interacting with + * various storage services (local filesystem, S3, etc.). * - * The "omithttp2" build tag may be used to disable the HTTP/2 implementation - * contained in the http package. + * NB! + * For compatibility with earlier PocketBase versions and to prevent + * unnecessary breaking changes, this package is based and implemented + * as a minimal, stripped down version of the previously used gocloud.dev/blob. + * While there is no promise that it won't diverge in the future to accommodate + * better some PocketBase specific use cases, currently it copies and + * tries to follow as close as possible the same implementations, + * conventions and rules for the key escaping/unescaping, blob read/write + * interfaces and struct options as gocloud.dev/blob, therefore the + * credits goes to the original Go Cloud Development Kit Authors. */ -namespace http { +namespace blob { /** - * PushOptions describes options for [Pusher.Push]. + * ListObject represents a single blob returned from List. */ - interface PushOptions { + interface ListObject { /** - * Method specifies the HTTP method for the promised request. - * If set, it must be "GET" or "HEAD". Empty means "GET". + * Key is the key for this blob. */ - method: string + key: string /** - * Header specifies additional promised request headers. This cannot - * include HTTP/2 pseudo header fields like ":path" and ":scheme", - * which will be added automatically. + * ModTime is the time the blob was last modified. */ - header: Header + modTime: time.Time + /** + * Size is the size of the blob's content in bytes. + */ + size: number + /** + * MD5 is an MD5 hash of the blob contents or nil if not available. + */ + md5: string|Array + /** + * IsDir indicates that this result represents a "directory" in the + * hierarchical namespace, ending in ListOptions.Delimiter. Key can be + * passed as ListOptions.Prefix to list items in the "directory". + * Fields other than Key and IsDir will not be set if IsDir is true. + */ + isDir: boolean } - // @ts-ignore - import urlpkg = url /** - * A Request represents an HTTP request received by a server - * or to be sent by a client. - * - * The field semantics differ slightly between client and server - * usage. In addition to the notes on the fields below, see the - * documentation for [Request.Write] and [RoundTripper]. + * Attributes contains attributes about a blob. */ - interface Request { + interface Attributes { /** - * Method specifies the HTTP method (GET, POST, PUT, etc.). - * For client requests, an empty string means GET. + * CacheControl specifies caching attributes that services may use + * when serving the blob. + * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control */ - method: string + cacheControl: string /** - * URL specifies either the URI being requested (for server - * requests) or the URL to access (for client requests). - * - * For server requests, the URL is parsed from the URI - * supplied on the Request-Line as stored in RequestURI. For - * most requests, fields other than Path and RawQuery will be - * empty. (See RFC 7230, Section 5.3) - * - * For client requests, the URL's Host specifies the server to - * connect to, while the Request's Host field optionally - * specifies the Host header value to send in the HTTP - * request. + * ContentDisposition specifies whether the blob content is expected to be + * displayed inline or as an attachment. + * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition */ - url?: url.URL + contentDisposition: string /** - * The protocol version for incoming server requests. - * - * For client requests, these fields are ignored. The HTTP - * client code always uses either HTTP/1.1 or HTTP/2. - * See the docs on Transport for details. + * ContentEncoding specifies the encoding used for the blob's content, if any. + * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding */ - proto: string // "HTTP/1.0" - protoMajor: number // 1 - protoMinor: number // 0 + contentEncoding: string /** - * Header contains the request header fields either received - * by the server or to be sent by the client. - * - * If a server received a request with header lines, - * - * ``` - * Host: example.com - * accept-encoding: gzip, deflate - * Accept-Language: en-us - * fOO: Bar - * foo: two - * ``` - * - * then - * - * ``` - * Header = map[string][]string{ - * "Accept-Encoding": {"gzip, deflate"}, - * "Accept-Language": {"en-us"}, - * "Foo": {"Bar", "two"}, - * } - * ``` + * ContentLanguage specifies the language used in the blob's content, if any. + * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Language + */ + contentLanguage: string + /** + * ContentType is the MIME type of the blob. It will not be empty. + * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type + */ + contentType: string + /** + * Metadata holds key/value pairs associated with the blob. + * Keys are guaranteed to be in lowercase, even if the backend service + * has case-sensitive keys (although note that Metadata written via + * this package will always be lowercased). If there are duplicate + * case-insensitive keys (e.g., "foo" and "FOO"), only one value + * will be kept, and it is undefined which one. + */ + metadata: _TygojaDict + /** + * CreateTime is the time the blob was created, if available. If not available, + * CreateTime will be the zero time. + */ + createTime: time.Time + /** + * ModTime is the time the blob was last modified. + */ + modTime: time.Time + /** + * Size is the size of the blob's content in bytes. + */ + size: number + /** + * MD5 is an MD5 hash of the blob contents or nil if not available. + */ + md5: string|Array + /** + * ETag for the blob; see https://en.wikipedia.org/wiki/HTTP_ETag. + */ + eTag: string + } + /** + * WriterOptions sets options for NewWriter. + */ + interface WriterOptions { + /** + * BufferSize changes the default size in bytes of the chunks that + * Writer will upload in a single request; larger blobs will be split into + * multiple requests. * - * For incoming requests, the Host header is promoted to the - * Request.Host field and removed from the Header map. + * This option may be ignored by some drivers. * - * HTTP defines that header names are case-insensitive. The - * request parser implements this by using CanonicalHeaderKey, - * making the first character and any characters following a - * hyphen uppercase and the rest lowercase. + * If 0, the driver will choose a reasonable default. * - * For client requests, certain headers such as Content-Length - * and Connection are automatically written when needed and - * values in Header may be ignored. See the documentation - * for the Request.Write method. + * If the Writer is used to do many small writes concurrently, using a + * smaller BufferSize may reduce memory usage. */ - header: Header + bufferSize: number /** - * Body is the request's body. - * - * For client requests, a nil body means the request has no - * body, such as a GET request. The HTTP Client's Transport - * is responsible for calling the Close method. + * MaxConcurrency changes the default concurrency for parts of an upload. * - * For server requests, the Request Body is always non-nil - * but will return EOF immediately when no body is present. - * The Server will close the request body. The ServeHTTP - * Handler does not need to. + * This option may be ignored by some drivers. * - * Body must allow Read to be called concurrently with Close. - * In particular, calling Close should unblock a Read waiting - * for input. + * If 0, the driver will choose a reasonable default. + */ + maxConcurrency: number + /** + * CacheControl specifies caching attributes that services may use + * when serving the blob. + * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control + */ + cacheControl: string + /** + * ContentDisposition specifies whether the blob content is expected to be + * displayed inline or as an attachment. + * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition + */ + contentDisposition: string + /** + * ContentEncoding specifies the encoding used for the blob's content, if any. + * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding + */ + contentEncoding: string + /** + * ContentLanguage specifies the language used in the blob's content, if any. + * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Language + */ + contentLanguage: string + /** + * ContentType specifies the MIME type of the blob being written. If not set, + * it will be inferred from the content using the algorithm described at + * http://mimesniff.spec.whatwg.org/. + * Set DisableContentTypeDetection to true to disable the above and force + * the ContentType to stay empty. + * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type + */ + contentType: string + /** + * When true, if ContentType is the empty string, it will stay the empty + * string rather than being inferred from the content. + * Note that while the blob will be written with an empty string ContentType, + * most providers will fill one in during reads, so don't expect an empty + * ContentType if you read the blob back. + */ + disableContentTypeDetection: boolean + /** + * ContentMD5 is used as a message integrity check. + * If len(ContentMD5) > 0, the MD5 hash of the bytes written must match + * ContentMD5, or Close will return an error without completing the write. + * https://tools.ietf.org/html/rfc1864 + */ + contentMD5: string|Array + /** + * Metadata holds key/value strings to be associated with the blob, or nil. + * Keys may not be empty, and are lowercased before being written. + * Duplicate case-insensitive keys (e.g., "foo" and "FOO") will result in + * an error. + */ + metadata: _TygojaDict + } + /** + * Reader reads bytes from a blob. + * It implements io.ReadSeekCloser, and must be closed after reads are finished. + */ + interface Reader { + } + interface Reader { + /** + * Read implements io.Reader (https://golang.org/pkg/io/#Reader). + */ + read(p: string|Array): number + } + interface Reader { + /** + * Seek implements io.Seeker (https://golang.org/pkg/io/#Seeker). + */ + seek(offset: number, whence: number): number + } + interface Reader { + /** + * Close implements io.Closer (https://golang.org/pkg/io/#Closer). */ - body: io.ReadCloser + close(): void + } + interface Reader { /** - * GetBody defines an optional func to return a new copy of - * Body. It is used for client requests when a redirect requires - * reading the body more than once. Use of GetBody still - * requires setting Body. - * - * For server requests, it is unused. + * ContentType returns the MIME type of the blob. */ - getBody: () => io.ReadCloser + contentType(): string + } + interface Reader { /** - * ContentLength records the length of the associated content. - * The value -1 indicates that the length is unknown. - * Values >= 0 indicate that the given number of bytes may - * be read from Body. - * - * For client requests, a value of 0 with a non-nil Body is - * also treated as unknown. + * ModTime returns the time the blob was last modified. */ - contentLength: number + modTime(): time.Time + } + interface Reader { /** - * TransferEncoding lists the transfer encodings from outermost to - * innermost. An empty list denotes the "identity" encoding. - * TransferEncoding can usually be ignored; chunked encoding is - * automatically added and removed as necessary when sending and - * receiving requests. + * Size returns the size of the blob content in bytes. */ - transferEncoding: Array + size(): number + } + interface Reader { /** - * Close indicates whether to close the connection after - * replying to this request (for servers) or after sending this - * request and reading its response (for clients). - * - * For server requests, the HTTP server handles this automatically - * and this field is not needed by Handlers. + * WriteTo reads from r and writes to w until there's no more data or + * an error occurs. + * The return value is the number of bytes written to w. * - * For client requests, setting this field prevents re-use of - * TCP connections between requests to the same hosts, as if - * Transport.DisableKeepAlives were set. + * It implements the io.WriterTo interface. */ - close: boolean + writeTo(w: io.Writer): number + } + /** + * Writer writes bytes to a blob. + * + * It implements io.WriteCloser (https://golang.org/pkg/io/#Closer), and must be + * closed after all writes are done. + */ + interface Writer { + } + interface Writer { /** - * For server requests, Host specifies the host on which the - * URL is sought. For HTTP/1 (per RFC 7230, section 5.4), this - * is either the value of the "Host" header or the host name - * given in the URL itself. For HTTP/2, it is the value of the - * ":authority" pseudo-header field. - * It may be of the form "host:port". For international domain - * names, Host may be in Punycode or Unicode form. Use - * golang.org/x/net/idna to convert it to either format if - * needed. - * To prevent DNS rebinding attacks, server Handlers should - * validate that the Host header has a value for which the - * Handler considers itself authoritative. The included - * ServeMux supports patterns registered to particular host - * names and thus protects its registered Handlers. + * Write implements the io.Writer interface (https://golang.org/pkg/io/#Writer). * - * For client requests, Host optionally overrides the Host - * header to send. If empty, the Request.Write method uses - * the value of URL.Host. Host may contain an international - * domain name. + * Writes may happen asynchronously, so the returned error can be nil + * even if the actual write eventually fails. The write is only guaranteed to + * have succeeded if Close returns no error. */ - host: string + write(p: string|Array): number + } + interface Writer { /** - * Form contains the parsed form data, including both the URL - * field's query parameters and the PATCH, POST, or PUT form data. - * This field is only available after ParseForm is called. - * The HTTP client ignores Form and uses Body instead. + * Close closes the blob writer. The write operation is not guaranteed + * to have succeeded until Close returns with no error. + * + * Close may return an error if the context provided to create the + * Writer is canceled or reaches its deadline. */ - form: url.Values + close(): void + } + interface Writer { /** - * PostForm contains the parsed form data from PATCH, POST - * or PUT body parameters. + * ReadFrom reads from r and writes to w until EOF or error. + * The return value is the number of bytes read from r. * - * This field is only available after ParseForm is called. - * The HTTP client ignores PostForm and uses Body instead. + * It implements the io.ReaderFrom interface. */ - postForm: url.Values + readFrom(r: io.Reader): number + } +} + +/** + * Package jwt is a Go implementation of JSON Web Tokens: http://self-issued.info/docs/draft-jones-json-web-token.html + * + * See README.md for more info. + */ +namespace jwt { + /** + * MapClaims is a claims type that uses the map[string]any for JSON + * decoding. This is the default claims type if you don't supply one + */ + interface MapClaims extends _TygojaDict{} + interface MapClaims { /** - * MultipartForm is the parsed multipart form, including file uploads. - * This field is only available after ParseMultipartForm is called. - * The HTTP client ignores MultipartForm and uses Body instead. + * GetExpirationTime implements the Claims interface. */ - multipartForm?: multipart.Form + getExpirationTime(): (NumericDate) + } + interface MapClaims { /** - * Trailer specifies additional headers that are sent after the request - * body. - * - * For server requests, the Trailer map initially contains only the - * trailer keys, with nil values. (The client declares which trailers it - * will later send.) While the handler is reading from Body, it must - * not reference Trailer. After reading from Body returns EOF, Trailer - * can be read again and will contain non-nil values, if they were sent - * by the client. - * - * For client requests, Trailer must be initialized to a map containing - * the trailer keys to later send. The values may be nil or their final - * values. The ContentLength must be 0 or -1, to send a chunked request. - * After the HTTP request is sent the map values can be updated while - * the request body is read. Once the body returns EOF, the caller must - * not mutate Trailer. - * - * Writing a request whose Trailer contains a key with invalid bytes - * (such as CR or LF), or such a value present when Write begins, - * returns an error. - * - * Few HTTP clients, servers, or proxies support HTTP trailers. + * GetNotBefore implements the Claims interface. */ - trailer: Header + getNotBefore(): (NumericDate) + } + interface MapClaims { /** - * RemoteAddr allows HTTP servers and other software to record - * the network address that sent the request, usually for - * logging. This field is not filled in by ReadRequest and - * has no defined format. The HTTP server in this package - * sets RemoteAddr to an "IP:port" address before invoking a - * handler. - * This field is ignored by the HTTP client. + * GetIssuedAt implements the Claims interface. */ - remoteAddr: string + getIssuedAt(): (NumericDate) + } + interface MapClaims { /** - * RequestURI is the unmodified request-target of the - * Request-Line (RFC 7230, Section 3.1.1) as sent by the client - * to a server. Usually the URL field should be used instead. - * It is an error to set this field in an HTTP client request. + * GetAudience implements the Claims interface. */ - requestURI: string + getAudience(): ClaimStrings + } + interface MapClaims { /** - * TLS allows HTTP servers and other software to record - * information about the TLS connection on which the request - * was received. This field is not filled in by ReadRequest. - * The HTTP server in this package sets the field for - * TLS-enabled connections before invoking a handler; - * otherwise it leaves the field nil. - * This field is ignored by the HTTP client. + * GetIssuer implements the Claims interface. */ - tls?: any + getIssuer(): string + } + interface MapClaims { /** - * Cancel is an optional channel whose closure indicates that the client - * request should be regarded as canceled. Not all implementations of - * RoundTripper may support Cancel. - * - * For server requests, this field is not applicable. - * - * Deprecated: Set the Request's context with NewRequestWithContext - * instead. If a Request's Cancel field and context are both - * set, it is undefined whether Cancel is respected. + * GetSubject implements the Claims interface. */ - cancel: undefined + getSubject(): string + } +} + +/** + * Package types implements some commonly used db serializable types + * like datetime, json, etc. + */ +namespace types { + /** + * DateTime represents a [time.Time] instance in UTC that is wrapped + * and serialized using the app default date layout. + */ + interface DateTime { + } + interface DateTime { /** - * Response is the redirect response which caused this request - * to be created. This field is only populated during client - * redirects. + * Time returns the internal [time.Time] instance. */ - response?: Response + time(): time.Time + } + interface DateTime { /** - * Pattern is the [ServeMux] pattern that matched the request. - * It is empty if the request was not matched against a pattern. + * Add returns a new DateTime based on the current DateTime + the specified duration. */ - pattern: string + add(duration: time.Duration): DateTime } - interface Request { + interface DateTime { /** - * Context returns the request's context. To change the context, use - * [Request.Clone] or [Request.WithContext]. - * - * The returned context is always non-nil; it defaults to the - * background context. + * Sub returns a [time.Duration] by subtracting the specified DateTime from the current one. * - * For outgoing client requests, the context controls cancellation. + * If the result exceeds the maximum (or minimum) value that can be stored in a [time.Duration], + * the maximum (or minimum) duration will be returned. + */ + sub(u: DateTime): time.Duration + } + interface DateTime { + /** + * AddDate returns a new DateTime based on the current one + duration. * - * For incoming server requests, the context is canceled when the - * client's connection closes, the request is canceled (with HTTP/2), - * or when the ServeHTTP method returns. + * It follows the same rules as [time.AddDate]. + */ + addDate(years: number, months: number, days: number): DateTime + } + interface DateTime { + /** + * After reports whether the current DateTime instance is after u. */ - context(): context.Context + after(u: DateTime): boolean } - interface Request { + interface DateTime { /** - * WithContext returns a shallow copy of r with its context changed - * to ctx. The provided ctx must be non-nil. - * - * For outgoing client request, the context controls the entire - * lifetime of a request and its response: obtaining a connection, - * sending the request, and reading the response headers and body. - * - * To create a new request with a context, use [NewRequestWithContext]. - * To make a deep copy of a request with a new context, use [Request.Clone]. + * Before reports whether the current DateTime instance is before u. */ - withContext(ctx: context.Context): (Request) + before(u: DateTime): boolean } - interface Request { + interface DateTime { /** - * Clone returns a deep copy of r with its context changed to ctx. - * The provided ctx must be non-nil. - * - * Clone only makes a shallow copy of the Body field. - * - * For an outgoing client request, the context controls the entire - * lifetime of a request and its response: obtaining a connection, - * sending the request, and reading the response headers and body. + * Compare compares the current DateTime instance with u. + * If the current instance is before u, it returns -1. + * If the current instance is after u, it returns +1. + * If they're the same, it returns 0. */ - clone(ctx: context.Context): (Request) + compare(u: DateTime): number } - interface Request { + interface DateTime { /** - * ProtoAtLeast reports whether the HTTP protocol used - * in the request is at least major.minor. + * Equal reports whether the current DateTime and u represent the same time instant. + * Two DateTime can be equal even if they are in different locations. + * For example, 6:00 +0200 and 4:00 UTC are Equal. */ - protoAtLeast(major: number, minor: number): boolean + equal(u: DateTime): boolean } - interface Request { + interface DateTime { /** - * UserAgent returns the client's User-Agent, if sent in the request. + * Unix returns the current DateTime as a Unix time, aka. + * the number of seconds elapsed since January 1, 1970 UTC. */ - userAgent(): string + unix(): number } - interface Request { + interface DateTime { /** - * Cookies parses and returns the HTTP cookies sent with the request. + * IsZero checks whether the current DateTime instance has zero time value. */ - cookies(): Array<(Cookie | undefined)> + isZero(): boolean } - interface Request { + interface DateTime { /** - * CookiesNamed parses and returns the named HTTP cookies sent with the request - * or an empty slice if none matched. + * String serializes the current DateTime instance into a formatted + * UTC date string. + * + * The zero value is serialized to an empty string. */ - cookiesNamed(name: string): Array<(Cookie | undefined)> + string(): string } - interface Request { + interface DateTime { /** - * Cookie returns the named cookie provided in the request or - * [ErrNoCookie] if not found. - * If multiple cookies match the given name, only one cookie will - * be returned. + * MarshalJSON implements the [json.Marshaler] interface. */ - cookie(name: string): (Cookie) + marshalJSON(): string|Array } - interface Request { + interface DateTime { /** - * AddCookie adds a cookie to the request. Per RFC 6265 section 5.4, - * AddCookie does not attach more than one [Cookie] header field. That - * means all cookies, if any, are written into the same line, - * separated by semicolon. - * AddCookie only sanitizes c's name and value, and does not sanitize - * a Cookie header already present in the request. + * UnmarshalJSON implements the [json.Unmarshaler] interface. */ - addCookie(c: Cookie): void + unmarshalJSON(b: string|Array): void } - interface Request { + interface DateTime { /** - * Referer returns the referring URL, if sent in the request. - * - * Referer is misspelled as in the request itself, a mistake from the - * earliest days of HTTP. This value can also be fetched from the - * [Header] map as Header["Referer"]; the benefit of making it available - * as a method is that the compiler can diagnose programs that use the - * alternate (correct English) spelling req.Referrer() but cannot - * diagnose programs that use Header["Referrer"]. + * Value implements the [driver.Valuer] interface. */ - referer(): string + value(): any } - interface Request { + interface DateTime { /** - * MultipartReader returns a MIME multipart reader if this is a - * multipart/form-data or a multipart/mixed POST request, else returns nil and an error. - * Use this function instead of [Request.ParseMultipartForm] to - * process the request body as a stream. + * Scan implements [sql.Scanner] interface to scan the provided value + * into the current DateTime instance. */ - multipartReader(): (multipart.Reader) + scan(value: any): void } - interface Request { + /** + * GeoPoint defines a struct for storing geo coordinates as serialized json object + * (e.g. {lon:0,lat:0}). + * + * Note: using object notation and not a plain array to avoid the confusion + * as there doesn't seem to be a fixed standard for the coordinates order. + */ + interface GeoPoint { + lon: number + lat: number + } + interface GeoPoint { /** - * Write writes an HTTP/1.1 request, which is the header and body, in wire format. - * This method consults the following fields of the request: - * - * ``` - * Host - * URL - * Method (defaults to "GET") - * Header - * ContentLength - * TransferEncoding - * Body - * ``` - * - * If Body is present, Content-Length is <= 0 and [Request.TransferEncoding] - * hasn't been set to "identity", Write adds "Transfer-Encoding: - * chunked" to the header. Body is closed after it is sent. - * - * Header values for Host, Content-Length, Transfer-Encoding, - * and Trailer are not used; these are derived from other Request fields. - * If the Header does not contain a User-Agent value, Write uses - * "Go-http-client/1.1". + * String returns the string representation of the current GeoPoint instance. */ - write(w: io.Writer): void + string(): string } - interface Request { + interface GeoPoint { /** - * WriteProxy is like [Request.Write] but writes the request in the form - * expected by an HTTP proxy. In particular, [Request.WriteProxy] writes the - * initial Request-URI line of the request with an absolute URI, per - * section 5.3 of RFC 7230, including the scheme and host. - * In either case, WriteProxy also writes a Host header, using - * either r.Host or r.URL.Host. + * AsMap implements [core.mapExtractor] and returns a value suitable + * to be used in an API rule expression. */ - writeProxy(w: io.Writer): void + asMap(): _TygojaDict } - interface Request { + interface GeoPoint { /** - * BasicAuth returns the username and password provided in the request's - * Authorization header, if the request uses HTTP Basic Authentication. - * See RFC 2617, Section 2. + * Value implements the [driver.Valuer] interface. */ - basicAuth(): [string, string, boolean] + value(): any } - interface Request { + interface GeoPoint { /** - * SetBasicAuth sets the request's Authorization header to use HTTP - * Basic Authentication with the provided username and password. - * - * With HTTP Basic Authentication the provided username and password - * are not encrypted. It should generally only be used in an HTTPS - * request. + * Scan implements [sql.Scanner] interface to scan the provided value + * into the current GeoPoint instance. * - * The username may not contain a colon. Some protocols may impose - * additional requirements on pre-escaping the username and - * password. For instance, when used with OAuth2, both arguments must - * be URL encoded first with [url.QueryEscape]. + * The value argument could be nil (no-op), another GeoPoint instance, + * map or serialized json object with lat-lon props. */ - setBasicAuth(username: string, password: string): void + scan(value: any): void } - interface Request { + /** + * JSONArray defines a slice that is safe for json and db read/write. + */ + interface JSONArray extends Array{} + interface JSONArray { /** - * ParseForm populates r.Form and r.PostForm. - * - * For all requests, ParseForm parses the raw query from the URL and updates - * r.Form. - * - * For POST, PUT, and PATCH requests, it also reads the request body, parses it - * as a form and puts the results into both r.PostForm and r.Form. Request body - * parameters take precedence over URL query string values in r.Form. - * - * If the request Body's size has not already been limited by [MaxBytesReader], - * the size is capped at 10MB. - * - * For other HTTP methods, or when the Content-Type is not - * application/x-www-form-urlencoded, the request Body is not read, and - * r.PostForm is initialized to a non-nil, empty value. - * - * [Request.ParseMultipartForm] calls ParseForm automatically. - * ParseForm is idempotent. + * MarshalJSON implements the [json.Marshaler] interface. */ - parseForm(): void + marshalJSON(): string|Array } - interface Request { + interface JSONArray { /** - * ParseMultipartForm parses a request body as multipart/form-data. - * The whole request body is parsed and up to a total of maxMemory bytes of - * its file parts are stored in memory, with the remainder stored on - * disk in temporary files. - * ParseMultipartForm calls [Request.ParseForm] if necessary. - * If ParseForm returns an error, ParseMultipartForm returns it but also - * continues parsing the request body. - * After one call to ParseMultipartForm, subsequent calls have no effect. + * String returns the string representation of the current json array. */ - parseMultipartForm(maxMemory: number): void + string(): string } - interface Request { + interface JSONArray { /** - * FormValue returns the first value for the named component of the query. - * The precedence order: - * 1. application/x-www-form-urlencoded form body (POST, PUT, PATCH only) - * 2. query parameters (always) - * 3. multipart/form-data form body (always) - * - * FormValue calls [Request.ParseMultipartForm] and [Request.ParseForm] - * if necessary and ignores any errors returned by these functions. - * If key is not present, FormValue returns the empty string. - * To access multiple values of the same key, call ParseForm and - * then inspect [Request.Form] directly. + * Value implements the [driver.Valuer] interface. */ - formValue(key: string): string + value(): any } - interface Request { + interface JSONArray { /** - * PostFormValue returns the first value for the named component of the POST, - * PUT, or PATCH request body. URL query parameters are ignored. - * PostFormValue calls [Request.ParseMultipartForm] and [Request.ParseForm] if necessary and ignores - * any errors returned by these functions. - * If key is not present, PostFormValue returns the empty string. + * Scan implements [sql.Scanner] interface to scan the provided value + * into the current JSONArray[T] instance. */ - postFormValue(key: string): string + scan(value: any): void } - interface Request { + /** + * JSONMap defines a map that is safe for json and db read/write. + */ + interface JSONMap extends _TygojaDict{} + interface JSONMap { /** - * FormFile returns the first file for the provided form key. - * FormFile calls [Request.ParseMultipartForm] and [Request.ParseForm] if necessary. + * Get retrieves a single value from the current JSONMap[T]. + * + * This helper was added primarily to assist the goja integration since custom map types + * don't have direct access to the map keys (https://pkg.go.dev/github.com/dop251/goja#hdr-Maps_with_methods). */ - formFile(key: string): [multipart.File, (multipart.FileHeader)] + get(key: string): T } - interface Request { + interface JSONMap { /** - * PathValue returns the value for the named path wildcard in the [ServeMux] pattern - * that matched the request. - * It returns the empty string if the request was not matched against a pattern - * or there is no such wildcard in the pattern. + * Set sets a single value in the current JSONMap[T]. * - * The value is unescaped. For example, if the pattern "/b/{bucket}" matches - * the path "/b/a%2fb", PathValue("bucket") returns "a/b". + * This helper was added primarily to assist the goja integration since custom map types + * don't have direct access to the map keys (https://pkg.go.dev/github.com/dop251/goja#hdr-Maps_with_methods). */ - pathValue(name: string): string + set(key: string, value: T): void } - interface Request { + interface JSONMap { /** - * SetPathValue sets name to value, so that subsequent calls to r.PathValue(name) - * return value. - * It does not unescape value. + * MarshalJSON implements the [json.Marshaler] interface. */ - setPathValue(name: string, value: string): void - } - /** - * A Handler responds to an HTTP request. - * - * [Handler.ServeHTTP] should write reply headers and data to the [ResponseWriter] - * and then return. Returning signals that the request is finished; it - * is not valid to use the [ResponseWriter] or read from the - * [Request.Body] after or concurrently with the completion of the - * ServeHTTP call. - * - * Depending on the HTTP client software, HTTP protocol version, and - * any intermediaries between the client and the Go server, it may not - * be possible to read from the [Request.Body] after writing to the - * [ResponseWriter]. Cautious handlers should read the [Request.Body] - * first, and then reply. - * - * Except for reading the body, handlers should not modify the - * provided Request. - * - * If ServeHTTP panics, the server (the caller of ServeHTTP) assumes - * that the effect of the panic was isolated to the active request. - * It recovers the panic, logs a stack trace to the server error log, - * and either closes the network connection or sends an HTTP/2 - * RST_STREAM, depending on the HTTP protocol. To abort a handler so - * the client sees an interrupted response but the server doesn't log - * an error, panic with the value [ErrAbortHandler]. - */ - interface Handler { - [key:string]: any; - serveHTTP(_arg0: ResponseWriter, _arg1: Request): void + marshalJSON(): string|Array } - /** - * A ResponseWriter interface is used by an HTTP handler to - * construct an HTTP response. - * - * A ResponseWriter may not be used after [Handler.ServeHTTP] has returned. - */ - interface ResponseWriter { - [key:string]: any; + interface JSONMap { /** - * Header returns the header map that will be sent by - * [ResponseWriter.WriteHeader]. The [Header] map also is the mechanism with which - * [Handler] implementations can set HTTP trailers. - * - * Changing the header map after a call to [ResponseWriter.WriteHeader] (or - * [ResponseWriter.Write]) has no effect unless the HTTP status code was of the - * 1xx class or the modified headers are trailers. - * - * There are two ways to set Trailers. The preferred way is to - * predeclare in the headers which trailers you will later - * send by setting the "Trailer" header to the names of the - * trailer keys which will come later. In this case, those - * keys of the Header map are treated as if they were - * trailers. See the example. The second way, for trailer - * keys not known to the [Handler] until after the first [ResponseWriter.Write], - * is to prefix the [Header] map keys with the [TrailerPrefix] - * constant value. - * - * To suppress automatic response headers (such as "Date"), set - * their value to nil. + * String returns the string representation of the current json map. */ - header(): Header + string(): string + } + interface JSONMap { /** - * Write writes the data to the connection as part of an HTTP reply. - * - * If [ResponseWriter.WriteHeader] has not yet been called, Write calls - * WriteHeader(http.StatusOK) before writing the data. If the Header - * does not contain a Content-Type line, Write adds a Content-Type set - * to the result of passing the initial 512 bytes of written data to - * [DetectContentType]. Additionally, if the total size of all written - * data is under a few KB and there are no Flush calls, the - * Content-Length header is added automatically. - * - * Depending on the HTTP protocol version and the client, calling - * Write or WriteHeader may prevent future reads on the - * Request.Body. For HTTP/1.x requests, handlers should read any - * needed request body data before writing the response. Once the - * headers have been flushed (due to either an explicit Flusher.Flush - * call or writing enough data to trigger a flush), the request body - * may be unavailable. For HTTP/2 requests, the Go HTTP server permits - * handlers to continue to read the request body while concurrently - * writing the response. However, such behavior may not be supported - * by all HTTP/2 clients. Handlers should read before writing if - * possible to maximize compatibility. + * Value implements the [driver.Valuer] interface. */ - write(_arg0: string|Array): number + value(): any + } + interface JSONMap { /** - * WriteHeader sends an HTTP response header with the provided - * status code. - * - * If WriteHeader is not called explicitly, the first call to Write - * will trigger an implicit WriteHeader(http.StatusOK). - * Thus explicit calls to WriteHeader are mainly used to - * send error codes or 1xx informational responses. - * - * The provided code must be a valid HTTP 1xx-5xx status code. - * Any number of 1xx headers may be written, followed by at most - * one 2xx-5xx header. 1xx headers are sent immediately, but 2xx-5xx - * headers may be buffered. Use the Flusher interface to send - * buffered data. The header map is cleared when 2xx-5xx headers are - * sent, but not with 1xx headers. - * - * The server will automatically send a 100 (Continue) header - * on the first read from the request body if the request has - * an "Expect: 100-continue" header. + * Scan implements [sql.Scanner] interface to scan the provided value + * into the current JSONMap[T] instance. */ - writeHeader(statusCode: number): void + scan(value: any): void } /** - * A Server defines parameters for running an HTTP server. - * The zero value for Server is a valid configuration. + * JSONRaw defines a json value type that is safe for db read/write. */ - interface Server { + interface JSONRaw extends Array{} + interface JSONRaw { /** - * Addr optionally specifies the TCP address for the server to listen on, - * in the form "host:port". If empty, ":http" (port 80) is used. - * The service names are defined in RFC 6335 and assigned by IANA. - * See net.Dial for details of the address format. + * String returns the current JSONRaw instance as a json encoded string. */ - addr: string - handler: Handler // handler to invoke, http.DefaultServeMux if nil + string(): string + } + interface JSONRaw { /** - * DisableGeneralOptionsHandler, if true, passes "OPTIONS *" requests to the Handler, - * otherwise responds with 200 OK and Content-Length: 0. + * MarshalJSON implements the [json.Marshaler] interface. */ - disableGeneralOptionsHandler: boolean + marshalJSON(): string|Array + } + interface JSONRaw { /** - * TLSConfig optionally provides a TLS configuration for use - * by ServeTLS and ListenAndServeTLS. Note that this value is - * cloned by ServeTLS and ListenAndServeTLS, so it's not - * possible to modify the configuration with methods like - * tls.Config.SetSessionTicketKeys. To use - * SetSessionTicketKeys, use Server.Serve with a TLS Listener - * instead. + * UnmarshalJSON implements the [json.Unmarshaler] interface. */ - tlsConfig?: any + unmarshalJSON(b: string|Array): void + } + interface JSONRaw { /** - * ReadTimeout is the maximum duration for reading the entire - * request, including the body. A zero or negative value means - * there will be no timeout. - * - * Because ReadTimeout does not let Handlers make per-request - * decisions on each request body's acceptable deadline or - * upload rate, most users will prefer to use - * ReadHeaderTimeout. It is valid to use them both. + * Value implements the [driver.Valuer] interface. */ - readTimeout: time.Duration + value(): any + } + interface JSONRaw { /** - * ReadHeaderTimeout is the amount of time allowed to read - * request headers. The connection's read deadline is reset - * after reading the headers and the Handler can decide what - * is considered too slow for the body. If zero, the value of - * ReadTimeout is used. If negative, or if zero and ReadTimeout - * is zero or negative, there is no timeout. + * Scan implements [sql.Scanner] interface to scan the provided value + * into the current JSONRaw instance. */ - readHeaderTimeout: time.Duration + scan(value: any): void + } +} + +/** + * Package sql provides a generic interface around SQL (or SQL-like) + * databases. + * + * The sql package must be used in conjunction with a database driver. + * See https://golang.org/s/sqldrivers for a list of drivers. + * + * Drivers that do not support context cancellation will not return until + * after the query is completed. + * + * For usage examples, see the wiki page at + * https://golang.org/s/sqlwiki. + */ +namespace sql { + /** + * TxOptions holds the transaction options to be used in [DB.BeginTx]. + */ + interface TxOptions { /** - * WriteTimeout is the maximum duration before timing out - * writes of the response. It is reset whenever a new - * request's header is read. Like ReadTimeout, it does not - * let Handlers make decisions on a per-request basis. - * A zero or negative value means there will be no timeout. + * Isolation is the transaction isolation level. + * If zero, the driver or database's default level is used. + */ + isolation: IsolationLevel + readOnly: boolean + } + /** + * NullString represents a string that may be null. + * NullString implements the [Scanner] interface so + * it can be used as a scan destination: + * + * ``` + * var s NullString + * err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&s) + * ... + * if s.Valid { + * // use s.String + * } else { + * // NULL value + * } + * ``` + */ + interface NullString { + string: string + valid: boolean // Valid is true if String is not NULL + } + interface NullString { + /** + * Scan implements the [Scanner] interface. */ - writeTimeout: time.Duration + scan(value: any): void + } + interface NullString { /** - * IdleTimeout is the maximum amount of time to wait for the - * next request when keep-alives are enabled. If zero, the value - * of ReadTimeout is used. If negative, or if zero and ReadTimeout - * is zero or negative, there is no timeout. + * Value implements the [driver.Valuer] interface. */ - idleTimeout: time.Duration + value(): any + } + /** + * DB is a database handle representing a pool of zero or more + * underlying connections. It's safe for concurrent use by multiple + * goroutines. + * + * The sql package creates and frees connections automatically; it + * also maintains a free pool of idle connections. If the database has + * a concept of per-connection state, such state can be reliably observed + * within a transaction ([Tx]) or connection ([Conn]). Once [DB.Begin] is called, the + * returned [Tx] is bound to a single connection. Once [Tx.Commit] or + * [Tx.Rollback] is called on the transaction, that transaction's + * connection is returned to [DB]'s idle connection pool. The pool size + * can be controlled with [DB.SetMaxIdleConns]. + */ + interface DB { + } + interface DB { /** - * MaxHeaderBytes controls the maximum number of bytes the - * server will read parsing the request header's keys and - * values, including the request line. It does not limit the - * size of the request body. - * If zero, DefaultMaxHeaderBytes is used. + * PingContext verifies a connection to the database is still alive, + * establishing a connection if necessary. */ - maxHeaderBytes: number + pingContext(ctx: context.Context): void + } + interface DB { /** - * MaxHeaderValueCount controls the maximum number of header - * values that the server is willing to parse from a request. - * If zero, DefaultMaxHeaderValueCount is used. - * Note that comma-separated values in a single header line are - * counted once, while values sent as multiple header lines are - * counted multiple times. + * Ping verifies a connection to the database is still alive, + * establishing a connection if necessary. + * + * Ping uses [context.Background] internally; to specify the context, use + * [DB.PingContext]. */ - maxHeaderValueCount: number + ping(): void + } + interface DB { /** - * TLSNextProto optionally specifies a function to take over - * ownership of the provided TLS connection when an ALPN - * protocol upgrade has occurred. The map key is the protocol - * name negotiated. The Handler argument should be used to - * handle HTTP requests and will initialize the Request's TLS - * and RemoteAddr if not already set. The connection is - * automatically closed when the function returns. - * If TLSNextProto is not nil, HTTP/2 support is not enabled - * automatically. + * Close closes the database and prevents new queries from starting. + * Close then waits for all queries that have started processing on the server + * to finish. * - * Historically, TLSNextProto was used to disable HTTP/2 support. - * The Server.Protocols field now provides a simpler way to do this. + * It is rare to Close a [DB], as the [DB] handle is meant to be + * long-lived and shared between many goroutines. */ - tlsNextProto: _TygojaDict + close(): void + } + interface DB { /** - * ConnState specifies an optional callback function that is - * called when a client connection changes state. See the - * ConnState type and associated constants for details. + * SetMaxIdleConns sets the maximum number of connections in the idle + * connection pool. + * + * If MaxOpenConns is greater than 0 but less than the new MaxIdleConns, + * then the new MaxIdleConns will be reduced to match the MaxOpenConns limit. + * + * If n <= 0, no idle connections are retained. + * + * The default max idle connections is currently 2. This may change in + * a future release. */ - connState: (_arg0: net.Conn, _arg1: ConnState) => void + setMaxIdleConns(n: number): void + } + interface DB { /** - * ErrorLog specifies an optional logger for errors accepting - * connections, unexpected behavior from handlers, and - * underlying FileSystem errors. - * If nil, logging is done via the log package's standard logger. + * SetMaxOpenConns sets the maximum number of open connections to the database. + * + * If MaxIdleConns is greater than 0 and the new MaxOpenConns is less than + * MaxIdleConns, then MaxIdleConns will be reduced to match the new + * MaxOpenConns limit. + * + * If n <= 0, then there is no limit on the number of open connections. + * The default is 0 (unlimited). */ - errorLog?: any + setMaxOpenConns(n: number): void + } + interface DB { /** - * BaseContext optionally specifies a function that returns - * the base context for incoming requests on this server. - * The provided Listener is the specific Listener that's - * about to start accepting requests. - * If BaseContext is nil, the default is context.Background(). - * If non-nil, it must return a non-nil context. + * SetConnMaxLifetime sets the maximum amount of time a connection may be reused. + * + * Expired connections may be closed lazily before reuse. + * + * If d <= 0, connections are not closed due to a connection's age. */ - baseContext: (_arg0: net.Listener) => context.Context + setConnMaxLifetime(d: time.Duration): void + } + interface DB { /** - * ConnContext optionally specifies a function that modifies - * the context used for a new connection c. The provided ctx - * is derived from the base context and has a ServerContextKey - * value. + * SetConnMaxIdleTime sets the maximum amount of time a connection may be idle. + * + * Expired connections may be closed lazily before reuse. + * + * If d <= 0, connections are not closed due to a connection's idle time. */ - connContext: (ctx: context.Context, c: net.Conn) => context.Context + setConnMaxIdleTime(d: time.Duration): void + } + interface DB { /** - * HTTP2 configures HTTP/2 connections. + * Stats returns database statistics. */ - http2?: HTTP2Config + stats(): DBStats + } + interface DB { /** - * Protocols is the set of protocols accepted by the server. - * - * If Protocols includes UnencryptedHTTP2, the server will accept - * unencrypted HTTP/2 connections. The server can serve both - * HTTP/1 and unencrypted HTTP/2 on the same address and port. + * PrepareContext creates a prepared statement for later queries or executions. + * Multiple queries or executions may be run concurrently from the + * returned statement. + * The caller must call the statement's [*Stmt.Close] method + * when the statement is no longer needed. * - * If Protocols is nil, the default is usually HTTP/1 and HTTP/2. - * If TLSNextProto is non-nil and does not contain an "h2" entry, - * the default is HTTP/1 only. + * The provided context is used for the preparation of the statement, not for the + * execution of the statement. */ - protocols?: Protocols + prepareContext(ctx: context.Context, query: string): (Stmt) + } + interface DB { /** - * DisableClientPriority specifies whether client-specified priority, as - * specified in RFC 9218, should be respected or not. - * - * This field only takes effect if using HTTP/2, and if no custom write - * scheduler is defined for the HTTP/2 server. Otherwise, this field is a - * no-op. + * Prepare creates a prepared statement for later queries or executions. + * Multiple queries or executions may be run concurrently from the + * returned statement. + * The caller must call the statement's [*Stmt.Close] method + * when the statement is no longer needed. * - * If set to true, requests will be served in a round-robin manner, without - * prioritization. + * Prepare uses [context.Background] internally; to specify the context, use + * [DB.PrepareContext]. */ - disableClientPriority: boolean + prepare(query: string): (Stmt) } - interface Server { + interface DB { /** - * Close immediately closes all active net.Listeners and any - * connections in state [StateNew], [StateActive], or [StateIdle]. For a - * graceful shutdown, use [Server.Shutdown]. - * - * Close does not attempt to close (and does not even know about) - * any hijacked connections, such as WebSockets. - * - * Close returns any error returned from closing the [Server]'s - * underlying Listener(s). + * ExecContext executes a query without returning any rows. + * The args are for any placeholder parameters in the query. */ - close(): void + execContext(ctx: context.Context, query: string, ...args: any[]): Result } - interface Server { + interface DB { /** - * Shutdown gracefully shuts down the server without interrupting any - * active connections. Shutdown works by first closing all open - * listeners, then closing all idle connections, and then waiting - * indefinitely for connections to return to idle and then shut down. - * If the provided context expires before the shutdown is complete, - * Shutdown returns the context's error, otherwise it returns any - * error returned from closing the [Server]'s underlying Listener(s). - * - * When Shutdown is called, [Serve], [ServeTLS], [ListenAndServe], and - * [ListenAndServeTLS] immediately return [ErrServerClosed]. Make sure the - * program doesn't exit and waits instead for Shutdown to return. - * - * Shutdown does not attempt to close nor wait for hijacked - * connections such as WebSockets. The caller of Shutdown should - * separately notify such long-lived connections of shutdown and wait - * for them to close, if desired. See [Server.RegisterOnShutdown] for a way to - * register shutdown notification functions. + * Exec executes a query without returning any rows. + * The args are for any placeholder parameters in the query. * - * Once Shutdown has been called on a server, it may not be reused; - * future calls to methods such as Serve will return ErrServerClosed. + * Exec uses [context.Background] internally; to specify the context, use + * [DB.ExecContext]. */ - shutdown(ctx: context.Context): void + exec(query: string, ...args: any[]): Result } - interface Server { + interface DB { /** - * RegisterOnShutdown registers a function to call on [Server.Shutdown]. - * This can be used to gracefully shutdown connections that have - * undergone ALPN protocol upgrade or that have been hijacked. - * This function should start protocol-specific graceful shutdown, - * but should not wait for shutdown to complete. + * QueryContext executes a query that returns rows, typically a SELECT. + * The args are for any placeholder parameters in the query. */ - registerOnShutdown(f: () => void): void + queryContext(ctx: context.Context, query: string, ...args: any[]): (Rows) } - interface Server { + interface DB { /** - * ListenAndServe listens on the TCP network address s.Addr and then - * calls [Serve] to handle requests on incoming connections. - * Accepted connections are configured to enable TCP keep-alives. + * Query executes a query that returns rows, typically a SELECT. + * The args are for any placeholder parameters in the query. * - * If s.Addr is blank, ":http" is used. + * Query uses [context.Background] internally; to specify the context, use + * [DB.QueryContext]. + */ + query(query: string, ...args: any[]): (Rows) + } + interface DB { + /** + * QueryRowContext executes a query that is expected to return at most one row. + * QueryRowContext always returns a non-nil value. Errors are deferred until + * [Row]'s Scan method is called. + * If the query selects no rows, the [*Row.Scan] will return [ErrNoRows]. + * Otherwise, [*Row.Scan] scans the first selected row and discards + * the rest. + */ + queryRowContext(ctx: context.Context, query: string, ...args: any[]): (Row) + } + interface DB { + /** + * QueryRow executes a query that is expected to return at most one row. + * QueryRow always returns a non-nil value. Errors are deferred until + * [Row]'s Scan method is called. + * If the query selects no rows, the [*Row.Scan] will return [ErrNoRows]. + * Otherwise, [*Row.Scan] scans the first selected row and discards + * the rest. * - * ListenAndServe always returns a non-nil error. After [Server.Shutdown] or [Server.Close], - * the returned error is [ErrServerClosed]. + * QueryRow uses [context.Background] internally; to specify the context, use + * [DB.QueryRowContext]. */ - listenAndServe(): void + queryRow(query: string, ...args: any[]): (Row) } - interface Server { + interface DB { /** - * Serve accepts incoming connections on the Listener l, creating a - * new service goroutine for each. The service goroutines read requests and - * then call s.Handler to reply to them. + * BeginTx starts a transaction. * - * HTTP/2 support is only enabled if the Listener returns [*tls.Conn] - * connections and they were configured with "h2" in the TLS - * Config.NextProtos. + * The provided context is used until the transaction is committed or rolled back. + * If the context is canceled, the sql package will roll back + * the transaction. [Tx.Commit] will return an error if the context provided to + * BeginTx is canceled. * - * Serve always returns a non-nil error and closes l. - * After [Server.Shutdown] or [Server.Close], the returned error is [ErrServerClosed]. + * The provided [TxOptions] is optional and may be nil if defaults should be used. + * If a non-default isolation level is used that the driver doesn't support, + * an error will be returned. */ - serve(l: net.Listener): void + beginTx(ctx: context.Context, opts: TxOptions): (Tx) } - interface Server { + interface DB { /** - * ServeTLS accepts incoming connections on the Listener l, creating a - * new service goroutine for each. The service goroutines perform TLS - * setup and then read requests, calling s.Handler to reply to them. - * - * Files containing a certificate and matching private key for the - * server must be provided if neither the [Server]'s - * TLSConfig.Certificates, TLSConfig.GetCertificate nor - * config.GetConfigForClient are populated. - * If the certificate is signed by a certificate authority, the - * certFile should be the concatenation of the server's certificate, - * any intermediates, and the CA's certificate. + * Begin starts a transaction. The default isolation level is dependent on + * the driver. * - * ServeTLS always returns a non-nil error. After [Server.Shutdown] or [Server.Close], the - * returned error is [ErrServerClosed]. + * Begin uses [context.Background] internally; to specify the context, use + * [DB.BeginTx]. */ - serveTLS(l: net.Listener, certFile: string, keyFile: string): void + begin(): (Tx) } - interface Server { + interface DB { /** - * SetKeepAlivesEnabled controls whether HTTP keep-alives are enabled. - * By default, keep-alives are always enabled. Only very - * resource-constrained environments or servers in the process of - * shutting down should disable them. + * Driver returns the database's underlying driver. */ - setKeepAlivesEnabled(v: boolean): void + driver(): any } - interface Server { + interface DB { /** - * ListenAndServeTLS listens on the TCP network address s.Addr and - * then calls [ServeTLS] to handle requests on incoming TLS connections. - * Accepted connections are configured to enable TCP keep-alives. - * - * Filenames containing a certificate and matching private key for the - * server must be provided if neither the [Server]'s TLSConfig.Certificates - * nor TLSConfig.GetCertificate are populated. If the certificate is - * signed by a certificate authority, the certFile should be the - * concatenation of the server's certificate, any intermediates, and - * the CA's certificate. - * - * If s.Addr is blank, ":https" is used. + * Conn returns a single connection by either opening a new connection + * or returning an existing connection from the connection pool. Conn will + * block until either a connection is returned or ctx is canceled. + * Queries run on the same Conn will be run in the same database session. * - * ListenAndServeTLS always returns a non-nil error. After [Server.Shutdown] or - * [Server.Close], the returned error is [ErrServerClosed]. + * Every Conn must be returned to the database pool after use by + * calling [Conn.Close]. */ - listenAndServeTLS(certFile: string, keyFile: string): void + conn(ctx: context.Context): (Conn) } -} - -/** - * Package blob defines a lightweight abstration for interacting with - * various storage services (local filesystem, S3, etc.). - * - * NB! - * For compatibility with earlier PocketBase versions and to prevent - * unnecessary breaking changes, this package is based and implemented - * as a minimal, stripped down version of the previously used gocloud.dev/blob. - * While there is no promise that it won't diverge in the future to accommodate - * better some PocketBase specific use cases, currently it copies and - * tries to follow as close as possible the same implementations, - * conventions and rules for the key escaping/unescaping, blob read/write - * interfaces and struct options as gocloud.dev/blob, therefore the - * credits goes to the original Go Cloud Development Kit Authors. - */ -namespace blob { /** - * ListObject represents a single blob returned from List. + * Tx is an in-progress database transaction. + * + * A transaction must end with a call to [Tx.Commit] or [Tx.Rollback]. + * + * After a call to [Tx.Commit] or [Tx.Rollback], all operations on the + * transaction fail with [ErrTxDone]. + * + * The statements prepared for a transaction by calling + * the transaction's [Tx.Prepare] or [Tx.Stmt] methods are closed + * by the call to [Tx.Commit] or [Tx.Rollback]. */ - interface ListObject { - /** - * Key is the key for this blob. - */ - key: string + interface Tx { + } + interface Tx { /** - * ModTime is the time the blob was last modified. + * Commit commits the transaction. */ - modTime: time.Time + commit(): void + } + interface Tx { /** - * Size is the size of the blob's content in bytes. + * Rollback aborts the transaction. */ - size: number + rollback(): void + } + interface Tx { /** - * MD5 is an MD5 hash of the blob contents or nil if not available. + * PrepareContext creates a prepared statement for use within a transaction. + * + * The returned statement operates within the transaction and will be closed + * when the transaction has been committed or rolled back. + * + * To use an existing prepared statement on this transaction, see [Tx.Stmt]. + * + * The provided context will be used for the preparation of the context, not + * for the execution of the returned statement. The returned statement + * will run in the transaction context. */ - md5: string|Array + prepareContext(ctx: context.Context, query: string): (Stmt) + } + interface Tx { /** - * IsDir indicates that this result represents a "directory" in the - * hierarchical namespace, ending in ListOptions.Delimiter. Key can be - * passed as ListOptions.Prefix to list items in the "directory". - * Fields other than Key and IsDir will not be set if IsDir is true. + * Prepare creates a prepared statement for use within a transaction. + * + * The returned statement operates within the transaction and will be closed + * when the transaction has been committed or rolled back. + * + * To use an existing prepared statement on this transaction, see [Tx.Stmt]. + * + * Prepare uses [context.Background] internally; to specify the context, use + * [Tx.PrepareContext]. */ - isDir: boolean + prepare(query: string): (Stmt) } - /** - * Attributes contains attributes about a blob. - */ - interface Attributes { + interface Tx { /** - * CacheControl specifies caching attributes that services may use - * when serving the blob. - * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control + * StmtContext returns a transaction-specific prepared statement from + * an existing statement. + * + * Example: + * + * ``` + * updateMoney, err := db.Prepare("UPDATE balance SET money=money+? WHERE id=?") + * ... + * tx, err := db.Begin() + * ... + * res, err := tx.StmtContext(ctx, updateMoney).Exec(123.45, 98293203) + * ``` + * + * The provided context is used for the preparation of the statement, not for the + * execution of the statement. + * + * The returned statement operates within the transaction and will be closed + * when the transaction has been committed or rolled back. */ - cacheControl: string + stmtContext(ctx: context.Context, stmt: Stmt): (Stmt) + } + interface Tx { /** - * ContentDisposition specifies whether the blob content is expected to be - * displayed inline or as an attachment. - * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition + * Stmt returns a transaction-specific prepared statement from + * an existing statement. + * + * Example: + * + * ``` + * updateMoney, err := db.Prepare("UPDATE balance SET money=money+? WHERE id=?") + * ... + * tx, err := db.Begin() + * ... + * res, err := tx.Stmt(updateMoney).Exec(123.45, 98293203) + * ``` + * + * The returned statement operates within the transaction and will be closed + * when the transaction has been committed or rolled back. + * + * Stmt uses [context.Background] internally; to specify the context, use + * [Tx.StmtContext]. */ - contentDisposition: string + stmt(stmt: Stmt): (Stmt) + } + interface Tx { /** - * ContentEncoding specifies the encoding used for the blob's content, if any. - * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding + * ExecContext executes a query that doesn't return rows. + * For example: an INSERT and UPDATE. */ - contentEncoding: string + execContext(ctx: context.Context, query: string, ...args: any[]): Result + } + interface Tx { /** - * ContentLanguage specifies the language used in the blob's content, if any. - * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Language + * Exec executes a query that doesn't return rows. + * For example: an INSERT and UPDATE. + * + * Exec uses [context.Background] internally; to specify the context, use + * [Tx.ExecContext]. */ - contentLanguage: string + exec(query: string, ...args: any[]): Result + } + interface Tx { /** - * ContentType is the MIME type of the blob. It will not be empty. - * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type + * QueryContext executes a query that returns rows, typically a SELECT. */ - contentType: string + queryContext(ctx: context.Context, query: string, ...args: any[]): (Rows) + } + interface Tx { /** - * Metadata holds key/value pairs associated with the blob. - * Keys are guaranteed to be in lowercase, even if the backend service - * has case-sensitive keys (although note that Metadata written via - * this package will always be lowercased). If there are duplicate - * case-insensitive keys (e.g., "foo" and "FOO"), only one value - * will be kept, and it is undefined which one. + * Query executes a query that returns rows, typically a SELECT. + * + * Query uses [context.Background] internally; to specify the context, use + * [Tx.QueryContext]. */ - metadata: _TygojaDict + query(query: string, ...args: any[]): (Rows) + } + interface Tx { /** - * CreateTime is the time the blob was created, if available. If not available, - * CreateTime will be the zero time. + * QueryRowContext executes a query that is expected to return at most one row. + * QueryRowContext always returns a non-nil value. Errors are deferred until + * [Row]'s Scan method is called. + * If the query selects no rows, the [*Row.Scan] will return [ErrNoRows]. + * Otherwise, the [*Row.Scan] scans the first selected row and discards + * the rest. */ - createTime: time.Time + queryRowContext(ctx: context.Context, query: string, ...args: any[]): (Row) + } + interface Tx { /** - * ModTime is the time the blob was last modified. + * QueryRow executes a query that is expected to return at most one row. + * QueryRow always returns a non-nil value. Errors are deferred until + * [Row]'s Scan method is called. + * If the query selects no rows, the [*Row.Scan] will return [ErrNoRows]. + * Otherwise, the [*Row.Scan] scans the first selected row and discards + * the rest. + * + * QueryRow uses [context.Background] internally; to specify the context, use + * [Tx.QueryRowContext]. */ - modTime: time.Time + queryRow(query: string, ...args: any[]): (Row) + } + /** + * Stmt is a prepared statement. + * A Stmt is safe for concurrent use by multiple goroutines. + * + * If a Stmt is prepared on a [Tx] or [Conn], it will be bound to a single + * underlying connection forever. If the [Tx] or [Conn] closes, the Stmt will + * become unusable and all operations will return an error. + * If a Stmt is prepared on a [DB], it will remain usable for the lifetime of the + * [DB]. When the Stmt needs to execute on a new underlying connection, it will + * prepare itself on the new connection automatically. + */ + interface Stmt { + } + interface Stmt { /** - * Size is the size of the blob's content in bytes. + * ExecContext executes a prepared statement with the given arguments and + * returns a [Result] summarizing the effect of the statement. */ - size: number + execContext(ctx: context.Context, ...args: any[]): Result + } + interface Stmt { /** - * MD5 is an MD5 hash of the blob contents or nil if not available. + * Exec executes a prepared statement with the given arguments and + * returns a [Result] summarizing the effect of the statement. + * + * Exec uses [context.Background] internally; to specify the context, use + * [Stmt.ExecContext]. */ - md5: string|Array + exec(...args: any[]): Result + } + interface Stmt { /** - * ETag for the blob; see https://en.wikipedia.org/wiki/HTTP_ETag. + * QueryContext executes a prepared query statement with the given arguments + * and returns the query results as a [*Rows]. */ - eTag: string + queryContext(ctx: context.Context, ...args: any[]): (Rows) } - /** - * WriterOptions sets options for NewWriter. - */ - interface WriterOptions { + interface Stmt { /** - * BufferSize changes the default size in bytes of the chunks that - * Writer will upload in a single request; larger blobs will be split into - * multiple requests. - * - * This option may be ignored by some drivers. - * - * If 0, the driver will choose a reasonable default. + * Query executes a prepared query statement with the given arguments + * and returns the query results as a *Rows. * - * If the Writer is used to do many small writes concurrently, using a - * smaller BufferSize may reduce memory usage. + * Query uses [context.Background] internally; to specify the context, use + * [Stmt.QueryContext]. */ - bufferSize: number + query(...args: any[]): (Rows) + } + interface Stmt { /** - * MaxConcurrency changes the default concurrency for parts of an upload. + * QueryRowContext executes a prepared query statement with the given arguments. + * If an error occurs during the execution of the statement, that error will + * be returned by a call to Scan on the returned [*Row], which is always non-nil. + * If the query selects no rows, the [*Row.Scan] will return [ErrNoRows]. + * Otherwise, the [*Row.Scan] scans the first selected row and discards + * the rest. + */ + queryRowContext(ctx: context.Context, ...args: any[]): (Row) + } + interface Stmt { + /** + * QueryRow executes a prepared query statement with the given arguments. + * If an error occurs during the execution of the statement, that error will + * be returned by a call to Scan on the returned [*Row], which is always non-nil. + * If the query selects no rows, the [*Row.Scan] will return [ErrNoRows]. + * Otherwise, the [*Row.Scan] scans the first selected row and discards + * the rest. * - * This option may be ignored by some drivers. + * Example usage: * - * If 0, the driver will choose a reasonable default. + * ``` + * var name string + * err := nameByUseridStmt.QueryRow(id).Scan(&name) + * ``` + * + * QueryRow uses [context.Background] internally; to specify the context, use + * [Stmt.QueryRowContext]. */ - maxConcurrency: number + queryRow(...args: any[]): (Row) + } + interface Stmt { /** - * CacheControl specifies caching attributes that services may use - * when serving the blob. - * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control + * Close closes the statement. */ - cacheControl: string + close(): void + } + /** + * Rows is the result of a query. Its cursor starts before the first row + * of the result set. Use [Rows.Next] to advance from row to row. + */ + interface Rows { + } + interface Rows { /** - * ContentDisposition specifies whether the blob content is expected to be - * displayed inline or as an attachment. - * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition + * Next prepares the next result row for reading with the [Rows.Scan] method. It + * returns true on success, or false if there is no next result row or an error + * happened while preparing it. [Rows.Err] should be consulted to distinguish between + * the two cases. + * + * Every call to [Rows.Scan], even the first one, must be preceded by a call to [Rows.Next]. */ - contentDisposition: string + next(): boolean + } + interface Rows { /** - * ContentEncoding specifies the encoding used for the blob's content, if any. - * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding + * NextResultSet prepares the next result set for reading. It reports whether + * there is further result sets, or false if there is no further result set + * or if there is an error advancing to it. The [Rows.Err] method should be consulted + * to distinguish between the two cases. + * + * After calling NextResultSet, the [Rows.Next] method should always be called before + * scanning. If there are further result sets they may not have rows in the result + * set. */ - contentEncoding: string + nextResultSet(): boolean + } + interface Rows { /** - * ContentLanguage specifies the language used in the blob's content, if any. - * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Language + * Err returns the error, if any, that was encountered during iteration. + * Err may be called after an explicit or implicit [Rows.Close]. */ - contentLanguage: string + err(): void + } + interface Rows { /** - * ContentType specifies the MIME type of the blob being written. If not set, - * it will be inferred from the content using the algorithm described at - * http://mimesniff.spec.whatwg.org/. - * Set DisableContentTypeDetection to true to disable the above and force - * the ContentType to stay empty. - * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type + * Columns returns the column names. + * Columns returns an error if the rows are closed. */ - contentType: string + columns(): Array + } + interface Rows { /** - * When true, if ContentType is the empty string, it will stay the empty - * string rather than being inferred from the content. - * Note that while the blob will be written with an empty string ContentType, - * most providers will fill one in during reads, so don't expect an empty - * ContentType if you read the blob back. + * ColumnTypes returns column information such as column type, length, + * and nullable. Some information may not be available from some drivers. */ - disableContentTypeDetection: boolean + columnTypes(): Array<(ColumnType | undefined)> + } + interface Rows { /** - * ContentMD5 is used as a message integrity check. - * If len(ContentMD5) > 0, the MD5 hash of the bytes written must match - * ContentMD5, or Close will return an error without completing the write. - * https://tools.ietf.org/html/rfc1864 + * Scan copies the columns in the current row into the values pointed + * at by dest. The number of values in dest must be the same as the + * number of columns in [Rows]. + * + * Scan converts columns read from the database into the following + * common Go types and special types provided by the sql package: + * + * ``` + * *string + * *[]byte + * *int, *int8, *int16, *int32, *int64 + * *uint, *uint8, *uint16, *uint32, *uint64 + * *bool + * *float32, *float64 + * *interface{} + * *RawBytes + * *Rows (cursor value) + * any type implementing Scanner (see Scanner docs) + * ``` + * + * In the most simple case, if the type of the value from the source + * column is an integer, bool or string type T and dest is of type *T, + * Scan simply assigns the value through the pointer. + * + * Scan also converts between string and numeric types, as long as no + * information would be lost. While Scan stringifies all numbers + * scanned from numeric database columns into *string, scans into + * numeric types are checked for overflow. For example, a float64 with + * value 300 or a string with value "300" can scan into a uint16, but + * not into a uint8, though float64(255) or "255" can scan into a + * uint8. One exception is that scans of some float64 numbers to + * strings may lose information when stringifying. In general, scan + * floating point columns into *float64. + * + * If a dest argument has type *[]byte, Scan saves in that argument a + * copy of the corresponding data. The copy is owned by the caller and + * can be modified and held indefinitely. The copy can be avoided by + * using an argument of type [*RawBytes] instead; see the documentation + * for [RawBytes] for restrictions on its use. + * + * If an argument has type *interface{}, Scan copies the value + * provided by the underlying driver without conversion. When scanning + * from a source value of type []byte to *interface{}, a copy of the + * slice is made and the caller owns the result. + * + * Source values of type [time.Time] may be scanned into values of type + * *time.Time, *interface{}, *string, or *[]byte. When converting to + * the latter two, [time.RFC3339Nano] is used. + * + * Source values of type bool may be scanned into types *bool, + * *interface{}, *string, *[]byte, or [*RawBytes]. + * + * For scanning into *bool, the source may be true, false, 1, 0, or + * string inputs parseable by [strconv.ParseBool]. + * + * Scan can also convert a cursor returned from a query, such as + * "select cursor(select * from my_table) from dual", into a + * [*Rows] value that can itself be scanned from. The parent + * select query will close any cursor [*Rows] if the parent [*Rows] is closed. + * + * If any of the first arguments implementing [Scanner] returns an error, + * that error will be wrapped in the returned error. */ - contentMD5: string|Array + scan(...dest: any[]): void + } + interface Rows { /** - * Metadata holds key/value strings to be associated with the blob, or nil. - * Keys may not be empty, and are lowercased before being written. - * Duplicate case-insensitive keys (e.g., "foo" and "FOO") will result in - * an error. + * Close closes the [Rows], preventing further enumeration. If [Rows.Next] is called + * and returns false and there are no further result sets, + * the [Rows] are closed automatically and it will suffice to check the + * result of [Rows.Err]. Close is idempotent and does not affect the result of [Rows.Err]. */ - metadata: _TygojaDict + close(): void } /** - * Reader reads bytes from a blob. - * It implements io.ReadSeekCloser, and must be closed after reads are finished. + * A Result summarizes an executed SQL command. */ - interface Reader { - } - interface Reader { + interface Result { + [key:string]: any; /** - * Read implements io.Reader (https://golang.org/pkg/io/#Reader). + * LastInsertId returns the integer generated by the database + * in response to a command. Typically this will be from an + * "auto increment" column when inserting a new row. Not all + * databases support this feature, and the syntax of such + * statements varies. */ - read(p: string|Array): number - } - interface Reader { + lastInsertId(): number /** - * Seek implements io.Seeker (https://golang.org/pkg/io/#Seeker). + * RowsAffected returns the number of rows affected by an + * update, insert, or delete. Not every database or database + * driver may support this. */ - seek(offset: number, whence: number): number + rowsAffected(): number } - interface Reader { +} + +namespace exec { + /** + * Cmd represents an external command being prepared or run. + * + * A Cmd cannot be reused after calling its [Cmd.Start], [Cmd.Run], + * [Cmd.Output], or [Cmd.CombinedOutput] methods. + */ + interface Cmd { /** - * Close implements io.Closer (https://golang.org/pkg/io/#Closer). + * Path is the path of the command to run. + * + * This is the only field that must be set to a non-zero + * value. If Path is relative, it is evaluated relative + * to Dir. */ - close(): void - } - interface Reader { + path: string /** - * ContentType returns the MIME type of the blob. + * Args holds command line arguments, including the command as Args[0]. + * If the Args field is empty or nil, Run uses {Path}. + * + * In typical use, both Path and Args are set by calling Command. */ - contentType(): string - } - interface Reader { + args: Array /** - * ModTime returns the time the blob was last modified. + * Env specifies the environment of the process. + * Each entry is of the form "key=value". + * If Env is nil, the new process uses the current process's + * environment. + * If Env contains duplicate environment keys, only the last + * value in the slice for each duplicate key is used. + * As a special case on Windows, SYSTEMROOT is always added if + * missing and not explicitly set to the empty string. + * + * See also the Dir field, which may set PWD in the environment. */ - modTime(): time.Time - } - interface Reader { + env: Array /** - * Size returns the size of the blob content in bytes. + * Dir specifies the working directory of the command. + * If Dir is the empty string, Run runs the command in the + * calling process's current directory. + * + * On Unix systems, the value of Dir also determines the + * child process's PWD environment variable if not otherwise + * specified. A Unix process represents its working directory + * not by name but as an implicit reference to a node in the + * file tree. So, if the child process obtains its working + * directory by calling a function such as C's getcwd, which + * computes the canonical name by walking up the file tree, it + * will not recover the original value of Dir if that value + * was an alias involving symbolic links. However, if the + * child process calls Go's [os.Getwd] or GNU C's + * get_current_dir_name, and the value of PWD is an alias for + * the current directory, those functions will return the + * value of PWD, which matches the value of Dir. */ - size(): number - } - interface Reader { + dir: string /** - * WriteTo reads from r and writes to w until there's no more data or - * an error occurs. - * The return value is the number of bytes written to w. + * Stdin specifies the process's standard input. * - * It implements the io.WriterTo interface. + * If Stdin is nil, the process reads from the null device (os.DevNull). + * + * If Stdin is an *os.File, the process's standard input is connected + * directly to that file. + * + * Otherwise, during the execution of the command a separate + * goroutine reads from Stdin and delivers that data to the command + * over a pipe. In this case, Wait does not complete until the goroutine + * stops copying, either because it has reached the end of Stdin + * (EOF or a read error), or because writing to the pipe returned an error, + * or because a nonzero WaitDelay was set and expired. + * + * Regardless of WaitDelay, Wait can block until a Read from + * Stdin completes. If you need to use a blocking io.Reader, + * use the StdinPipe method to get a pipe, copy from the Reader + * to the pipe, and arrange to close the Reader after Wait returns. */ - writeTo(w: io.Writer): number - } - /** - * Writer writes bytes to a blob. - * - * It implements io.WriteCloser (https://golang.org/pkg/io/#Closer), and must be - * closed after all writes are done. - */ - interface Writer { - } - interface Writer { + stdin: io.Reader /** - * Write implements the io.Writer interface (https://golang.org/pkg/io/#Writer). + * Stdout and Stderr specify the process's standard output and error. * - * Writes may happen asynchronously, so the returned error can be nil - * even if the actual write eventually fails. The write is only guaranteed to - * have succeeded if Close returns no error. + * If either is nil, Run connects the corresponding file descriptor + * to the null device (os.DevNull). + * + * If either is an *os.File, the corresponding output from the process + * is connected directly to that file. + * + * Otherwise, during the execution of the command a separate goroutine + * reads from the process over a pipe and delivers that data to the + * corresponding Writer. In this case, Wait does not complete until the + * goroutine reaches EOF or encounters an error or a nonzero WaitDelay + * expires. + * + * Regardless of WaitDelay, Wait can block until a Write to + * Stdout or Stderr completes. If you need to use a blocking io.Writer, + * use the StdoutPipe or StderrPipe method to get a pipe, + * copy from the pipe to the Writer, and arrange to close the + * Writer after Wait returns. + * + * If Stdout and Stderr are the same writer, and have a type that can + * be compared with ==, at most one goroutine at a time will call Write. */ - write(p: string|Array): number - } - interface Writer { + stdout: io.Writer + stderr: io.Writer /** - * Close closes the blob writer. The write operation is not guaranteed - * to have succeeded until Close returns with no error. + * ExtraFiles specifies additional open files to be inherited by the + * new process. It does not include standard input, standard output, or + * standard error. If non-nil, entry i becomes file descriptor 3+i. * - * Close may return an error if the context provided to create the - * Writer is canceled or reaches its deadline. + * ExtraFiles is not supported on Windows. */ - close(): void - } - interface Writer { + extraFiles: Array<(os.File | undefined)> /** - * ReadFrom reads from r and writes to w until EOF or error. - * The return value is the number of bytes read from r. - * - * It implements the io.ReaderFrom interface. + * SysProcAttr holds optional, operating system-specific attributes. + * Run passes it to os.StartProcess as the os.ProcAttr's Sys field. */ - readFrom(r: io.Reader): number - } -} - -namespace hook { - /** - * Event implements [Resolver] and it is intended to be used as a base - * Hook event that you can embed in your custom typed event structs. - * - * Example: - * - * ``` - * type CustomEvent struct { - * hook.Event - * - * SomeField int - * } - * ``` - */ - interface Event { - } - interface Event { + sysProcAttr?: syscall.SysProcAttr /** - * Next calls the next hook handler. + * Process is the underlying process, once started. */ - next(): void - } - /** - * Handler defines a single Hook handler. - * Multiple handlers can share the same id. - * If Id is not explicitly set it will be autogenerated by Hook.Add and Hook.AddHandler. - */ - interface Handler { + process?: os.Process /** - * Func defines the handler function to execute. + * ProcessState contains information about an exited process. + * If the process was started successfully, Wait or Run will + * populate its ProcessState when the command completes. + */ + processState?: os.ProcessState + err: Error // LookPath error, if any. + /** + * If Cancel is non-nil, the command must have been created with + * CommandContext and Cancel will be called when the command's + * Context is done. By default, CommandContext sets Cancel to + * call the Kill method on the command's Process. * - * Note that users need to call e.Next() in order to proceed with - * the execution of the hook chain. + * Typically a custom Cancel will send a signal to the command's + * Process, but it may instead take other actions to initiate cancellation, + * such as closing a stdin or stdout pipe or sending a shutdown request on a + * network socket. + * + * If the command exits with a success status after Cancel is + * called, and Cancel does not return an error equivalent to + * os.ErrProcessDone, then Wait and similar methods will return a non-nil + * error: either an error wrapping the one returned by Cancel, + * or the error from the Context. + * (If the command exits with a non-success status, or Cancel + * returns an error that wraps os.ErrProcessDone, Wait and similar methods + * continue to return the command's usual exit status.) + * + * If Cancel is set to nil, nothing will happen immediately when the command's + * Context is done, but a nonzero WaitDelay will still take effect. That may + * be useful, for example, to work around deadlocks in commands that do not + * support shutdown signals but are expected to always finish quickly. + * + * Cancel will not be called if Start returns a non-nil error. */ - func: (_arg0: T) => void + cancel: () => void /** - * Id is the unique identifier of the handler. + * If WaitDelay is non-zero, it bounds the time spent waiting on two sources + * of unexpected delay in Wait: a child process that fails to exit after the + * associated Context is canceled, and a child process that exits but leaves + * its I/O pipes unclosed. * - * It could be used later to remove the handler from a hook via [Hook.Remove]. + * The WaitDelay timer starts when either the associated Context is done or a + * call to Wait observes that the child process has exited, whichever occurs + * first. When the delay has elapsed, the command shuts down the child process + * and/or its I/O pipes. * - * If missing, an autogenerated value will be assigned when adding - * the handler to a hook. - */ - id: string - /** - * Priority allows changing the default exec priority of the handler within a hook. + * If the child process has failed to exit — perhaps because it ignored or + * failed to receive a shutdown signal from a Cancel function, or because no + * Cancel function was set — then it will be terminated using os.Process.Kill. * - * If 0, the handler will be executed in the same order it was registered. + * Then, if the I/O pipes communicating with the child process are still open, + * those pipes are closed in order to unblock any goroutines currently blocked + * on Read or Write calls. + * + * If pipes are closed due to WaitDelay, no Cancel call has occurred, + * and the command has otherwise exited with a successful status, Wait and + * similar methods will return ErrWaitDelay instead of nil. + * + * If WaitDelay is zero (the default), I/O pipes will be read until EOF, + * which might not occur until orphaned subprocesses of the command have + * also closed their descriptors for the pipes. */ - priority: number + waitDelay: time.Duration } - /** - * Hook defines a generic concurrent safe structure for managing event hooks. - * - * When using custom event it must embed the base [hook.Event]. - * - * Example: - * - * ``` - * type CustomEvent struct { - * hook.Event - * SomeField int - * } - * - * h := Hook[*CustomEvent]{} - * - * h.BindFunc(func(e *CustomEvent) error { - * println(e.SomeField) - * - * return e.Next() - * }) - * - * h.Trigger(&CustomEvent{ SomeField: 123 }) - * ``` - */ - interface Hook { + interface Cmd { + /** + * String returns a human-readable description of c. + * It is intended only for debugging. + * In particular, it is not suitable for use as input to a shell. + * The output of String may vary across Go releases. + */ + string(): string } - interface Hook { + interface Cmd { /** - * Bind registers the provided handler to the current hooks queue. + * Run starts the specified command and waits for it to complete. * - * If handler.Id is empty it is updated with autogenerated value. + * The returned error is nil if the command runs, has no problems + * copying stdin, stdout, and stderr, and exits with a zero exit + * status. * - * If a handler from the current hook list has Id matching handler.Id - * then the old handler is replaced with the new one. + * If the command starts but does not complete successfully, the error is of + * type [*ExitError]. Other error types may be returned for other situations. + * + * If the calling goroutine has locked the operating system thread + * with [runtime.LockOSThread] and modified any inheritable OS-level + * thread state (for example, Linux or Plan 9 name spaces), the new + * process will inherit the caller's thread state. */ - bind(handler: Handler): string + run(): void } - interface Hook { + interface Cmd { /** - * BindFunc is similar to Bind but registers a new handler from just the provided function. + * Start starts the specified command but does not wait for it to complete. * - * The registered handler is added with a default 0 priority and the id will be autogenerated. + * If Start returns successfully, the c.Process field will be set. * - * If you want to register a handler with custom priority or id use the [Hook.Bind] method. + * After a successful call to Start the [Cmd.Wait] method must be called in + * order to release associated system resources. */ - bindFunc(fn: (e: T) => void): string + start(): void } - interface Hook { + interface Cmd { /** - * Unbind removes one or many hook handler by their id. + * Wait waits for the command to exit and waits for any copying to + * stdin or copying from stdout or stderr to complete. + * + * The command must have been started by [Cmd.Start]. + * + * The returned error is nil if the command runs, has no problems + * copying stdin, stdout, and stderr, and exits with a zero exit + * status. + * + * If the command fails to run or doesn't complete successfully, the + * error is of type [*ExitError]. Other error types may be + * returned for I/O problems. + * + * If any of c.Stdin, c.Stdout or c.Stderr are not an [*os.File], Wait also waits + * for the respective I/O loop copying to or from the process to complete. + * + * Wait must not be called concurrently from multiple goroutines. + * A custom Cmd.Cancel function should not call Wait. + * + * Wait releases any resources associated with the [Cmd]. */ - unbind(...idsToRemove: string[]): void + wait(): void } - interface Hook { + interface Cmd { /** - * UnbindAll removes all registered handlers. + * Output runs the command and returns its standard output. + * Any returned error will usually be of type [*ExitError]. + * If c.Stderr was nil and the returned error is of type + * [*ExitError], Output populates the Stderr field of the + * returned error. */ - unbindAll(): void + output(): string|Array } - interface Hook { + interface Cmd { /** - * Length returns to total number of registered hook handlers. + * CombinedOutput runs the command and returns its combined standard + * output and standard error. */ - length(): number + combinedOutput(): string|Array } - interface Hook { + interface Cmd { /** - * Trigger executes all registered hook handlers one by one - * with the specified event as an argument. - * - * Optionally, this method allows also to register additional one off - * handler funcs that will be temporary appended to the handlers queue. - * - * NB! Each hook handler must call event.Next() in order the hook chain to proceed. + * StdinPipe returns a pipe that will be connected to the command's + * standard input when the command starts. + * The pipe will be closed automatically after [Cmd.Wait] sees the command exit. + * A caller need only call Close to force the pipe to close sooner. + * For example, if the command being run will not exit until standard input + * is closed, the caller must close the pipe. */ - trigger(event: T, ...oneOffHandlerFuncs: ((_arg0: T) => void)[]): void - } - /** - * TaggedHook defines a proxy hook which register handlers that are triggered only - * if the TaggedHook.tags are empty or includes at least one of the event data tag(s). - */ - type _shlEWmu = mainHook - interface TaggedHook extends _shlEWmu { + stdinPipe(): io.WriteCloser } - interface TaggedHook { + interface Cmd { /** - * CanTriggerOn checks if the current TaggedHook can be triggered with - * the provided event data tags. + * StdoutPipe returns a pipe that will be connected to the command's + * standard output when the command starts. * - * It returns always true if the hook doesn't have any tags. + * [Cmd.Wait] will close the pipe after seeing the command exit, so most callers + * need not close the pipe themselves. It is thus incorrect to call Wait + * before all reads from the pipe have completed. + * For the same reason, it is incorrect to call [Cmd.Run] when using StdoutPipe. + * See the example for idiomatic usage. */ - canTriggerOn(tagsToCheck: Array): boolean + stdoutPipe(): io.ReadCloser } - interface TaggedHook { + interface Cmd { /** - * Bind registers the provided handler to the current hooks queue. + * StderrPipe returns a pipe that will be connected to the command's + * standard error when the command starts. * - * It is similar to [Hook.Bind] with the difference that the handler - * function is invoked only if the event data tags satisfy h.CanTriggerOn. + * [Cmd.Wait] will close the pipe after seeing the command exit, so most callers + * need not close the pipe themselves. It is thus incorrect to call Wait + * before all reads from the pipe have completed. + * For the same reason, it is incorrect to use [Cmd.Run] when using StderrPipe. + * See the StdoutPipe example for idiomatic usage. */ - bind(handler: Handler): string + stderrPipe(): io.ReadCloser } - interface TaggedHook { + interface Cmd { /** - * BindFunc registers a new handler with the specified function. - * - * It is similar to [Hook.Bind] with the difference that the handler - * function is invoked only if the event data tags satisfy h.CanTriggerOn. + * Environ returns a copy of the environment in which the command would be run + * as it is currently configured. */ - bindFunc(fn: (e: T) => void): string + environ(): Array } } -namespace router { - // @ts-ignore - import validation = ozzo_validation +namespace store { /** - * ApiError defines the struct for a basic api error response. + * Store defines a concurrent safe in memory key-value data store. */ - interface ApiError { - data: _TygojaDict - message: string - status: number - } - interface ApiError { - /** - * Error makes it compatible with the `error` interface. - */ - error(): string - } - interface ApiError { - /** - * RawData returns the unformatted error data (could be an internal error, text, etc.) - */ - rawData(): any + interface Store { } - interface ApiError { + interface Store { /** - * Is reports whether the current ApiError wraps the target. + * Reset clears the store and replaces the store data with a + * shallow copy of the provided newData. */ - is(target: Error): boolean - } - /** - * Event specifies based Route handler event that is usually intended - * to be embedded as part of a custom event struct. - * - * NB! It is expected that the Response and Request fields are always set. - */ - type _sQryJPL = hook.Event - interface Event extends _sQryJPL { - response: http.ResponseWriter - request?: http.Request + reset(newData: _TygojaDict): void } - interface Event { + interface Store { /** - * Written reports whether the current response has already been written. - * - * This method always returns false if e.ResponseWritter doesn't implement the WriteTracker interface - * (all router package handlers receives a ResponseWritter that implements it unless explicitly replaced with a custom one). + * Length returns the current number of elements in the store. */ - written(): boolean + length(): number } - interface Event { - /** - * Status reports the status code of the current response. - * - * This method always returns 0 if e.Response doesn't implement the StatusTracker interface - * (all router package handlers receives a ResponseWritter that implements it unless explicitly replaced with a custom one). + interface Store { + /** + * RemoveAll removes all the existing store entries. */ - status(): number + removeAll(): void } - interface Event { + interface Store { /** - * Flush flushes buffered data to the current response. + * Remove removes a single entry from the store. * - * Returns [http.ErrNotSupported] if e.Response doesn't implement the [http.Flusher] interface - * (all router package handlers receives a ResponseWritter that implements it unless explicitly replaced with a custom one). + * Remove does nothing if key doesn't exist in the store. */ - flush(): void + remove(key: K): void } - interface Event { + interface Store { /** - * IsTLS reports whether the connection on which the request was received is TLS. + * Has checks if element with the specified key exist or not. */ - isTLS(): boolean + has(key: K): boolean } - interface Event { + interface Store { /** - * SetCookie is an alias for [http.SetCookie]. + * Get returns a single element value from the store. * - * SetCookie adds a Set-Cookie header to the current response's headers. - * The provided cookie must have a valid Name. - * Invalid cookies may be silently dropped. + * If key is not set, the zero T value is returned. */ - setCookie(cookie: http.Cookie): void + get(key: K): T } - interface Event { + interface Store { /** - * RemoteIP returns the IP address of the client that sent the request. - * - * IPv6 addresses are returned expanded. - * For example, "2001:db8::1" becomes "2001:0db8:0000:0000:0000:0000:0000:0001". - * - * Note that if you are behind reverse proxy(ies), this method returns - * the IP of the last connecting proxy. + * GetOk is similar to Get but returns also a boolean indicating whether the key exists or not. */ - remoteIP(): string + getOk(key: K): [T, boolean] } - interface Event { + interface Store { /** - * FindUploadedFiles extracts all form files of "key" from a http request - * and returns a slice with filesystem.File instances (if any). + * GetAll returns a shallow copy of the current store data. */ - findUploadedFiles(key: string): Array<(filesystem.File | undefined)> + getAll(): _TygojaDict } - interface Event { + interface Store { /** - * Get retrieves single value from the current event data store. + * Keys returns a slice with all of the store keys. */ - get(key: string): any + keys(): Array } - interface Event { + interface Store { /** - * GetAll returns a copy of the current event data store. + * Values returns a slice with all of the store values. */ - getAll(): _TygojaDict + values(): Array } - interface Event { + interface Store { /** - * Set saves single value into the current event data store. + * Set sets (or overwrite if already exists) a new value for key. */ - set(key: string, value: any): void + set(key: K, value: T): void } - interface Event { + interface Store { /** - * SetAll saves all items from m into the current event data store. + * SetFunc sets (or overwrite if already exists) a new value resolved + * from the function callback for the provided key. + * + * The function callback receives as argument the old store element value (if exists). + * If there is no old store element, the argument will be the T zero value. + * + * Example: + * + * ``` + * s := store.New[string, int](nil) + * s.SetFunc("count", func(old int) int { + * return old + 1 + * }) + * ``` */ - setAll(m: _TygojaDict): void + setFunc(key: K, fn: (old: T) => T): void } - interface Event { + interface Store { /** - * String writes a plain string response. + * GetOrSet retrieves a single existing value for the provided key + * or stores a new one if it doesn't exist. */ - string(status: number, data: string): void + getOrSet(key: K, setFunc: () => T): T } - interface Event { + interface Store { /** - * HTML writes an HTML response. + * SetIfLessThanLimit sets (or overwrite if already exist) a new value for key. + * + * This method is similar to Set() but **it will skip adding new elements** + * to the store if the store length has reached the specified limit. + * false is returned if maxAllowedElements limit is reached. */ - html(status: number, data: string): void + setIfLessThanLimit(key: K, value: T, maxAllowedElements: number): boolean } - interface Event { + interface Store { /** - * JSON writes a JSON response. - * - * It also provides a generic response data fields picker if the "fields" query parameter is set. - * For example, if you are requesting `?fields=a,b` for `e.JSON(200, map[string]int{ "a":1, "b":2, "c":3 })`, - * it should result in a JSON response like: `{"a":1, "b": 2}`. + * UnmarshalJSON implements [json.Unmarshaler] and imports the + * provided JSON data into the store. * - * Note that invalid UTF8 characters are mangled for compatibility - * with earlier versions and to prevent unnecessary causing a response error. + * The store entries that match with the ones from the data will be overwritten with the new value. */ - json(status: number, data: any): void + unmarshalJSON(data: string|Array): void } - interface Event { + interface Store { /** - * XML writes an XML response. - * It automatically prepends the generic [xml.Header] string to the response. + * MarshalJSON implements [json.Marshaler] and export the current + * store data into valid JSON. */ - xml(status: number, data: any): void + marshalJSON(): string|Array } - interface Event { +} + +namespace subscriptions { + /** + * Broker defines a struct for managing subscriptions clients. + */ + interface Broker { + } + interface Broker { /** - * Stream streams the specified reader into the response. + * Clients returns a shallow copy of all registered clients indexed + * with their connection id. */ - stream(status: number, contentType: string, reader: io.Reader): void + clients(): _TygojaDict } - interface Event { + interface Broker { /** - * Blob writes a blob (bytes slice) response. + * ChunkedClients splits the current clients into a chunked slice. */ - blob(status: number, contentType: string, b: string|Array): void + chunkedClients(chunkSize: number): Array> } - interface Event { + interface Broker { /** - * FileFS serves the specified filename from fsys. - * - * It is similar to [echo.FileFS] for consistency with earlier versions. + * TotalClients returns the total number of registered clients. */ - fileFS(fsys: fs.FS, filename: string): void + totalClients(): number } - interface Event { + interface Broker { /** - * NoContent writes a response with no body (ex. 204). + * ClientById finds a registered client by its id. + * + * Returns non-nil error when client with clientId is not registered. */ - noContent(status: number): void + clientById(clientId: string): Client } - interface Event { + interface Broker { /** - * Redirect writes a redirect response to the specified url. - * The status code must be in between 300 – 399 range. + * Register adds a new client to the broker instance. */ - redirect(status: number, url: string): void - } - interface Event { - error(status: number, message: string, errData: any): (ApiError) - } - interface Event { - badRequestError(message: string, errData: any): (ApiError) - } - interface Event { - notFoundError(message: string, errData: any): (ApiError) - } - interface Event { - forbiddenError(message: string, errData: any): (ApiError) - } - interface Event { - unauthorizedError(message: string, errData: any): (ApiError) - } - interface Event { - tooManyRequestsError(message: string, errData: any): (ApiError) + register(client: Client): void } - interface Event { - internalServerError(message: string, errData: any): (ApiError) + interface Broker { + /** + * Unregister removes a single client by its id and marks it as discarded. + * + * If client with clientId doesn't exist, this method does nothing. + */ + unregister(clientId: string): void } - interface Event { + /** + * Client is an interface for a generic subscription client. + */ + interface Client { + [key:string]: any; /** - * BindBody unmarshal the request body into the provided dst. + * Id Returns the unique id of the client. + */ + id(): string + /** + * Channel returns the client's communication channel. * - * dst must be either a struct pointer or map[string]any. + * NB! The channel shouldn't be used after calling Discard(). + */ + channel(): undefined + /** + * Subscriptions returns a shallow copy of the client subscriptions matching the prefixes. + * If no prefix is specified, returns all subscriptions. + */ + subscriptions(...prefixes: string[]): _TygojaDict + /** + * Subscribe subscribes the client to the provided subscriptions list. * - * The rules how the body will be scanned depends on the request Content-Type. + * Each subscription can also have "options" (json serialized SubscriptionOptions) as query parameter. * - * Currently the following Content-Types are supported: - * ``` - * - application/json - * - text/xml, application/xml - * - multipart/form-data, application/x-www-form-urlencoded - * ``` + * Example: * - * Respectively the following struct tags are supported (again, which one will be used depends on the Content-Type): - * ``` - * - "json" (json body)- uses the builtin Go json package for unmarshaling. - * - "xml" (xml body) - uses the builtin Go xml package for unmarshaling. - * - "form" (form data) - utilizes the custom [router.UnmarshalRequestData] method. * ``` - * - * NB! When dst is a struct make sure that it doesn't have public fields - * that shouldn't be bindable and it is advisible such fields to be unexported - * or have a separate struct just for the binding. For example: - * + * Subscribe( + * "subscriptionA", + * `subscriptionB?options={"query":{"a":1},"headers":{"x_token":"abc"}}`, + * ) * ``` - * data := struct{ - * somethingPrivate string + */ + subscribe(...subs: string[]): void + /** + * Unsubscribe unsubscribes the client from the provided subscriptions list. + */ + unsubscribe(...subs: string[]): void + /** + * HasSubscription checks if the client is subscribed to `sub`. + */ + hasSubscription(sub: string): boolean + /** + * Set stores any value to the client's context. + */ + set(key: string, value: any): void + /** + * Unset removes a single value from the client's context. + */ + unset(key: string): void + /** + * Get retrieves the key value from the client's context. + */ + get(key: string): any + /** + * Discard marks the client as "discarded" (and closes its channel), + * meaning that it shouldn't be used anymore for sending new messages. * - * Title string `json:"title" form:"title"` - * Total int `json:"total" form:"total"` - * }{} - * err := e.BindBody(&data) - * ``` + * It is safe to call Discard() multiple times. */ - bindBody(dst: any): void + discard(): void + /** + * IsDiscarded indicates whether the client has been "discarded" + * and should no longer be used. + */ + isDiscarded(): boolean + /** + * Send sends the specified message to the client's channel (if not discarded). + */ + send(m: Message): void } /** - * Router defines a thin wrapper around the standard Go [http.ServeMux] by - * adding support for routing sub-groups, middlewares and other common utils. - * - * Example: - * - * ``` - * r := NewRouter[*MyEvent](eventFactory) - * - * // middlewares - * r.BindFunc(m1, m2) - * - * // routes - * r.GET("/test", handler1) - * - * // sub-routers/groups - * api := r.Group("/api") - * api.GET("/admins", handler2) - * - * // generate a http.ServeMux instance based on the router configurations - * mux, _ := r.BuildMux() - * - * http.ListenAndServe("localhost:8090", mux) - * ``` + * Message defines a client's channel data. */ - type _sVOsxGt = RouterGroup - interface Router extends _sVOsxGt { + interface Message { + name: string + data: string|Array } - interface Router { + interface Message { /** - * BuildMux constructs a new mux [http.Handler] instance from the current router configurations. + * WriteSSE writes the current message in a SSE format into the provided writer. + * + * For example, writing to a router.Event: + * + * ``` + * m := Message{Name: "users/create", Data: []byte{...}} + * m.WriteSSE(e.Response, "yourEventId") + * e.Flush() + * ``` */ - buildMux(): http.Handler + writeSSE(w: io.Writer, eventId: string): void } } @@ -20561,34 +20308,6 @@ namespace auth { } } -namespace mailer { - /** - * Message defines a generic email message struct. - */ - interface Message { - from: { address: string; name?: string; } - to: Array<{ address: string; name?: string; }> - bcc: Array<{ address: string; name?: string; }> - cc: Array<{ address: string; name?: string; }> - subject: string - html: string - text: string - headers: _TygojaDict - attachments: _TygojaDict - inlineAttachments: _TygojaDict - } - /** - * Mailer defines a base mail client interface. - */ - interface Mailer { - [key:string]: any; - /** - * Send sends an email with the provided Message. - */ - send(message: Message): void - } -} - /** * Package slog provides structured logging, * in which log records include a message, @@ -20981,2014 +20700,1847 @@ namespace slog { */ handler(): Handler } - interface Logger { - /** - * With returns a Logger that includes the given attributes - * in each output operation. Arguments are converted to - * attributes as if by [Logger.Log]. - */ - with(...args: any[]): (Logger) - } - interface Logger { - /** - * WithGroup returns a Logger that starts a group, if name is non-empty. - * The keys of all attributes added to the Logger will be qualified by the given - * name. (How that qualification happens depends on the [Handler.WithGroup] - * method of the Logger's Handler.) - * - * If name is empty, WithGroup returns the receiver. - */ - withGroup(name: string): (Logger) - } - interface Logger { - /** - * Enabled reports whether l emits log records at the given context and level. - */ - enabled(ctx: context.Context, level: Level): boolean - } - interface Logger { - /** - * Log emits a log record with the current time and the given level and message. - * The Record's Attrs consist of the Logger's attributes followed by - * the Attrs specified by args. - * - * The attribute arguments are processed as follows: - * ``` - * - If an argument is an Attr, it is used as is. - * - If an argument is a string and this is not the last argument, - * the following argument is treated as the value and the two are combined - * into an Attr. - * - Otherwise, the argument is treated as a value with key "!BADKEY". - * ``` - */ - log(ctx: context.Context, level: Level, msg: string, ...args: any[]): void - } - interface Logger { - /** - * LogAttrs is a more efficient version of [Logger.Log] that accepts only Attrs. - */ - logAttrs(ctx: context.Context, level: Level, msg: string, ...attrs: Attr[]): void - } - interface Logger { - /** - * Debug logs at [LevelDebug]. - * It uses [context.Background] internally; to specify the context, use - * [Logger.DebugContext]. - */ - debug(msg: string, ...args: any[]): void - } - interface Logger { - /** - * DebugContext logs at [LevelDebug] with the given context. - */ - debugContext(ctx: context.Context, msg: string, ...args: any[]): void - } - interface Logger { - /** - * Info logs at [LevelInfo]. - * It uses [context.Background] internally; to specify the context, use - * [Logger.InfoContext]. - */ - info(msg: string, ...args: any[]): void - } - interface Logger { - /** - * InfoContext logs at [LevelInfo] with the given context. - */ - infoContext(ctx: context.Context, msg: string, ...args: any[]): void - } - interface Logger { - /** - * Warn logs at [LevelWarn]. - * It uses [context.Background] internally; to specify the context, use - * [Logger.WarnContext]. - */ - warn(msg: string, ...args: any[]): void - } - interface Logger { - /** - * WarnContext logs at [LevelWarn] with the given context. - */ - warnContext(ctx: context.Context, msg: string, ...args: any[]): void - } - interface Logger { - /** - * Error logs at [LevelError]. - * It uses [context.Background] internally; to specify the context, use - * [Logger.ErrorContext]. - */ - error(msg: string, ...args: any[]): void - } - interface Logger { - /** - * ErrorContext logs at [LevelError] with the given context. - */ - errorContext(ctx: context.Context, msg: string, ...args: any[]): void - } -} - -namespace subscriptions { - /** - * Broker defines a struct for managing subscriptions clients. - */ - interface Broker { - } - interface Broker { - /** - * Clients returns a shallow copy of all registered clients indexed - * with their connection id. - */ - clients(): _TygojaDict - } - interface Broker { - /** - * ChunkedClients splits the current clients into a chunked slice. - */ - chunkedClients(chunkSize: number): Array> - } - interface Broker { - /** - * TotalClients returns the total number of registered clients. - */ - totalClients(): number - } - interface Broker { - /** - * ClientById finds a registered client by its id. - * - * Returns non-nil error when client with clientId is not registered. - */ - clientById(clientId: string): Client - } - interface Broker { - /** - * Register adds a new client to the broker instance. - */ - register(client: Client): void - } - interface Broker { - /** - * Unregister removes a single client by its id and marks it as discarded. - * - * If client with clientId doesn't exist, this method does nothing. - */ - unregister(clientId: string): void - } - /** - * Client is an interface for a generic subscription client. - */ - interface Client { - [key:string]: any; + interface Logger { /** - * Id Returns the unique id of the client. + * With returns a Logger that includes the given attributes + * in each output operation. Arguments are converted to + * attributes as if by [Logger.Log]. */ - id(): string + with(...args: any[]): (Logger) + } + interface Logger { /** - * Channel returns the client's communication channel. + * WithGroup returns a Logger that starts a group, if name is non-empty. + * The keys of all attributes added to the Logger will be qualified by the given + * name. (How that qualification happens depends on the [Handler.WithGroup] + * method of the Logger's Handler.) * - * NB! The channel shouldn't be used after calling Discard(). + * If name is empty, WithGroup returns the receiver. */ - channel(): undefined + withGroup(name: string): (Logger) + } + interface Logger { /** - * Subscriptions returns a shallow copy of the client subscriptions matching the prefixes. - * If no prefix is specified, returns all subscriptions. + * Enabled reports whether l emits log records at the given context and level. */ - subscriptions(...prefixes: string[]): _TygojaDict + enabled(ctx: context.Context, level: Level): boolean + } + interface Logger { /** - * Subscribe subscribes the client to the provided subscriptions list. - * - * Each subscription can also have "options" (json serialized SubscriptionOptions) as query parameter. - * - * Example: + * Log emits a log record with the current time and the given level and message. + * The Record's Attrs consist of the Logger's attributes followed by + * the Attrs specified by args. * + * The attribute arguments are processed as follows: * ``` - * Subscribe( - * "subscriptionA", - * `subscriptionB?options={"query":{"a":1},"headers":{"x_token":"abc"}}`, - * ) + * - If an argument is an Attr, it is used as is. + * - If an argument is a string and this is not the last argument, + * the following argument is treated as the value and the two are combined + * into an Attr. + * - Otherwise, the argument is treated as a value with key "!BADKEY". * ``` */ - subscribe(...subs: string[]): void + log(ctx: context.Context, level: Level, msg: string, ...args: any[]): void + } + interface Logger { /** - * Unsubscribe unsubscribes the client from the provided subscriptions list. + * LogAttrs is a more efficient version of [Logger.Log] that accepts only Attrs. */ - unsubscribe(...subs: string[]): void + logAttrs(ctx: context.Context, level: Level, msg: string, ...attrs: Attr[]): void + } + interface Logger { /** - * HasSubscription checks if the client is subscribed to `sub`. + * Debug logs at [LevelDebug]. + * It uses [context.Background] internally; to specify the context, use + * [Logger.DebugContext]. */ - hasSubscription(sub: string): boolean + debug(msg: string, ...args: any[]): void + } + interface Logger { /** - * Set stores any value to the client's context. + * DebugContext logs at [LevelDebug] with the given context. */ - set(key: string, value: any): void + debugContext(ctx: context.Context, msg: string, ...args: any[]): void + } + interface Logger { /** - * Unset removes a single value from the client's context. + * Info logs at [LevelInfo]. + * It uses [context.Background] internally; to specify the context, use + * [Logger.InfoContext]. */ - unset(key: string): void + info(msg: string, ...args: any[]): void + } + interface Logger { /** - * Get retrieves the key value from the client's context. + * InfoContext logs at [LevelInfo] with the given context. */ - get(key: string): any + infoContext(ctx: context.Context, msg: string, ...args: any[]): void + } + interface Logger { /** - * Discard marks the client as "discarded" (and closes its channel), - * meaning that it shouldn't be used anymore for sending new messages. - * - * It is safe to call Discard() multiple times. + * Warn logs at [LevelWarn]. + * It uses [context.Background] internally; to specify the context, use + * [Logger.WarnContext]. */ - discard(): void + warn(msg: string, ...args: any[]): void + } + interface Logger { /** - * IsDiscarded indicates whether the client has been "discarded" - * and should no longer be used. + * WarnContext logs at [LevelWarn] with the given context. */ - isDiscarded(): boolean + warnContext(ctx: context.Context, msg: string, ...args: any[]): void + } + interface Logger { /** - * Send sends the specified message to the client's channel (if not discarded). + * Error logs at [LevelError]. + * It uses [context.Background] internally; to specify the context, use + * [Logger.ErrorContext]. */ - send(m: Message): void - } - /** - * Message defines a client's channel data. - */ - interface Message { - name: string - data: string|Array + error(msg: string, ...args: any[]): void } - interface Message { + interface Logger { /** - * WriteSSE writes the current message in a SSE format into the provided writer. - * - * For example, writing to a router.Event: - * - * ``` - * m := Message{Name: "users/create", Data: []byte{...}} - * m.WriteSSE(e.Response, "yourEventId") - * e.Flush() - * ``` + * ErrorContext logs at [LevelError] with the given context. */ - writeSSE(w: io.Writer, eventId: string): void + errorContext(ctx: context.Context, msg: string, ...args: any[]): void } } -/** - * Package cron implements a crontab-like service to execute and schedule - * repeative tasks/jobs. - * - * Example: - * - * ``` - * c := cron.New() - * c.MustAdd("dailyReport", "0 0 * * *", func() { ... }) - * c.Start() - * ``` - */ -namespace cron { +namespace hook { /** - * Cron is a crontab-like struct for tasks/jobs scheduling. + * Event implements [Resolver] and it is intended to be used as a base + * Hook event that you can embed in your custom typed event structs. + * + * Example: + * + * ``` + * type CustomEvent struct { + * hook.Event + * + * SomeField int + * } + * ``` */ - interface Cron { - } - interface Cron { - /** - * SetInterval changes the current cron tick interval - * (it usually should be >= 1 minute). - */ - setInterval(d: time.Duration): void + interface Event { } - interface Cron { + interface Event { /** - * SetTimezone changes the current cron tick timezone. + * Next calls the next hook handler. */ - setTimezone(l: time.Location): void + next(): void } - interface Cron { + /** + * Handler defines a single Hook handler. + * Multiple handlers can share the same id. + * If Id is not explicitly set it will be autogenerated by Hook.Add and Hook.AddHandler. + */ + interface Handler { /** - * MustAdd is similar to Add() but panic on failure. + * Func defines the handler function to execute. + * + * Note that users need to call e.Next() in order to proceed with + * the execution of the hook chain. */ - mustAdd(jobId: string, cronExpr: string, run: () => void): void - } - interface Cron { + func: (_arg0: T) => void /** - * Add registers a single cron job. + * Id is the unique identifier of the handler. * - * If there is already a job with the provided id, then the old job - * will be replaced with the new one. + * It could be used later to remove the handler from a hook via [Hook.Remove]. * - * cronExpr is a regular cron expression, eg. "0 *\/3 * * *" (aka. at minute 0 past every 3rd hour). - * Check cron.NewSchedule() for the supported tokens. - */ - add(jobId: string, cronExpr: string, fn: () => void): void - } - interface Cron { - /** - * Remove removes a single cron job by its id. - */ - remove(jobId: string): void - } - interface Cron { - /** - * RemoveAll removes all registered cron jobs. - */ - removeAll(): void - } - interface Cron { - /** - * Total returns the current total number of registered cron jobs. - */ - total(): number - } - interface Cron { - /** - * Jobs returns a shallow copy of the currently registered cron jobs. + * If missing, an autogenerated value will be assigned when adding + * the handler to a hook. */ - jobs(): Array<(Job | undefined)> - } - interface Cron { + id: string /** - * Stop stops the current cron ticker (if not already). + * Priority allows changing the default exec priority of the handler within a hook. * - * You can resume the ticker by calling Start(). + * If 0, the handler will be executed in the same order it was registered. */ - stop(): void + priority: number } - interface Cron { + /** + * Hook defines a generic concurrent safe structure for managing event hooks. + * + * When using custom event it must embed the base [hook.Event]. + * + * Example: + * + * ``` + * type CustomEvent struct { + * hook.Event + * SomeField int + * } + * + * h := Hook[*CustomEvent]{} + * + * h.BindFunc(func(e *CustomEvent) error { + * println(e.SomeField) + * + * return e.Next() + * }) + * + * h.Trigger(&CustomEvent{ SomeField: 123 }) + * ``` + */ + interface Hook { + } + interface Hook { /** - * Start starts the cron ticker. + * Bind registers the provided handler to the current hooks queue. * - * Calling Start() on already started cron will restart the ticker. + * If handler.Id is empty it is updated with autogenerated value. + * + * If a handler from the current hook list has Id matching handler.Id + * then the old handler is replaced with the new one. */ - start(): void + bind(handler: Handler): string } - interface Cron { + interface Hook { /** - * HasStarted checks whether the current Cron ticker has been started. + * BindFunc is similar to Bind but registers a new handler from just the provided function. + * + * The registered handler is added with a default 0 priority and the id will be autogenerated. + * + * If you want to register a handler with custom priority or id use the [Hook.Bind] method. */ - hasStarted(): boolean + bindFunc(fn: (e: T) => void): string } -} - -/** - * Package cobra is a commander providing a simple interface to create powerful modern CLI interfaces. - * In addition to providing an interface, Cobra simultaneously provides a controller to organize your application code. - */ -namespace cobra { - interface Command { + interface Hook { /** - * GenBashCompletion generates bash completion file and writes to the passed writer. + * Unbind removes one or many hook handler by their id. */ - genBashCompletion(w: io.Writer): void + unbind(...idsToRemove: string[]): void } - interface Command { + interface Hook { /** - * GenBashCompletionFile generates bash completion file. + * UnbindAll removes all registered handlers. */ - genBashCompletionFile(filename: string): void + unbindAll(): void } - interface Command { + interface Hook { /** - * GenBashCompletionFileV2 generates Bash completion version 2. + * Length returns to total number of registered hook handlers. */ - genBashCompletionFileV2(filename: string, includeDesc: boolean): void + length(): number } - interface Command { + interface Hook { /** - * GenBashCompletionV2 generates Bash completion file version 2 - * and writes it to the passed writer. + * Trigger executes all registered hook handlers one by one + * with the specified event as an argument. + * + * Optionally, this method allows also to register additional one off + * handler funcs that will be temporary appended to the handlers queue. + * + * NB! Each hook handler must call event.Next() in order the hook chain to proceed. */ - genBashCompletionV2(w: io.Writer, includeDesc: boolean): void + trigger(event: T, ...oneOffHandlerFuncs: ((_arg0: T) => void)[]): void } - // @ts-ignore - import flag = pflag /** - * Command is just that, a command for your application. - * E.g. 'go run ...' - 'run' is the command. Cobra requires - * you to define the usage and description as part of your command - * definition to ensure usability. + * TaggedHook defines a proxy hook which register handlers that are triggered only + * if the TaggedHook.tags are empty or includes at least one of the event data tag(s). */ - interface Command { - /** - * Use is the one-line usage message. - * Recommended syntax is as follows: - * ``` - * [ ] identifies an optional argument. Arguments that are not enclosed in brackets are required. - * ... indicates that you can specify multiple values for the previous argument. - * | indicates mutually exclusive information. You can use the argument to the left of the separator or the - * argument to the right of the separator. You cannot use both arguments in a single use of the command. - * { } delimits a set of mutually exclusive arguments when one of the arguments is required. If the arguments are - * optional, they are enclosed in brackets ([ ]). - * ``` - * Example: add [-F file | -D dir]... [-f format] profile - */ - use: string - /** - * Aliases is an array of aliases that can be used instead of the first word in Use. - */ - aliases: Array - /** - * SuggestFor is an array of command names for which this command will be suggested - - * similar to aliases but only suggests. - */ - suggestFor: Array - /** - * Short is the short description shown in the 'help' output. - */ - short: string - /** - * The group id under which this subcommand is grouped in the 'help' output of its parent. - */ - groupID: string - /** - * Long is the long message shown in the 'help ' output. - */ - long: string - /** - * Example is examples of how to use the command. - */ - example: string - /** - * ValidArgs is list of all valid non-flag arguments that are accepted in shell completions - */ - validArgs: Array - /** - * ValidArgsFunction is an optional function that provides valid non-flag arguments for shell completion. - * It is a dynamic version of using ValidArgs. - * Only one of ValidArgs and ValidArgsFunction can be used for a command. - */ - validArgsFunction: CompletionFunc - /** - * Expected arguments - */ - args: PositionalArgs - /** - * ArgAliases is List of aliases for ValidArgs. - * These are not suggested to the user in the shell completion, - * but accepted if entered manually. - */ - argAliases: Array + type _sdgUcvX = mainHook + interface TaggedHook extends _sdgUcvX { + } + interface TaggedHook { /** - * BashCompletionFunction is custom bash functions used by the legacy bash autocompletion generator. - * For portability with other shells, it is recommended to instead use ValidArgsFunction + * CanTriggerOn checks if the current TaggedHook can be triggered with + * the provided event data tags. + * + * It returns always true if the hook doesn't have any tags. */ - bashCompletionFunction: string + canTriggerOn(tagsToCheck: Array): boolean + } + interface TaggedHook { /** - * Deprecated defines, if this command is deprecated and should print this string when used. + * Bind registers the provided handler to the current hooks queue. + * + * It is similar to [Hook.Bind] with the difference that the handler + * function is invoked only if the event data tags satisfy h.CanTriggerOn. */ - deprecated: string + bind(handler: Handler): string + } + interface TaggedHook { /** - * Annotations are key/value pairs that can be used by applications to identify or - * group commands or set special options. + * BindFunc registers a new handler with the specified function. + * + * It is similar to [Hook.Bind] with the difference that the handler + * function is invoked only if the event data tags satisfy h.CanTriggerOn. */ - annotations: _TygojaDict + bindFunc(fn: (e: T) => void): string + } +} + +namespace search { + /** + * Result defines the returned search result structure. + */ + interface Result { + items: any + page: number + perPage: number + totalItems: number + totalPages: number + } + /** + * ResolverResult defines a single FieldResolver.Resolve() successfully parsed result. + */ + interface ResolverResult { /** - * Version defines the version for this command. If this value is non-empty and the command does not - * define a "version" flag, a "version" boolean flag will be added to the command and, if specified, - * will print content of the "Version" variable. A shorthand "v" flag will also be added if the - * command does not define one. + * Identifier is the plain SQL identifier/column that will be used + * in the final db expression as left or right operand. */ - version: string + identifier: string /** - * The *Run functions are executed in the following order: - * ``` - * * PersistentPreRun() - * * PreRun() - * * Run() - * * PostRun() - * * PersistentPostRun() - * ``` - * All functions get the same args, the arguments after the command name. - * The *PreRun and *PostRun functions will only be executed if the Run function of the current - * command has been declared. + * NullFallback specify the preference for how NULL or empty values + * should be resolved (default to "auto"). * - * PersistentPreRun: children of this command will inherit and execute. - */ - persistentPreRun: (cmd: Command, args: Array) => void - /** - * PersistentPreRunE: PersistentPreRun but returns an error. + * Set to NullFallbackDisabled to prevent any COALESCE or NULL fallbacks. + * Set to NullFallbackEnforced to prefer COALESCE or NULL fallbacks when needed. */ - persistentPreRunE: (cmd: Command, args: Array) => void + nullFallback: NullFallbackPreference /** - * PreRun: children of this command will not inherit. + * 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. */ - preRun: (cmd: Command, args: Array) => void + params: dbx.Params /** - * PreRunE: PreRun but returns an error. + * MultiMatchSubQuery is an optional sub query expression that will be added + * in addition to the combined ResolverResult expression during build. */ - preRunE: (cmd: Command, args: Array) => void + multiMatchSubQuery?: MultiMatchSubquery /** - * Run: Typically the actual work function. Most commands will only implement this. + * AfterBuild is an optional function that will be called after building + * and combining the result of both resolved operands/sides in a single expression. */ - run: (cmd: Command, args: Array) => void + afterBuild: (expr: dbx.Expression) => dbx.Expression + } +} + +namespace router { + // @ts-ignore + import validation = ozzo_validation + /** + * ApiError defines the struct for a basic api error response. + */ + interface ApiError { + data: _TygojaDict + message: string + status: number + } + interface ApiError { /** - * RunE: Run but returns an error. + * Error makes it compatible with the `error` interface. */ - runE: (cmd: Command, args: Array) => void + error(): string + } + interface ApiError { /** - * PostRun: run after the Run command. + * RawData returns the unformatted error data (could be an internal error, text, etc.) */ - postRun: (cmd: Command, args: Array) => void + rawData(): any + } + interface ApiError { /** - * PostRunE: PostRun but returns an error. + * Is reports whether the current ApiError wraps the target. */ - postRunE: (cmd: Command, args: Array) => void + is(target: Error): boolean + } + /** + * Event specifies based Route handler event that is usually intended + * to be embedded as part of a custom event struct. + * + * NB! It is expected that the Response and Request fields are always set. + */ + type _spTaHbt = hook.Event + interface Event extends _spTaHbt { + response: http.ResponseWriter + request?: http.Request + } + interface Event { /** - * PersistentPostRun: children of this command will inherit and execute after PostRun. + * Written reports whether the current response has already been written. + * + * This method always returns false if e.ResponseWritter doesn't implement the WriteTracker interface + * (all router package handlers receives a ResponseWritter that implements it unless explicitly replaced with a custom one). */ - persistentPostRun: (cmd: Command, args: Array) => void + written(): boolean + } + interface Event { /** - * PersistentPostRunE: PersistentPostRun but returns an error. + * Status reports the status code of the current response. + * + * This method always returns 0 if e.Response doesn't implement the StatusTracker interface + * (all router package handlers receives a ResponseWritter that implements it unless explicitly replaced with a custom one). */ - persistentPostRunE: (cmd: Command, args: Array) => void + status(): number + } + interface Event { /** - * FParseErrWhitelist flag parse errors to be ignored + * Flush flushes buffered data to the current response. + * + * Returns [http.ErrNotSupported] if e.Response doesn't implement the [http.Flusher] interface + * (all router package handlers receives a ResponseWritter that implements it unless explicitly replaced with a custom one). */ - fParseErrWhitelist: FParseErrWhitelist + flush(): void + } + interface Event { /** - * CompletionOptions is a set of options to control the handling of shell completion + * IsTLS reports whether the connection on which the request was received is TLS. */ - completionOptions: CompletionOptions + isTLS(): boolean + } + interface Event { /** - * TraverseChildren parses flags on all parents before executing child command. + * SetCookie is an alias for [http.SetCookie]. + * + * SetCookie adds a Set-Cookie header to the current response's headers. + * The provided cookie must have a valid Name. + * Invalid cookies may be silently dropped. */ - traverseChildren: boolean + setCookie(cookie: http.Cookie): void + } + interface Event { /** - * Hidden defines, if this command is hidden and should NOT show up in the list of available commands. + * RemoteIP returns the IP address of the client that sent the request. + * + * IPv6 addresses are returned expanded. + * For example, "2001:db8::1" becomes "2001:0db8:0000:0000:0000:0000:0000:0001". + * + * Note that if you are behind reverse proxy(ies), this method returns + * the IP of the last connecting proxy. */ - hidden: boolean + remoteIP(): string + } + interface Event { /** - * SilenceErrors is an option to quiet errors down stream. + * FindUploadedFiles extracts all form files of "key" from a http request + * and returns a slice with filesystem.File instances (if any). */ - silenceErrors: boolean + findUploadedFiles(key: string): Array<(filesystem.File | undefined)> + } + interface Event { /** - * SilenceUsage is an option to silence usage when an error occurs. + * Get retrieves single value from the current event data store. */ - silenceUsage: boolean + get(key: string): any + } + interface Event { /** - * DisableFlagParsing disables the flag parsing. - * If this is true all flags will be passed to the command as arguments. + * GetAll returns a copy of the current event data store. */ - disableFlagParsing: boolean + getAll(): _TygojaDict + } + interface Event { /** - * DisableAutoGenTag defines, if gen tag ("Auto generated by spf13/cobra...") - * will be printed by generating docs for this command. + * Set saves single value into the current event data store. */ - disableAutoGenTag: boolean + set(key: string, value: any): void + } + interface Event { /** - * DisableFlagsInUseLine will disable the addition of [flags] to the usage - * line of a command when printing help or generating docs + * SetAll saves all items from m into the current event data store. */ - disableFlagsInUseLine: boolean + setAll(m: _TygojaDict): void + } + interface Event { /** - * DisableSuggestions disables the suggestions based on Levenshtein distance - * that go along with 'unknown command' messages. + * String writes a plain string response. */ - disableSuggestions: boolean + string(status: number, data: string): void + } + interface Event { /** - * SuggestionsMinimumDistance defines minimum levenshtein distance to display suggestions. - * Must be > 0. + * HTML writes an HTML response. */ - suggestionsMinimumDistance: number + html(status: number, data: string): void } - interface Command { + interface Event { /** - * Context returns underlying command context. If command was executed - * with ExecuteContext or the context was set with SetContext, the - * previously set context will be returned. Otherwise, nil is returned. + * JSON writes a JSON response. * - * Notice that a call to Execute and ExecuteC will replace a nil context of - * a command with a context.Background, so a background context will be - * returned by Context after one of these functions has been called. + * It also provides a generic response data fields picker if the "fields" query parameter is set. + * For example, if you are requesting `?fields=a,b` for `e.JSON(200, map[string]int{ "a":1, "b":2, "c":3 })`, + * it should result in a JSON response like: `{"a":1, "b": 2}`. + * + * Note that invalid UTF8 characters are mangled for compatibility + * with earlier versions and to prevent unnecessary causing a response error. */ - context(): context.Context + json(status: number, data: any): void } - interface Command { + interface Event { /** - * SetContext sets context for the command. This context will be overwritten by - * Command.ExecuteContext or Command.ExecuteContextC. + * XML writes an XML response. + * It automatically prepends the generic [xml.Header] string to the response. */ - setContext(ctx: context.Context): void + xml(status: number, data: any): void } - interface Command { + interface Event { /** - * SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden - * particularly useful when testing. + * Stream streams the specified reader into the response. */ - setArgs(a: Array): void + stream(status: number, contentType: string, reader: io.Reader): void } - interface Command { + interface Event { /** - * SetOutput sets the destination for usage and error messages. - * If output is nil, os.Stderr is used. - * - * Deprecated: Use SetOut and/or SetErr instead + * Blob writes a blob (bytes slice) response. */ - setOutput(output: io.Writer): void + blob(status: number, contentType: string, b: string|Array): void } - interface Command { + interface Event { /** - * SetOut sets the destination for usage messages. - * If newOut is nil, os.Stdout is used. + * FileFS serves the specified filename from fsys. + * + * It is similar to [echo.FileFS] for consistency with earlier versions. */ - setOut(newOut: io.Writer): void + fileFS(fsys: fs.FS, filename: string): void } - interface Command { + interface Event { /** - * SetErr sets the destination for error messages. - * If newErr is nil, os.Stderr is used. + * NoContent writes a response with no body (ex. 204). */ - setErr(newErr: io.Writer): void + noContent(status: number): void } - interface Command { + interface Event { /** - * SetIn sets the source for input data - * If newIn is nil, os.Stdin is used. + * Redirect writes a redirect response to the specified url. + * The status code must be in between 300 – 399 range. */ - setIn(newIn: io.Reader): void + redirect(status: number, url: string): void } - interface Command { + interface Event { + error(status: number, message: string, errData: any): (ApiError) + } + interface Event { + badRequestError(message: string, errData: any): (ApiError) + } + interface Event { + notFoundError(message: string, errData: any): (ApiError) + } + interface Event { + forbiddenError(message: string, errData: any): (ApiError) + } + interface Event { + unauthorizedError(message: string, errData: any): (ApiError) + } + interface Event { + tooManyRequestsError(message: string, errData: any): (ApiError) + } + interface Event { + internalServerError(message: string, errData: any): (ApiError) + } + interface Event { /** - * SetUsageFunc sets usage function. Usage can be defined by application. + * BindBody unmarshal the request body into the provided dst. + * + * dst must be either a struct pointer or map[string]any. + * + * The rules how the body will be scanned depends on the request Content-Type. + * + * Currently the following Content-Types are supported: + * ``` + * - application/json + * - text/xml, application/xml + * - multipart/form-data, application/x-www-form-urlencoded + * ``` + * + * Respectively the following struct tags are supported (again, which one will be used depends on the Content-Type): + * ``` + * - "json" (json body)- uses the builtin Go json package for unmarshaling. + * - "xml" (xml body) - uses the builtin Go xml package for unmarshaling. + * - "form" (form data) - utilizes the custom [router.UnmarshalRequestData] method. + * ``` + * + * NB! When dst is a struct make sure that it doesn't have public fields + * that shouldn't be bindable and it is advisible such fields to be unexported + * or have a separate struct just for the binding. For example: + * + * ``` + * data := struct{ + * somethingPrivate string + * + * Title string `json:"title" form:"title"` + * Total int `json:"total" form:"total"` + * }{} + * err := e.BindBody(&data) + * ``` */ - setUsageFunc(f: (_arg0: Command) => void): void + bindBody(dst: any): void } - interface Command { + /** + * Router defines a thin wrapper around the standard Go [http.ServeMux] by + * adding support for routing sub-groups, middlewares and other common utils. + * + * Example: + * + * ``` + * r := NewRouter[*MyEvent](eventFactory) + * + * // middlewares + * r.BindFunc(m1, m2) + * + * // routes + * r.GET("/test", handler1) + * + * // sub-routers/groups + * api := r.Group("/api") + * api.GET("/admins", handler2) + * + * // generate a http.ServeMux instance based on the router configurations + * mux, _ := r.BuildMux() + * + * http.ListenAndServe("localhost:8090", mux) + * ``` + */ + type _sEiobfY = RouterGroup + interface Router extends _sEiobfY { + } + interface Router { /** - * SetUsageTemplate sets usage template. Can be defined by Application. + * BuildMux constructs a new mux [http.Handler] instance from the current router configurations. */ - setUsageTemplate(s: string): void + buildMux(): http.Handler } +} + +/** + * Package cobra is a commander providing a simple interface to create powerful modern CLI interfaces. + * In addition to providing an interface, Cobra simultaneously provides a controller to organize your application code. + */ +namespace cobra { interface Command { /** - * SetFlagErrorFunc sets a function to generate an error when flag parsing - * fails. + * GenBashCompletion generates bash completion file and writes to the passed writer. */ - setFlagErrorFunc(f: (_arg0: Command, _arg1: Error) => void): void + genBashCompletion(w: io.Writer): void } interface Command { /** - * SetHelpFunc sets help function. Can be defined by Application. + * GenBashCompletionFile generates bash completion file. */ - setHelpFunc(f: (_arg0: Command, _arg1: Array) => void): void + genBashCompletionFile(filename: string): void } interface Command { /** - * SetHelpCommand sets help command. + * GenBashCompletionFileV2 generates Bash completion version 2. */ - setHelpCommand(cmd: Command): void + genBashCompletionFileV2(filename: string, includeDesc: boolean): void } interface Command { /** - * SetHelpCommandGroupID sets the group id of the help command. + * GenBashCompletionV2 generates Bash completion file version 2 + * and writes it to the passed writer. */ - setHelpCommandGroupID(groupID: string): void + genBashCompletionV2(w: io.Writer, includeDesc: boolean): void } + // @ts-ignore + import flag = pflag + /** + * Command is just that, a command for your application. + * E.g. 'go run ...' - 'run' is the command. Cobra requires + * you to define the usage and description as part of your command + * definition to ensure usability. + */ interface Command { /** - * SetCompletionCommandGroupID sets the group id of the completion command. + * Use is the one-line usage message. + * Recommended syntax is as follows: + * ``` + * [ ] identifies an optional argument. Arguments that are not enclosed in brackets are required. + * ... indicates that you can specify multiple values for the previous argument. + * | indicates mutually exclusive information. You can use the argument to the left of the separator or the + * argument to the right of the separator. You cannot use both arguments in a single use of the command. + * { } delimits a set of mutually exclusive arguments when one of the arguments is required. If the arguments are + * optional, they are enclosed in brackets ([ ]). + * ``` + * Example: add [-F file | -D dir]... [-f format] profile */ - setCompletionCommandGroupID(groupID: string): void - } - interface Command { + use: string /** - * SetHelpTemplate sets help template to be used. Application can use it to set custom template. + * Aliases is an array of aliases that can be used instead of the first word in Use. */ - setHelpTemplate(s: string): void - } - interface Command { + aliases: Array /** - * SetVersionTemplate sets version template to be used. Application can use it to set custom template. + * SuggestFor is an array of command names for which this command will be suggested - + * similar to aliases but only suggests. */ - setVersionTemplate(s: string): void - } - interface Command { + suggestFor: Array /** - * SetErrPrefix sets error message prefix to be used. Application can use it to set custom prefix. + * Short is the short description shown in the 'help' output. */ - setErrPrefix(s: string): void - } - interface Command { + short: string /** - * SetGlobalNormalizationFunc sets a normalization function to all flag sets and also to child commands. - * The user should not have a cyclic dependency on commands. + * The group id under which this subcommand is grouped in the 'help' output of its parent. */ - setGlobalNormalizationFunc(n: (f: any, name: string) => any): void - } - interface Command { + groupID: string /** - * OutOrStdout returns output to stdout. + * Long is the long message shown in the 'help ' output. */ - outOrStdout(): io.Writer - } - interface Command { + long: string /** - * OutOrStderr returns output to stderr + * Example is examples of how to use the command. */ - outOrStderr(): io.Writer - } - interface Command { + example: string /** - * ErrOrStderr returns output to stderr + * ValidArgs is list of all valid non-flag arguments that are accepted in shell completions */ - errOrStderr(): io.Writer - } - interface Command { + validArgs: Array /** - * InOrStdin returns input to stdin + * ValidArgsFunction is an optional function that provides valid non-flag arguments for shell completion. + * It is a dynamic version of using ValidArgs. + * Only one of ValidArgs and ValidArgsFunction can be used for a command. */ - inOrStdin(): io.Reader - } - interface Command { + validArgsFunction: CompletionFunc /** - * UsageFunc returns either the function set by SetUsageFunc for this command - * or a parent, or it returns a default usage function. + * Expected arguments */ - usageFunc(): (_arg0: Command) => void - } - interface Command { + args: PositionalArgs /** - * Usage puts out the usage for the command. - * Used when a user provides invalid input. - * Can be defined by user by overriding UsageFunc. + * ArgAliases is List of aliases for ValidArgs. + * These are not suggested to the user in the shell completion, + * but accepted if entered manually. */ - usage(): void - } - interface Command { + argAliases: Array /** - * HelpFunc returns either the function set by SetHelpFunc for this command - * or a parent, or it returns a function with default help behavior. + * BashCompletionFunction is custom bash functions used by the legacy bash autocompletion generator. + * For portability with other shells, it is recommended to instead use ValidArgsFunction */ - helpFunc(): (_arg0: Command, _arg1: Array) => void - } - interface Command { + bashCompletionFunction: string /** - * Help puts out the help for the command. - * Used when a user calls help [command]. - * Can be defined by user by overriding HelpFunc. + * Deprecated defines, if this command is deprecated and should print this string when used. */ - help(): void - } - interface Command { + deprecated: string /** - * UsageString returns usage string. + * Annotations are key/value pairs that can be used by applications to identify or + * group commands or set special options. */ - usageString(): string - } - interface Command { + annotations: _TygojaDict /** - * FlagErrorFunc returns either the function set by SetFlagErrorFunc for this - * command or a parent, or it returns a function which returns the original - * error. + * Version defines the version for this command. If this value is non-empty and the command does not + * define a "version" flag, a "version" boolean flag will be added to the command and, if specified, + * will print content of the "Version" variable. A shorthand "v" flag will also be added if the + * command does not define one. */ - flagErrorFunc(): (_arg0: Command, _arg1: Error) => void - } - interface Command { + version: string /** - * UsagePadding return padding for the usage. + * The *Run functions are executed in the following order: + * ``` + * * PersistentPreRun() + * * PreRun() + * * Run() + * * PostRun() + * * PersistentPostRun() + * ``` + * All functions get the same args, the arguments after the command name. + * The *PreRun and *PostRun functions will only be executed if the Run function of the current + * command has been declared. + * + * PersistentPreRun: children of this command will inherit and execute. */ - usagePadding(): number - } - interface Command { + persistentPreRun: (cmd: Command, args: Array) => void /** - * CommandPathPadding return padding for the command path. + * PersistentPreRunE: PersistentPreRun but returns an error. */ - commandPathPadding(): number - } - interface Command { + persistentPreRunE: (cmd: Command, args: Array) => void /** - * NamePadding returns padding for the name. + * PreRun: children of this command will not inherit. */ - namePadding(): number - } - interface Command { + preRun: (cmd: Command, args: Array) => void /** - * UsageTemplate returns usage template for the command. - * This function is kept for backwards-compatibility reasons. + * PreRunE: PreRun but returns an error. */ - usageTemplate(): string - } - interface Command { + preRunE: (cmd: Command, args: Array) => void /** - * HelpTemplate return help template for the command. - * This function is kept for backwards-compatibility reasons. + * Run: Typically the actual work function. Most commands will only implement this. */ - helpTemplate(): string - } - interface Command { + run: (cmd: Command, args: Array) => void /** - * VersionTemplate return version template for the command. - * This function is kept for backwards-compatibility reasons. + * RunE: Run but returns an error. */ - versionTemplate(): string - } - interface Command { + runE: (cmd: Command, args: Array) => void /** - * ErrPrefix return error message prefix for the command + * PostRun: run after the Run command. */ - errPrefix(): string - } - interface Command { + postRun: (cmd: Command, args: Array) => void /** - * Find the target command given the args and command tree - * Meant to be run on the highest node. Only searches down. + * PostRunE: PostRun but returns an error. */ - find(args: Array): [(Command), Array] - } - interface Command { + postRunE: (cmd: Command, args: Array) => void /** - * Traverse the command tree to find the command, and parse args for - * each parent. + * PersistentPostRun: children of this command will inherit and execute after PostRun. */ - traverse(args: Array): [(Command), Array] - } - interface Command { + persistentPostRun: (cmd: Command, args: Array) => void /** - * SuggestionsFor provides suggestions for the typedName. + * PersistentPostRunE: PersistentPostRun but returns an error. */ - suggestionsFor(typedName: string): Array - } - interface Command { + persistentPostRunE: (cmd: Command, args: Array) => void /** - * VisitParents visits all parents of the command and invokes fn on each parent. + * FParseErrWhitelist flag parse errors to be ignored */ - visitParents(fn: (_arg0: Command) => void): void - } - interface Command { + fParseErrWhitelist: FParseErrWhitelist /** - * Root finds root command. + * CompletionOptions is a set of options to control the handling of shell completion */ - root(): (Command) - } - interface Command { + completionOptions: CompletionOptions /** - * ArgsLenAtDash will return the length of c.Flags().Args at the moment - * when a -- was found during args parsing. + * TraverseChildren parses flags on all parents before executing child command. */ - argsLenAtDash(): number - } - interface Command { + traverseChildren: boolean /** - * ExecuteContext is the same as Execute(), but sets the ctx on the command. - * Retrieve ctx by calling cmd.Context() inside your *Run lifecycle or ValidArgs - * functions. + * Hidden defines, if this command is hidden and should NOT show up in the list of available commands. */ - executeContext(ctx: context.Context): void - } - interface Command { + hidden: boolean /** - * Execute uses the args (os.Args[1:] by default) - * and run through the command tree finding appropriate matches - * for commands and then corresponding flags. + * SilenceErrors is an option to quiet errors down stream. */ - execute(): void - } - interface Command { + silenceErrors: boolean /** - * ExecuteContextC is the same as ExecuteC(), but sets the ctx on the command. - * Retrieve ctx by calling cmd.Context() inside your *Run lifecycle or ValidArgs - * functions. + * SilenceUsage is an option to silence usage when an error occurs. */ - executeContextC(ctx: context.Context): (Command) - } - interface Command { + silenceUsage: boolean /** - * ExecuteC executes the command. + * DisableFlagParsing disables the flag parsing. + * If this is true all flags will be passed to the command as arguments. */ - executeC(): (Command) - } - interface Command { - validateArgs(args: Array): void - } - interface Command { + disableFlagParsing: boolean /** - * ValidateRequiredFlags validates all required flags are present and returns an error otherwise + * DisableAutoGenTag defines, if gen tag ("Auto generated by spf13/cobra...") + * will be printed by generating docs for this command. */ - validateRequiredFlags(): void - } - interface Command { + disableAutoGenTag: boolean /** - * InitDefaultHelpFlag adds default help flag to c. - * It is called automatically by executing the c or by calling help and usage. - * If c already has help flag, it will do nothing. + * DisableFlagsInUseLine will disable the addition of [flags] to the usage + * line of a command when printing help or generating docs */ - initDefaultHelpFlag(): void - } - interface Command { + disableFlagsInUseLine: boolean /** - * InitDefaultVersionFlag adds default version flag to c. - * It is called automatically by executing the c. - * If c already has a version flag, it will do nothing. - * If c.Version is empty, it will do nothing. + * DisableSuggestions disables the suggestions based on Levenshtein distance + * that go along with 'unknown command' messages. */ - initDefaultVersionFlag(): void - } - interface Command { + disableSuggestions: boolean /** - * InitDefaultHelpCmd adds default help command to c. - * It is called automatically by executing the c or by calling help and usage. - * If c already has help command or c has no subcommands, it will do nothing. + * SuggestionsMinimumDistance defines minimum levenshtein distance to display suggestions. + * Must be > 0. */ - initDefaultHelpCmd(): void + suggestionsMinimumDistance: number } interface Command { /** - * ResetCommands delete parent, subcommand and help command from c. + * Context returns underlying command context. If command was executed + * with ExecuteContext or the context was set with SetContext, the + * previously set context will be returned. Otherwise, nil is returned. + * + * Notice that a call to Execute and ExecuteC will replace a nil context of + * a command with a context.Background, so a background context will be + * returned by Context after one of these functions has been called. */ - resetCommands(): void + context(): context.Context } interface Command { /** - * Commands returns a sorted slice of child commands. + * SetContext sets context for the command. This context will be overwritten by + * Command.ExecuteContext or Command.ExecuteContextC. */ - commands(): Array<(Command | undefined)> + setContext(ctx: context.Context): void } interface Command { /** - * AddCommand adds one or more commands to this parent command. + * SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden + * particularly useful when testing. */ - addCommand(...cmds: (Command | undefined)[]): void + setArgs(a: Array): void } interface Command { /** - * Groups returns a slice of child command groups. + * SetOutput sets the destination for usage and error messages. + * If output is nil, os.Stderr is used. + * + * Deprecated: Use SetOut and/or SetErr instead */ - groups(): Array<(Group | undefined)> + setOutput(output: io.Writer): void } interface Command { /** - * AllChildCommandsHaveGroup returns if all subcommands are assigned to a group + * SetOut sets the destination for usage messages. + * If newOut is nil, os.Stdout is used. */ - allChildCommandsHaveGroup(): boolean + setOut(newOut: io.Writer): void } interface Command { /** - * ContainsGroup return if groupID exists in the list of command groups. + * SetErr sets the destination for error messages. + * If newErr is nil, os.Stderr is used. */ - containsGroup(groupID: string): boolean + setErr(newErr: io.Writer): void } interface Command { /** - * AddGroup adds one or more command groups to this parent command. + * SetIn sets the source for input data + * If newIn is nil, os.Stdin is used. */ - addGroup(...groups: (Group | undefined)[]): void + setIn(newIn: io.Reader): void } interface Command { /** - * RemoveCommand removes one or more commands from a parent command. + * SetUsageFunc sets usage function. Usage can be defined by application. */ - removeCommand(...cmds: (Command | undefined)[]): void + setUsageFunc(f: (_arg0: Command) => void): void } interface Command { /** - * Print is a convenience method to Print to the defined output, fallback to Stderr if not set. + * SetUsageTemplate sets usage template. Can be defined by Application. */ - print(...i: { - }[]): void + setUsageTemplate(s: string): void } interface Command { /** - * Println is a convenience method to Println to the defined output, fallback to Stderr if not set. + * SetFlagErrorFunc sets a function to generate an error when flag parsing + * fails. */ - println(...i: { - }[]): void + setFlagErrorFunc(f: (_arg0: Command, _arg1: Error) => void): void } interface Command { /** - * Printf is a convenience method to Printf to the defined output, fallback to Stderr if not set. + * SetHelpFunc sets help function. Can be defined by Application. */ - printf(format: string, ...i: { - }[]): void + setHelpFunc(f: (_arg0: Command, _arg1: Array) => void): void } interface Command { /** - * PrintErr is a convenience method to Print to the defined Err output, fallback to Stderr if not set. + * SetHelpCommand sets help command. */ - printErr(...i: { - }[]): void + setHelpCommand(cmd: Command): void } interface Command { /** - * PrintErrln is a convenience method to Println to the defined Err output, fallback to Stderr if not set. + * SetHelpCommandGroupID sets the group id of the help command. */ - printErrln(...i: { - }[]): void + setHelpCommandGroupID(groupID: string): void } interface Command { /** - * PrintErrf is a convenience method to Printf to the defined Err output, fallback to Stderr if not set. + * SetCompletionCommandGroupID sets the group id of the completion command. */ - printErrf(format: string, ...i: { - }[]): void + setCompletionCommandGroupID(groupID: string): void } interface Command { /** - * CommandPath returns the full path to this command. + * SetHelpTemplate sets help template to be used. Application can use it to set custom template. */ - commandPath(): string + setHelpTemplate(s: string): void } interface Command { /** - * DisplayName returns the name to display in help text. Returns command Name() - * If CommandDisplayNameAnnoation is not set + * SetVersionTemplate sets version template to be used. Application can use it to set custom template. */ - displayName(): string + setVersionTemplate(s: string): void } interface Command { /** - * UseLine puts out the full usage for a given command (including parents). + * SetErrPrefix sets error message prefix to be used. Application can use it to set custom prefix. */ - useLine(): string + setErrPrefix(s: string): void } interface Command { /** - * DebugFlags used to determine which flags have been assigned to which commands - * and which persist. + * SetGlobalNormalizationFunc sets a normalization function to all flag sets and also to child commands. + * The user should not have a cyclic dependency on commands. */ - debugFlags(): void + setGlobalNormalizationFunc(n: (f: any, name: string) => any): void } interface Command { /** - * Name returns the command's name: the first word in the use line. + * OutOrStdout returns output to stdout. */ - name(): string + outOrStdout(): io.Writer } interface Command { /** - * HasAlias determines if a given string is an alias of the command. + * OutOrStderr returns output to stderr */ - hasAlias(s: string): boolean + outOrStderr(): io.Writer } interface Command { /** - * CalledAs returns the command name or alias that was used to invoke - * this command or an empty string if the command has not been called. + * ErrOrStderr returns output to stderr */ - calledAs(): string + errOrStderr(): io.Writer } interface Command { /** - * NameAndAliases returns a list of the command name and all aliases + * InOrStdin returns input to stdin */ - nameAndAliases(): string + inOrStdin(): io.Reader } interface Command { /** - * HasExample determines if the command has example. + * UsageFunc returns either the function set by SetUsageFunc for this command + * or a parent, or it returns a default usage function. */ - hasExample(): boolean + usageFunc(): (_arg0: Command) => void } interface Command { /** - * Runnable determines if the command is itself runnable. + * Usage puts out the usage for the command. + * Used when a user provides invalid input. + * Can be defined by user by overriding UsageFunc. */ - runnable(): boolean + usage(): void } interface Command { /** - * HasSubCommands determines if the command has children commands. + * HelpFunc returns either the function set by SetHelpFunc for this command + * or a parent, or it returns a function with default help behavior. */ - hasSubCommands(): boolean + helpFunc(): (_arg0: Command, _arg1: Array) => void } interface Command { /** - * IsAvailableCommand determines if a command is available as a non-help command - * (this includes all non deprecated/hidden commands). + * Help puts out the help for the command. + * Used when a user calls help [command]. + * Can be defined by user by overriding HelpFunc. */ - isAvailableCommand(): boolean + help(): void } interface Command { /** - * IsAdditionalHelpTopicCommand determines if a command is an additional - * help topic command; additional help topic command is determined by the - * fact that it is NOT runnable/hidden/deprecated, and has no sub commands that - * are runnable/hidden/deprecated. - * Concrete example: https://github.com/spf13/cobra/issues/393#issuecomment-282741924. + * UsageString returns usage string. */ - isAdditionalHelpTopicCommand(): boolean + usageString(): string } interface Command { /** - * HasHelpSubCommands determines if a command has any available 'help' sub commands - * that need to be shown in the usage/help default template under 'additional help - * topics'. + * FlagErrorFunc returns either the function set by SetFlagErrorFunc for this + * command or a parent, or it returns a function which returns the original + * error. */ - hasHelpSubCommands(): boolean + flagErrorFunc(): (_arg0: Command, _arg1: Error) => void } interface Command { /** - * HasAvailableSubCommands determines if a command has available sub commands that - * need to be shown in the usage/help default template under 'available commands'. + * UsagePadding return padding for the usage. */ - hasAvailableSubCommands(): boolean + usagePadding(): number } interface Command { /** - * HasParent determines if the command is a child command. + * CommandPathPadding return padding for the command path. */ - hasParent(): boolean + commandPathPadding(): number } interface Command { /** - * GlobalNormalizationFunc returns the global normalization function or nil if it doesn't exist. + * NamePadding returns padding for the name. */ - globalNormalizationFunc(): (f: any, name: string) => any + namePadding(): number } interface Command { /** - * Flags returns the complete FlagSet that applies - * to this command (local and persistent declared here and by all parents). + * UsageTemplate returns usage template for the command. + * This function is kept for backwards-compatibility reasons. */ - flags(): (any) + usageTemplate(): string } interface Command { /** - * LocalNonPersistentFlags are flags specific to this command which will NOT persist to subcommands. - * This function does not modify the flags of the current command, it's purpose is to return the current state. + * HelpTemplate return help template for the command. + * This function is kept for backwards-compatibility reasons. */ - localNonPersistentFlags(): (any) + helpTemplate(): string } interface Command { /** - * LocalFlags returns the local FlagSet specifically set in the current command. - * This function does not modify the flags of the current command, it's purpose is to return the current state. + * VersionTemplate return version template for the command. + * This function is kept for backwards-compatibility reasons. */ - localFlags(): (any) + versionTemplate(): string } interface Command { /** - * InheritedFlags returns all flags which were inherited from parent commands. - * This function does not modify the flags of the current command, it's purpose is to return the current state. + * ErrPrefix return error message prefix for the command */ - inheritedFlags(): (any) + errPrefix(): string } interface Command { /** - * NonInheritedFlags returns all flags which were not inherited from parent commands. - * This function does not modify the flags of the current command, it's purpose is to return the current state. + * Find the target command given the args and command tree + * Meant to be run on the highest node. Only searches down. */ - nonInheritedFlags(): (any) + find(args: Array): [(Command), Array] } interface Command { /** - * PersistentFlags returns the persistent FlagSet specifically set in the current command. + * Traverse the command tree to find the command, and parse args for + * each parent. */ - persistentFlags(): (any) + traverse(args: Array): [(Command), Array] } interface Command { /** - * ResetFlags deletes all flags from command. + * SuggestionsFor provides suggestions for the typedName. */ - resetFlags(): void + suggestionsFor(typedName: string): Array } interface Command { /** - * HasFlags checks if the command contains any flags (local plus persistent from the entire structure). + * VisitParents visits all parents of the command and invokes fn on each parent. */ - hasFlags(): boolean + visitParents(fn: (_arg0: Command) => void): void } interface Command { /** - * HasPersistentFlags checks if the command contains persistent flags. + * Root finds root command. */ - hasPersistentFlags(): boolean + root(): (Command) } interface Command { /** - * HasLocalFlags checks if the command has flags specifically declared locally. + * ArgsLenAtDash will return the length of c.Flags().Args at the moment + * when a -- was found during args parsing. */ - hasLocalFlags(): boolean + argsLenAtDash(): number } interface Command { /** - * HasInheritedFlags checks if the command has flags inherited from its parent command. + * ExecuteContext is the same as Execute(), but sets the ctx on the command. + * Retrieve ctx by calling cmd.Context() inside your *Run lifecycle or ValidArgs + * functions. */ - hasInheritedFlags(): boolean + executeContext(ctx: context.Context): void } interface Command { /** - * HasAvailableFlags checks if the command contains any flags (local plus persistent from the entire - * structure) which are not hidden or deprecated. + * Execute uses the args (os.Args[1:] by default) + * and run through the command tree finding appropriate matches + * for commands and then corresponding flags. */ - hasAvailableFlags(): boolean + execute(): void } interface Command { /** - * HasAvailablePersistentFlags checks if the command contains persistent flags which are not hidden or deprecated. + * ExecuteContextC is the same as ExecuteC(), but sets the ctx on the command. + * Retrieve ctx by calling cmd.Context() inside your *Run lifecycle or ValidArgs + * functions. */ - hasAvailablePersistentFlags(): boolean + executeContextC(ctx: context.Context): (Command) } interface Command { /** - * HasAvailableLocalFlags checks if the command has flags specifically declared locally which are not hidden - * or deprecated. + * ExecuteC executes the command. */ - hasAvailableLocalFlags(): boolean + executeC(): (Command) } interface Command { - /** - * HasAvailableInheritedFlags checks if the command has flags inherited from its parent command which are - * not hidden or deprecated. - */ - hasAvailableInheritedFlags(): boolean + validateArgs(args: Array): void } interface Command { /** - * Flag climbs up the command tree looking for matching flag. + * ValidateRequiredFlags validates all required flags are present and returns an error otherwise */ - flag(name: string): (any) + validateRequiredFlags(): void } interface Command { /** - * ParseFlags parses persistent flag tree and local flags. + * InitDefaultHelpFlag adds default help flag to c. + * It is called automatically by executing the c or by calling help and usage. + * If c already has help flag, it will do nothing. */ - parseFlags(args: Array): void + initDefaultHelpFlag(): void } interface Command { /** - * Parent returns a commands parent command. + * InitDefaultVersionFlag adds default version flag to c. + * It is called automatically by executing the c. + * If c already has a version flag, it will do nothing. + * If c.Version is empty, it will do nothing. */ - parent(): (Command) + initDefaultVersionFlag(): void } interface Command { /** - * RegisterFlagCompletionFunc should be called to register a function to provide completion for a flag. - * - * You can use pre-defined completion functions such as [FixedCompletions] or [NoFileCompletions], - * or you can define your own. + * InitDefaultHelpCmd adds default help command to c. + * It is called automatically by executing the c or by calling help and usage. + * If c already has help command or c has no subcommands, it will do nothing. */ - registerFlagCompletionFunc(flagName: string, f: CompletionFunc): void + initDefaultHelpCmd(): void } interface Command { /** - * GetFlagCompletionFunc returns the completion function for the given flag of the command, if available. + * ResetCommands delete parent, subcommand and help command from c. */ - getFlagCompletionFunc(flagName: string): [CompletionFunc, boolean] + resetCommands(): void } interface Command { /** - * InitDefaultCompletionCmd adds a default 'completion' command to c. - * This function will do nothing if any of the following is true: - * 1- the feature has been explicitly disabled by the program, - * 2- c has no subcommands (to avoid creating one), - * 3- c already has a 'completion' command provided by the program. + * Commands returns a sorted slice of child commands. */ - initDefaultCompletionCmd(...args: string[]): void + commands(): Array<(Command | undefined)> } interface Command { /** - * GenFishCompletion generates fish completion file and writes to the passed writer. + * AddCommand adds one or more commands to this parent command. */ - genFishCompletion(w: io.Writer, includeDesc: boolean): void + addCommand(...cmds: (Command | undefined)[]): void } interface Command { /** - * GenFishCompletionFile generates fish completion file. + * Groups returns a slice of child command groups. */ - genFishCompletionFile(filename: string, includeDesc: boolean): void + groups(): Array<(Group | undefined)> } interface Command { /** - * MarkFlagsRequiredTogether marks the given flags with annotations so that Cobra errors - * if the command is invoked with a subset (but not all) of the given flags. + * AllChildCommandsHaveGroup returns if all subcommands are assigned to a group */ - markFlagsRequiredTogether(...flagNames: string[]): void + allChildCommandsHaveGroup(): boolean } interface Command { /** - * MarkFlagsOneRequired marks the given flags with annotations so that Cobra errors - * if the command is invoked without at least one flag from the given set of flags. + * ContainsGroup return if groupID exists in the list of command groups. */ - markFlagsOneRequired(...flagNames: string[]): void + containsGroup(groupID: string): boolean } interface Command { /** - * MarkFlagsMutuallyExclusive marks the given flags with annotations so that Cobra errors - * if the command is invoked with more than one flag from the given set of flags. + * AddGroup adds one or more command groups to this parent command. */ - markFlagsMutuallyExclusive(...flagNames: string[]): void + addGroup(...groups: (Group | undefined)[]): void } interface Command { /** - * ValidateFlagGroups validates the mutuallyExclusive/oneRequired/requiredAsGroup logic and returns the - * first error encountered. + * RemoveCommand removes one or more commands from a parent command. */ - validateFlagGroups(): void + removeCommand(...cmds: (Command | undefined)[]): void } interface Command { /** - * GenPowerShellCompletionFile generates powershell completion file without descriptions. + * Print is a convenience method to Print to the defined output, fallback to Stderr if not set. */ - genPowerShellCompletionFile(filename: string): void + print(...i: { + }[]): void } interface Command { /** - * GenPowerShellCompletion generates powershell completion file without descriptions - * and writes it to the passed writer. + * Println is a convenience method to Println to the defined output, fallback to Stderr if not set. */ - genPowerShellCompletion(w: io.Writer): void + println(...i: { + }[]): void } interface Command { /** - * GenPowerShellCompletionFileWithDesc generates powershell completion file with descriptions. + * Printf is a convenience method to Printf to the defined output, fallback to Stderr if not set. */ - genPowerShellCompletionFileWithDesc(filename: string): void + printf(format: string, ...i: { + }[]): void } interface Command { /** - * GenPowerShellCompletionWithDesc generates powershell completion file with descriptions - * and writes it to the passed writer. + * PrintErr is a convenience method to Print to the defined Err output, fallback to Stderr if not set. */ - genPowerShellCompletionWithDesc(w: io.Writer): void + printErr(...i: { + }[]): void } interface Command { /** - * MarkFlagRequired instructs the various shell completion implementations to - * prioritize the named flag when performing completion, - * and causes your command to report an error if invoked without the flag. + * PrintErrln is a convenience method to Println to the defined Err output, fallback to Stderr if not set. */ - markFlagRequired(name: string): void + printErrln(...i: { + }[]): void } interface Command { /** - * MarkPersistentFlagRequired instructs the various shell completion implementations to - * prioritize the named persistent flag when performing completion, - * and causes your command to report an error if invoked without the flag. + * PrintErrf is a convenience method to Printf to the defined Err output, fallback to Stderr if not set. */ - markPersistentFlagRequired(name: string): void + printErrf(format: string, ...i: { + }[]): void } interface Command { /** - * MarkFlagFilename instructs the various shell completion implementations to - * limit completions for the named flag to the specified file extensions. + * CommandPath returns the full path to this command. */ - markFlagFilename(name: string, ...extensions: string[]): void + commandPath(): string } interface Command { /** - * MarkFlagCustom adds the BashCompCustom annotation to the named flag, if it exists. - * The bash completion script will call the bash function f for the flag. - * - * This will only work for bash completion. - * It is recommended to instead use c.RegisterFlagCompletionFunc(...) which allows - * to register a Go function which will work across all shells. + * DisplayName returns the name to display in help text. Returns command Name() + * If CommandDisplayNameAnnoation is not set */ - markFlagCustom(name: string, f: string): void + displayName(): string } interface Command { /** - * MarkPersistentFlagFilename instructs the various shell completion - * implementations to limit completions for the named persistent flag to the - * specified file extensions. + * UseLine puts out the full usage for a given command (including parents). */ - markPersistentFlagFilename(name: string, ...extensions: string[]): void + useLine(): string } interface Command { /** - * MarkFlagDirname instructs the various shell completion implementations to - * limit completions for the named flag to directory names. + * DebugFlags used to determine which flags have been assigned to which commands + * and which persist. */ - markFlagDirname(name: string): void + debugFlags(): void } interface Command { /** - * MarkPersistentFlagDirname instructs the various shell completion - * implementations to limit completions for the named persistent flag to - * directory names. + * Name returns the command's name: the first word in the use line. */ - markPersistentFlagDirname(name: string): void + name(): string } interface Command { /** - * GenZshCompletionFile generates zsh completion file including descriptions. + * HasAlias determines if a given string is an alias of the command. */ - genZshCompletionFile(filename: string): void + hasAlias(s: string): boolean } interface Command { /** - * GenZshCompletion generates zsh completion file including descriptions - * and writes it to the passed writer. + * CalledAs returns the command name or alias that was used to invoke + * this command or an empty string if the command has not been called. */ - genZshCompletion(w: io.Writer): void + calledAs(): string } interface Command { /** - * GenZshCompletionFileNoDesc generates zsh completion file without descriptions. + * NameAndAliases returns a list of the command name and all aliases */ - genZshCompletionFileNoDesc(filename: string): void + nameAndAliases(): string } interface Command { /** - * GenZshCompletionNoDesc generates zsh completion file without descriptions - * and writes it to the passed writer. + * HasExample determines if the command has example. */ - genZshCompletionNoDesc(w: io.Writer): void + hasExample(): boolean } interface Command { /** - * MarkZshCompPositionalArgumentFile only worked for zsh and its behavior was - * not consistent with Bash completion. It has therefore been disabled. - * Instead, when no other completion is specified, file completion is done by - * default for every argument. One can disable file completion on a per-argument - * basis by using ValidArgsFunction and ShellCompDirectiveNoFileComp. - * To achieve file extension filtering, one can use ValidArgsFunction and - * ShellCompDirectiveFilterFileExt. - * - * Deprecated + * Runnable determines if the command is itself runnable. */ - markZshCompPositionalArgumentFile(argPosition: number, ...patterns: string[]): void + runnable(): boolean } interface Command { /** - * MarkZshCompPositionalArgumentWords only worked for zsh. It has therefore - * been disabled. - * To achieve the same behavior across all shells, one can use - * ValidArgs (for the first argument only) or ValidArgsFunction for - * any argument (can include the first one also). - * - * Deprecated + * HasSubCommands determines if the command has children commands. */ - markZshCompPositionalArgumentWords(argPosition: number, ...words: string[]): void - } -} - -namespace sync { - // @ts-ignore - import isync = sync - /** - * A Locker represents an object that can be locked and unlocked. - */ - interface Locker { - [key:string]: any; - lock(): void - unlock(): void + hasSubCommands(): boolean } - // @ts-ignore - import rtatomic = atomic -} - -namespace io { - /** - * WriteCloser is the interface that groups the basic Write and Close methods. - */ - interface WriteCloser { - [key:string]: any; + interface Command { + /** + * IsAvailableCommand determines if a command is available as a non-help command + * (this includes all non deprecated/hidden commands). + */ + isAvailableCommand(): boolean } -} - -namespace syscall { - // @ts-ignore - import errpkg = errors - /** - * SysProcIDMap holds Container ID to Host ID mappings used for User Namespaces in Linux. - * See user_namespaces(7). - * - * Note that User Namespaces are not available on a number of popular Linux - * versions (due to security issues), or are available but subject to AppArmor - * restrictions like in Ubuntu 24.04. - */ - interface SysProcIDMap { - containerID: number // Container ID. - hostID: number // Host ID. - size: number // Size. + interface Command { + /** + * IsAdditionalHelpTopicCommand determines if a command is an additional + * help topic command; additional help topic command is determined by the + * fact that it is NOT runnable/hidden/deprecated, and has no sub commands that + * are runnable/hidden/deprecated. + * Concrete example: https://github.com/spf13/cobra/issues/393#issuecomment-282741924. + */ + isAdditionalHelpTopicCommand(): boolean } - // @ts-ignore - import errorspkg = errors - /** - * Credential holds user and group identities to be assumed - * by a child process started by [StartProcess]. - */ - interface Credential { - uid: number // User ID. - gid: number // Group ID. - groups: Array // Supplementary group IDs. - noSetGroups: boolean // If true, don't set supplementary groups + interface Command { + /** + * HasHelpSubCommands determines if a command has any available 'help' sub commands + * that need to be shown in the usage/help default template under 'additional help + * topics'. + */ + hasHelpSubCommands(): boolean } - /** - * A Signal is a number describing a process signal. - * It implements the [os.Signal] interface. - */ - interface Signal extends Number{} - interface Signal { - signal(): void + interface Command { + /** + * HasAvailableSubCommands determines if a command has available sub commands that + * need to be shown in the usage/help default template under 'available commands'. + */ + hasAvailableSubCommands(): boolean } - interface Signal { - string(): string + interface Command { + /** + * HasParent determines if the command is a child command. + */ + hasParent(): boolean } -} - -namespace time { - /** - * A Month specifies a month of the year (January = 1, ...). - */ - interface Month extends Number{} - interface Month { + interface Command { /** - * String returns the English name of the month ("January", "February", ...). + * GlobalNormalizationFunc returns the global normalization function or nil if it doesn't exist. */ - string(): string + globalNormalizationFunc(): (f: any, name: string) => any } - /** - * A Weekday specifies a day of the week (Sunday = 0, ...). - */ - interface Weekday extends Number{} - interface Weekday { + interface Command { /** - * String returns the English name of the day ("Sunday", "Monday", ...). + * Flags returns the complete FlagSet that applies + * to this command (local and persistent declared here and by all parents). */ - string(): string + flags(): (any) } - /** - * A Location maps time instants to the zone in use at that time. - * Typically, the Location represents the collection of time offsets - * in use in a geographical area. For many Locations the time offset varies - * depending on whether daylight savings time is in use at the time instant. - * - * Location is used to provide a time zone in a printed Time value and for - * calculations involving intervals that may cross daylight savings time - * boundaries. - */ - interface Location { + interface Command { + /** + * LocalNonPersistentFlags are flags specific to this command which will NOT persist to subcommands. + * This function does not modify the flags of the current command, it's purpose is to return the current state. + */ + localNonPersistentFlags(): (any) } - interface Location { + interface Command { /** - * String returns a descriptive name for the time zone information, - * corresponding to the name argument to [LoadLocation] or [FixedZone]. + * LocalFlags returns the local FlagSet specifically set in the current command. + * This function does not modify the flags of the current command, it's purpose is to return the current state. */ - string(): string + localFlags(): (any) } -} - -namespace fs { -} - -namespace store { -} - -namespace bufio { - /** - * Reader implements buffering for an io.Reader object. - * A new Reader is created by calling [NewReader] or [NewReaderSize]; - * alternatively the zero value of a Reader may be used after calling [Reader.Reset] - * on it. - */ - interface Reader { + interface Command { + /** + * InheritedFlags returns all flags which were inherited from parent commands. + * This function does not modify the flags of the current command, it's purpose is to return the current state. + */ + inheritedFlags(): (any) } - interface Reader { + interface Command { /** - * Size returns the size of the underlying buffer in bytes. + * NonInheritedFlags returns all flags which were not inherited from parent commands. + * This function does not modify the flags of the current command, it's purpose is to return the current state. */ - size(): number + nonInheritedFlags(): (any) } - interface Reader { + interface Command { /** - * Reset discards any buffered data, resets all state, and switches - * the buffered reader to read from r. - * Calling Reset on the zero value of [Reader] initializes the internal buffer - * to the default size. - * Calling b.Reset(b) (that is, resetting a [Reader] to itself) does nothing. + * PersistentFlags returns the persistent FlagSet specifically set in the current command. */ - reset(r: io.Reader): void + persistentFlags(): (any) } - interface Reader { + interface Command { /** - * Peek returns the next n bytes without advancing the reader. The bytes stop - * being valid at the next read call. If necessary, Peek will read more bytes - * into the buffer in order to make n bytes available. If Peek returns fewer - * than n bytes, it also returns an error explaining why the read is short. - * The error is [ErrBufferFull] if n is larger than b's buffer size. - * - * Calling Peek prevents a [Reader.UnreadByte] or [Reader.UnreadRune] call from succeeding - * until the next read operation. + * ResetFlags deletes all flags from command. */ - peek(n: number): string|Array + resetFlags(): void } - interface Reader { + interface Command { /** - * Discard skips the next n bytes, returning the number of bytes discarded. - * - * If Discard skips fewer than n bytes, it also returns an error. - * If 0 <= n <= b.Buffered(), Discard is guaranteed to succeed without - * reading from the underlying io.Reader. + * HasFlags checks if the command contains any flags (local plus persistent from the entire structure). */ - discard(n: number): number + hasFlags(): boolean } - interface Reader { + interface Command { /** - * Read reads data into p. - * It returns the number of bytes read into p. - * The bytes are taken from at most one Read on the underlying [Reader], - * hence n may be less than len(p). - * To read exactly len(p) bytes, use io.ReadFull(b, p). - * If the underlying [Reader] can return a non-zero count with io.EOF, - * then this Read method can do so as well; see the [io.Reader] docs. + * HasPersistentFlags checks if the command contains persistent flags. */ - read(p: string|Array): number + hasPersistentFlags(): boolean } - interface Reader { + interface Command { /** - * ReadByte reads and returns a single byte. - * If no byte is available, returns an error. + * HasLocalFlags checks if the command has flags specifically declared locally. */ - readByte(): number + hasLocalFlags(): boolean } - interface Reader { + interface Command { /** - * UnreadByte unreads the last byte. Only the most recently read byte can be unread. - * - * UnreadByte returns an error if the most recent method called on the - * [Reader] was not a read operation. Notably, [Reader.Peek], [Reader.Discard], and [Reader.WriteTo] are not - * considered read operations. + * HasInheritedFlags checks if the command has flags inherited from its parent command. */ - unreadByte(): void + hasInheritedFlags(): boolean } - interface Reader { + interface Command { /** - * ReadRune reads a single UTF-8 encoded Unicode character and returns the - * rune and its size in bytes. If the encoded rune is invalid, it consumes one byte - * and returns unicode.ReplacementChar (U+FFFD) with a size of 1. + * HasAvailableFlags checks if the command contains any flags (local plus persistent from the entire + * structure) which are not hidden or deprecated. */ - readRune(): [number, number] + hasAvailableFlags(): boolean } - interface Reader { + interface Command { /** - * UnreadRune unreads the last rune. If the most recent method called on - * the [Reader] was not a [Reader.ReadRune], [Reader.UnreadRune] returns an error. (In this - * regard it is stricter than [Reader.UnreadByte], which will unread the last byte - * from any read operation.) + * HasAvailablePersistentFlags checks if the command contains persistent flags which are not hidden or deprecated. */ - unreadRune(): void + hasAvailablePersistentFlags(): boolean } - interface Reader { + interface Command { /** - * Buffered returns the number of bytes that can be read from the current buffer. + * HasAvailableLocalFlags checks if the command has flags specifically declared locally which are not hidden + * or deprecated. */ - buffered(): number + hasAvailableLocalFlags(): boolean } - interface Reader { + interface Command { /** - * ReadSlice reads until the first occurrence of delim in the input, - * returning a slice pointing at the bytes in the buffer. - * The bytes stop being valid at the next read. - * If ReadSlice encounters an error before finding a delimiter, - * it returns all the data in the buffer and the error itself (often io.EOF). - * ReadSlice fails with error [ErrBufferFull] if the buffer fills without a delim. - * Because the data returned from ReadSlice will be overwritten - * by the next I/O operation, most clients should use - * [Reader.ReadBytes] or ReadString instead. - * ReadSlice returns err != nil if and only if line does not end in delim. + * HasAvailableInheritedFlags checks if the command has flags inherited from its parent command which are + * not hidden or deprecated. + */ + hasAvailableInheritedFlags(): boolean + } + interface Command { + /** + * Flag climbs up the command tree looking for matching flag. + */ + flag(name: string): (any) + } + interface Command { + /** + * ParseFlags parses persistent flag tree and local flags. */ - readSlice(delim: number): string|Array + parseFlags(args: Array): void } - interface Reader { + interface Command { /** - * ReadLine is a low-level line-reading primitive. Most callers should use - * [Reader.ReadBytes]('\n') or [Reader.ReadString]('\n') instead or use a [Scanner]. - * - * ReadLine tries to return a single line, not including the end-of-line bytes. - * If the line was too long for the buffer then isPrefix is set and the - * beginning of the line is returned. The rest of the line will be returned - * from future calls. isPrefix will be false when returning the last fragment - * of the line. The returned buffer is only valid until the next call to - * ReadLine. ReadLine either returns a non-nil line or it returns an error, - * never both. - * - * The text returned from ReadLine does not include the line end ("\r\n" or "\n"). - * No indication or error is given if the input ends without a final line end. - * Calling [Reader.UnreadByte] after ReadLine will always unread the last byte read - * (possibly a character belonging to the line end) even if that byte is not - * part of the line returned by ReadLine. + * Parent returns a commands parent command. */ - readLine(): [string|Array, boolean] + parent(): (Command) } - interface Reader { + interface Command { /** - * ReadBytes reads until the first occurrence of delim in the input, - * returning a slice containing the data up to and including the delimiter. - * If ReadBytes encounters an error before finding a delimiter, - * it returns the data read before the error and the error itself (often io.EOF). - * ReadBytes returns err != nil if and only if the returned data does not end in - * delim. - * For simple uses, a Scanner may be more convenient. + * RegisterFlagCompletionFunc should be called to register a function to provide completion for a flag. + * + * You can use pre-defined completion functions such as [FixedCompletions] or [NoFileCompletions], + * or you can define your own. */ - readBytes(delim: number): string|Array + registerFlagCompletionFunc(flagName: string, f: CompletionFunc): void } - interface Reader { + interface Command { /** - * ReadString reads until the first occurrence of delim in the input, - * returning a string containing the data up to and including the delimiter. - * If ReadString encounters an error before finding a delimiter, - * it returns the data read before the error and the error itself (often io.EOF). - * ReadString returns err != nil if and only if the returned data does not end in - * delim. - * For simple uses, a Scanner may be more convenient. + * GetFlagCompletionFunc returns the completion function for the given flag of the command, if available. */ - readString(delim: number): string + getFlagCompletionFunc(flagName: string): [CompletionFunc, boolean] } - interface Reader { + interface Command { /** - * WriteTo implements io.WriterTo. - * This may make multiple calls to the [Reader.Read] method of the underlying [Reader]. - * If the underlying reader supports the [Reader.WriteTo] method, - * this calls the underlying [Reader.WriteTo] without buffering. + * InitDefaultCompletionCmd adds a default 'completion' command to c. + * This function will do nothing if any of the following is true: + * 1- the feature has been explicitly disabled by the program, + * 2- c has no subcommands (to avoid creating one), + * 3- c already has a 'completion' command provided by the program. */ - writeTo(w: io.Writer): number + initDefaultCompletionCmd(...args: string[]): void } - /** - * Writer implements buffering for an [io.Writer] object. - * If an error occurs writing to a [Writer], no more data will be - * accepted and all subsequent writes, and [Writer.Flush], will return the error. - * After all data has been written, the client should call the - * [Writer.Flush] method to guarantee all data has been forwarded to - * the underlying [io.Writer]. - */ - interface Writer { + interface Command { + /** + * GenFishCompletion generates fish completion file and writes to the passed writer. + */ + genFishCompletion(w: io.Writer, includeDesc: boolean): void } - interface Writer { + interface Command { /** - * Size returns the size of the underlying buffer in bytes. + * GenFishCompletionFile generates fish completion file. */ - size(): number + genFishCompletionFile(filename: string, includeDesc: boolean): void } - interface Writer { + interface Command { /** - * Reset discards any unflushed buffered data, clears any error, and - * resets b to write its output to w. - * Calling Reset on the zero value of [Writer] initializes the internal buffer - * to the default size. - * Calling w.Reset(w) (that is, resetting a [Writer] to itself) does nothing. + * MarkFlagsRequiredTogether marks the given flags with annotations so that Cobra errors + * if the command is invoked with a subset (but not all) of the given flags. */ - reset(w: io.Writer): void + markFlagsRequiredTogether(...flagNames: string[]): void } - interface Writer { + interface Command { /** - * Flush writes any buffered data to the underlying [io.Writer]. + * MarkFlagsOneRequired marks the given flags with annotations so that Cobra errors + * if the command is invoked without at least one flag from the given set of flags. */ - flush(): void + markFlagsOneRequired(...flagNames: string[]): void } - interface Writer { + interface Command { /** - * Available returns how many bytes are unused in the buffer. + * MarkFlagsMutuallyExclusive marks the given flags with annotations so that Cobra errors + * if the command is invoked with more than one flag from the given set of flags. */ - available(): number + markFlagsMutuallyExclusive(...flagNames: string[]): void } - interface Writer { + interface Command { /** - * AvailableBuffer returns an empty buffer with b.Available() capacity. - * This buffer is intended to be appended to and - * passed to an immediately succeeding [Writer.Write] call. - * The buffer is only valid until the next write operation on b. + * ValidateFlagGroups validates the mutuallyExclusive/oneRequired/requiredAsGroup logic and returns the + * first error encountered. */ - availableBuffer(): string|Array + validateFlagGroups(): void } - interface Writer { + interface Command { /** - * Buffered returns the number of bytes that have been written into the current buffer. + * GenPowerShellCompletionFile generates powershell completion file without descriptions. */ - buffered(): number + genPowerShellCompletionFile(filename: string): void } - interface Writer { + interface Command { /** - * Write writes the contents of p into the buffer. - * It returns the number of bytes written. - * If nn < len(p), it also returns an error explaining - * why the write is short. + * GenPowerShellCompletion generates powershell completion file without descriptions + * and writes it to the passed writer. */ - write(p: string|Array): number + genPowerShellCompletion(w: io.Writer): void } - interface Writer { + interface Command { /** - * WriteByte writes a single byte. + * GenPowerShellCompletionFileWithDesc generates powershell completion file with descriptions. */ - writeByte(c: number): void + genPowerShellCompletionFileWithDesc(filename: string): void } - interface Writer { + interface Command { /** - * WriteRune writes a single Unicode code point, returning - * the number of bytes written and any error. + * GenPowerShellCompletionWithDesc generates powershell completion file with descriptions + * and writes it to the passed writer. */ - writeRune(r: number): number + genPowerShellCompletionWithDesc(w: io.Writer): void } - interface Writer { + interface Command { /** - * WriteString writes a string. - * It returns the number of bytes written. - * If the count is less than len(s), it also returns an error explaining - * why the write is short. + * MarkFlagRequired instructs the various shell completion implementations to + * prioritize the named flag when performing completion, + * and causes your command to report an error if invoked without the flag. */ - writeString(s: string): number + markFlagRequired(name: string): void } - interface Writer { + interface Command { /** - * ReadFrom implements [io.ReaderFrom]. If the underlying writer - * supports the ReadFrom method, this calls the underlying ReadFrom. - * If there is buffered data and an underlying ReadFrom, this fills - * the buffer and writes it before calling ReadFrom. + * MarkPersistentFlagRequired instructs the various shell completion implementations to + * prioritize the named persistent flag when performing completion, + * and causes your command to report an error if invoked without the flag. */ - readFrom(r: io.Reader): number + markPersistentFlagRequired(name: string): void } -} - -namespace context { -} - -namespace sql { - /** - * IsolationLevel is the transaction isolation level used in [TxOptions]. - */ - interface IsolationLevel extends Number{} - interface IsolationLevel { + interface Command { /** - * String returns the name of the transaction isolation level. + * MarkFlagFilename instructs the various shell completion implementations to + * limit completions for the named flag to the specified file extensions. */ - string(): string + markFlagFilename(name: string, ...extensions: string[]): void } - /** - * DBStats contains database statistics. - */ - interface DBStats { - maxOpenConnections: number // Maximum number of open connections to the database. + interface Command { /** - * Pool Status + * MarkFlagCustom adds the BashCompCustom annotation to the named flag, if it exists. + * The bash completion script will call the bash function f for the flag. + * + * This will only work for bash completion. + * It is recommended to instead use c.RegisterFlagCompletionFunc(...) which allows + * to register a Go function which will work across all shells. */ - openConnections: number // The number of established connections both in use and idle. - inUse: number // The number of connections currently in use. - idle: number // The number of idle connections. + markFlagCustom(name: string, f: string): void + } + interface Command { /** - * Counters + * MarkPersistentFlagFilename instructs the various shell completion + * implementations to limit completions for the named persistent flag to the + * specified file extensions. */ - waitCount: number // The total number of connections waited for. - waitDuration: time.Duration // The total time blocked waiting for a new connection. - maxIdleClosed: number // The total number of connections closed due to SetMaxIdleConns. - maxIdleTimeClosed: number // The total number of connections closed due to SetConnMaxIdleTime. - maxLifetimeClosed: number // The total number of connections closed due to SetConnMaxLifetime. + markPersistentFlagFilename(name: string, ...extensions: string[]): void } - /** - * Conn represents a single database connection rather than a pool of database - * connections. Prefer running queries from [DB] unless there is a specific - * need for a continuous single database connection. - * - * A Conn must call [Conn.Close] to return the connection to the database pool - * and may do so concurrently with a running query. - * - * After a call to [Conn.Close], all operations on the - * connection fail with [ErrConnDone]. - */ - interface Conn { + interface Command { + /** + * MarkFlagDirname instructs the various shell completion implementations to + * limit completions for the named flag to directory names. + */ + markFlagDirname(name: string): void } - interface Conn { + interface Command { /** - * PingContext verifies the connection to the database is still alive. + * MarkPersistentFlagDirname instructs the various shell completion + * implementations to limit completions for the named persistent flag to + * directory names. */ - pingContext(ctx: context.Context): void + markPersistentFlagDirname(name: string): void } - interface Conn { + interface Command { /** - * ExecContext executes a query without returning any rows. - * The args are for any placeholder parameters in the query. + * GenZshCompletionFile generates zsh completion file including descriptions. */ - execContext(ctx: context.Context, query: string, ...args: any[]): Result + genZshCompletionFile(filename: string): void } - interface Conn { + interface Command { /** - * QueryContext executes a query that returns rows, typically a SELECT. - * The args are for any placeholder parameters in the query. + * GenZshCompletion generates zsh completion file including descriptions + * and writes it to the passed writer. */ - queryContext(ctx: context.Context, query: string, ...args: any[]): (Rows) + genZshCompletion(w: io.Writer): void } - interface Conn { + interface Command { /** - * QueryRowContext executes a query that is expected to return at most one row. - * QueryRowContext always returns a non-nil value. Errors are deferred until - * the [*Row.Scan] method is called. - * If the query selects no rows, the [*Row.Scan] will return [ErrNoRows]. - * Otherwise, the [*Row.Scan] scans the first selected row and discards - * the rest. + * GenZshCompletionFileNoDesc generates zsh completion file without descriptions. */ - queryRowContext(ctx: context.Context, query: string, ...args: any[]): (Row) + genZshCompletionFileNoDesc(filename: string): void } - interface Conn { + interface Command { /** - * PrepareContext creates a prepared statement for later queries or executions. - * Multiple queries or executions may be run concurrently from the - * returned statement. - * The caller must call the statement's [*Stmt.Close] method - * when the statement is no longer needed. - * - * The provided context is used for the preparation of the statement, not for the - * execution of the statement. + * GenZshCompletionNoDesc generates zsh completion file without descriptions + * and writes it to the passed writer. */ - prepareContext(ctx: context.Context, query: string): (Stmt) + genZshCompletionNoDesc(w: io.Writer): void } - interface Conn { + interface Command { /** - * Raw executes f exposing the underlying driver connection for the - * duration of f. The driverConn must not be used outside of f. + * MarkZshCompPositionalArgumentFile only worked for zsh and its behavior was + * not consistent with Bash completion. It has therefore been disabled. + * Instead, when no other completion is specified, file completion is done by + * default for every argument. One can disable file completion on a per-argument + * basis by using ValidArgsFunction and ShellCompDirectiveNoFileComp. + * To achieve file extension filtering, one can use ValidArgsFunction and + * ShellCompDirectiveFilterFileExt. * - * Once f returns and err is not [driver.ErrBadConn], the [Conn] will continue to be usable - * until [Conn.Close] is called. + * Deprecated */ - raw(f: (driverConn: any) => void): void + markZshCompPositionalArgumentFile(argPosition: number, ...patterns: string[]): void } - interface Conn { + interface Command { /** - * BeginTx starts a transaction. - * - * The provided context is used until the transaction is committed or rolled back. - * If the context is canceled, the sql package will roll back - * the transaction. [Tx.Commit] will return an error if the context provided to - * BeginTx is canceled. + * MarkZshCompPositionalArgumentWords only worked for zsh. It has therefore + * been disabled. + * To achieve the same behavior across all shells, one can use + * ValidArgs (for the first argument only) or ValidArgsFunction for + * any argument (can include the first one also). * - * The provided [TxOptions] is optional and may be nil if defaults should be used. - * If a non-default isolation level is used that the driver doesn't support, - * an error will be returned. + * Deprecated */ - beginTx(ctx: context.Context, opts: TxOptions): (Tx) + markZshCompPositionalArgumentWords(argPosition: number, ...words: string[]): void } - interface Conn { +} + +namespace mailer { + /** + * Message defines a generic email message struct. + */ + interface Message { + from: { address: string; name?: string; } + to: Array<{ address: string; name?: string; }> + bcc: Array<{ address: string; name?: string; }> + cc: Array<{ address: string; name?: string; }> + subject: string + html: string + text: string + headers: _TygojaDict + attachments: _TygojaDict + inlineAttachments: _TygojaDict + } + /** + * Mailer defines a base mail client interface. + */ + interface Mailer { + [key:string]: any; /** - * Close returns the connection to the connection pool. - * All operations after a Close will return with [ErrConnDone]. - * Close is safe to call concurrently with other operations and will - * block until all other operations finish. It may be useful to first - * cancel any used context and then call close directly after. + * Send sends an email with the provided Message. */ - close(): void + send(message: Message): void } +} + +namespace sync { + // @ts-ignore + import isync = sync /** - * ColumnType contains the name and type of a column. + * A Locker represents an object that can be locked and unlocked. */ - interface ColumnType { + interface Locker { + [key:string]: any; + lock(): void + unlock(): void } - interface ColumnType { - /** - * Name returns the name or alias of the column. - */ - name(): string + // @ts-ignore + import rtatomic = atomic +} + +namespace syscall { + // @ts-ignore + import errpkg = errors + /** + * SysProcIDMap holds Container ID to Host ID mappings used for User Namespaces in Linux. + * See user_namespaces(7). + * + * Note that User Namespaces are not available on a number of popular Linux + * versions (due to security issues), or are available but subject to AppArmor + * restrictions like in Ubuntu 24.04. + */ + interface SysProcIDMap { + containerID: number // Container ID. + hostID: number // Host ID. + size: number // Size. } - interface ColumnType { - /** - * Length returns the column type length for variable length column types such - * as text and binary field types. If the type length is unbounded the value will - * be [math.MaxInt64] (any database limits will still apply). - * If the column type is not variable length, such as an int, or if not supported - * by the driver ok is false. - */ - length(): [number, boolean] + // @ts-ignore + import errorspkg = errors + /** + * Credential holds user and group identities to be assumed + * by a child process started by [StartProcess]. + */ + interface Credential { + uid: number // User ID. + gid: number // Group ID. + groups: Array // Supplementary group IDs. + noSetGroups: boolean // If true, don't set supplementary groups } - interface ColumnType { - /** - * DecimalSize returns the scale and precision of a decimal type. - * If not applicable or if not supported ok is false. - */ - decimalSize(): [number, number, boolean] + /** + * A Signal is a number describing a process signal. + * It implements the [os.Signal] interface. + */ + interface Signal extends Number{} + interface Signal { + signal(): void } - interface ColumnType { - /** - * ScanType returns a Go type suitable for scanning into using [Rows.Scan]. - * If a driver does not support this property ScanType will return - * the type of an empty interface. - */ - scanType(): any + interface Signal { + string(): string } - interface ColumnType { +} + +namespace time { + /** + * A Month specifies a month of the year (January = 1, ...). + */ + interface Month extends Number{} + interface Month { /** - * Nullable reports whether the column may be null. - * If a driver does not support this property ok will be false. + * String returns the English name of the month ("January", "February", ...). */ - nullable(): [boolean, boolean] + string(): string } - interface ColumnType { + /** + * A Weekday specifies a day of the week (Sunday = 0, ...). + */ + interface Weekday extends Number{} + interface Weekday { /** - * DatabaseTypeName returns the database system name of the column type. If an empty - * string is returned, then the driver type name is not supported. - * Consult your driver documentation for a list of driver data types. [ColumnType.Length] specifiers - * are not included. - * Common type names include "VARCHAR", "TEXT", "NVARCHAR", "DECIMAL", "BOOL", - * "INT", and "BIGINT". + * String returns the English name of the day ("Sunday", "Monday", ...). */ - databaseTypeName(): string + string(): string } /** - * Row is the result of calling [DB.QueryRow] to select a single row. + * A Location maps time instants to the zone in use at that time. + * Typically, the Location represents the collection of time offsets + * in use in a geographical area. For many Locations the time offset varies + * depending on whether daylight savings time is in use at the time instant. + * + * Location is used to provide a time zone in a printed Time value and for + * calculations involving intervals that may cross daylight savings time + * boundaries. */ - interface Row { + interface Location { } - interface Row { + interface Location { /** - * Scan copies the columns from the matched row into the values - * pointed at by dest. See the documentation on [Rows.Scan] for details. - * If more than one row matches the query, - * Scan uses the first row and discards the rest. If no row matches - * the query, Scan returns [ErrNoRows]. + * String returns a descriptive name for the time zone information, + * corresponding to the name argument to [LoadLocation] or [FixedZone]. */ - scan(...dest: any[]): void + string(): string } - interface Row { - /** - * Err provides a way for wrapping packages to check for - * query errors without calling [Row.Scan]. - * Err returns the error, if any, that was encountered while running the query. - * If this error is not nil, this error will also be returned from [Row.Scan]. - */ - err(): void +} + +namespace context { +} + +namespace io { + /** + * WriteCloser is the interface that groups the basic Write and Close methods. + */ + interface WriteCloser { + [key:string]: any; + } +} + +namespace fs { +} + +namespace net { + /** + * Addr represents a network end point address. + * + * The two methods [Addr.Network] and [Addr.String] conventionally return strings + * that can be passed as the arguments to [Dial], but the exact form + * and meaning of the strings is up to the implementation. + */ + interface Addr { + [key:string]: any; + network(): string // name of the network (for example, "tcp", "udp") + string(): string // string form of address (for example, "192.0.2.1:25", "[2001:db8::1]:80") } + // @ts-ignore + import _cgopackage = cgo } /** @@ -23079,212 +22631,459 @@ namespace url { * In general, code should call EscapedPath instead of * reading u.RawPath directly. */ - escapedPath(): string + escapedPath(): string + } + interface URL { + /** + * EscapedFragment returns the escaped form of u.Fragment. + * In general there are multiple possible escaped forms of any fragment. + * EscapedFragment returns u.RawFragment when it is a valid escaping of u.Fragment. + * Otherwise EscapedFragment ignores u.RawFragment and computes an escaped + * form on its own. + * The [URL.String] method uses EscapedFragment to construct its result. + * In general, code should call EscapedFragment instead of + * reading u.RawFragment directly. + */ + escapedFragment(): string + } + interface URL { + /** + * String reassembles the [URL] into a valid URL string. + * The general form of the result is one of: + * + * ``` + * scheme:opaque?query#fragment + * scheme://userinfo@host/path?query#fragment + * ``` + * + * If u.Opaque is non-empty, String uses the first form; + * otherwise it uses the second form. + * Any non-ASCII characters in host are escaped. + * To obtain the path, String uses u.EscapedPath(). + * + * In the second form, the following rules apply: + * ``` + * - if u.Scheme is empty, scheme: is omitted. + * - if u.User is nil, userinfo@ is omitted. + * - if u.Host is empty, host/ is omitted. + * - if u.Scheme and u.Host are empty and u.User is nil, + * the entire scheme://userinfo@host/ is omitted. + * - if u.Host is non-empty and u.Path begins with a /, + * the form host/path does not add its own /. + * - if u.RawQuery is empty, ?query is omitted. + * - if u.Fragment is empty, #fragment is omitted. + * ``` + */ + string(): string + } + interface URL { + /** + * Redacted is like [URL.String] but replaces any password with "xxxxx". + * Only the password in u.User is redacted. + */ + redacted(): string + } + /** + * Values maps a string key to a list of values. + * It is typically used for query parameters and form values. + * Unlike in the http.Header map, the keys in a Values map + * are case-sensitive. + */ + interface Values extends _TygojaDict{} + interface Values { + /** + * Get gets the first value associated with the given key. + * If there are no values associated with the key, Get returns + * the empty string. To access multiple values, use the map + * directly. + */ + get(key: string): string + } + interface Values { + /** + * Set sets the key to value. It replaces any existing + * values. + */ + set(key: string, value: string): void + } + interface Values { + /** + * Add adds the value to key. It appends to any existing + * values associated with key. + */ + add(key: string, value: string): void + } + interface Values { + /** + * Del deletes the values associated with key. + */ + del(key: string): void + } + interface Values { + /** + * Has checks whether a given key is set. + */ + has(key: string): boolean + } + interface Values { + /** + * Clone creates a deep copy of the subject [Values]. + */ + clone(): Values + } + interface Values { + /** + * Encode encodes the values into “URL encoded” form + * ("bar=baz&foo=quux") sorted by key. + */ + encode(): string + } + interface URL { + /** + * IsAbs reports whether the [URL] is absolute. + * Absolute means that it has a non-empty scheme. + */ + isAbs(): boolean + } + interface URL { + /** + * Parse parses a [URL] in the context of the receiver. The provided URL + * may be relative or absolute. Parse returns nil, err on parse + * failure, otherwise its return value is the same as [URL.ResolveReference]. + */ + parse(ref: string): (URL) + } + interface URL { + /** + * ResolveReference resolves a URI reference to an absolute URI from + * an absolute base URI u, per RFC 3986 Section 5.2. The URI reference + * may be relative or absolute. ResolveReference always returns a new + * [URL] instance, even if the returned URL is identical to either the + * base or reference. If ref is an absolute URL, then ResolveReference + * ignores base and returns a copy of ref. + */ + resolveReference(ref: URL): (URL) + } + interface URL { + /** + * Query parses RawQuery and returns the corresponding values. + * It silently discards malformed value pairs. + * To check errors use [ParseQuery]. + */ + query(): Values + } + interface URL { + /** + * RequestURI returns the encoded path?query or opaque?query + * string that would be used in an HTTP request for u. + */ + requestURI(): string + } + interface URL { + /** + * Hostname returns u.Host, stripping any valid port number if present. + * + * If the result is enclosed in square brackets, as literal IPv6 addresses are, + * the square brackets are removed from the result. + */ + hostname(): string + } + interface URL { + /** + * Port returns the port part of u.Host, without the leading colon. + * + * If u.Host doesn't contain a valid numeric port, Port returns an empty string. + */ + port(): string + } + interface URL { + marshalBinary(): string|Array + } + interface URL { + appendBinary(b: string|Array): string|Array + } + interface URL { + unmarshalBinary(text: string|Array): void + } + interface URL { + /** + * JoinPath returns a new [URL] with the provided path elements joined to + * any existing path and the resulting path cleaned of any ./ or ../ elements. + * Any sequences of multiple / characters will be reduced to a single /. + * Path elements must already be in escaped form, as produced by [PathEscape]. + */ + joinPath(...elem: string[]): (URL) + } + interface URL { + /** + * Clone creates a deep copy of the fields of the subject [URL]. + */ + clone(): (URL) + } +} + +namespace bufio { + /** + * Reader implements buffering for an io.Reader object. + * A new Reader is created by calling [NewReader] or [NewReaderSize]; + * alternatively the zero value of a Reader may be used after calling [Reader.Reset] + * on it. + */ + interface Reader { + } + interface Reader { + /** + * Size returns the size of the underlying buffer in bytes. + */ + size(): number + } + interface Reader { + /** + * Reset discards any buffered data, resets all state, and switches + * the buffered reader to read from r. + * Calling Reset on the zero value of [Reader] initializes the internal buffer + * to the default size. + * Calling b.Reset(b) (that is, resetting a [Reader] to itself) does nothing. + */ + reset(r: io.Reader): void + } + interface Reader { + /** + * Peek returns the next n bytes without advancing the reader. The bytes stop + * being valid at the next read call. If necessary, Peek will read more bytes + * into the buffer in order to make n bytes available. If Peek returns fewer + * than n bytes, it also returns an error explaining why the read is short. + * The error is [ErrBufferFull] if n is larger than b's buffer size. + * + * Calling Peek prevents a [Reader.UnreadByte] or [Reader.UnreadRune] call from succeeding + * until the next read operation. + */ + peek(n: number): string|Array + } + interface Reader { + /** + * Discard skips the next n bytes, returning the number of bytes discarded. + * + * If Discard skips fewer than n bytes, it also returns an error. + * If 0 <= n <= b.Buffered(), Discard is guaranteed to succeed without + * reading from the underlying io.Reader. + */ + discard(n: number): number + } + interface Reader { + /** + * Read reads data into p. + * It returns the number of bytes read into p. + * The bytes are taken from at most one Read on the underlying [Reader], + * hence n may be less than len(p). + * To read exactly len(p) bytes, use io.ReadFull(b, p). + * If the underlying [Reader] can return a non-zero count with io.EOF, + * then this Read method can do so as well; see the [io.Reader] docs. + */ + read(p: string|Array): number } - interface URL { + interface Reader { /** - * EscapedFragment returns the escaped form of u.Fragment. - * In general there are multiple possible escaped forms of any fragment. - * EscapedFragment returns u.RawFragment when it is a valid escaping of u.Fragment. - * Otherwise EscapedFragment ignores u.RawFragment and computes an escaped - * form on its own. - * The [URL.String] method uses EscapedFragment to construct its result. - * In general, code should call EscapedFragment instead of - * reading u.RawFragment directly. + * ReadByte reads and returns a single byte. + * If no byte is available, returns an error. */ - escapedFragment(): string + readByte(): number } - interface URL { + interface Reader { /** - * String reassembles the [URL] into a valid URL string. - * The general form of the result is one of: - * - * ``` - * scheme:opaque?query#fragment - * scheme://userinfo@host/path?query#fragment - * ``` - * - * If u.Opaque is non-empty, String uses the first form; - * otherwise it uses the second form. - * Any non-ASCII characters in host are escaped. - * To obtain the path, String uses u.EscapedPath(). + * UnreadByte unreads the last byte. Only the most recently read byte can be unread. * - * In the second form, the following rules apply: - * ``` - * - if u.Scheme is empty, scheme: is omitted. - * - if u.User is nil, userinfo@ is omitted. - * - if u.Host is empty, host/ is omitted. - * - if u.Scheme and u.Host are empty and u.User is nil, - * the entire scheme://userinfo@host/ is omitted. - * - if u.Host is non-empty and u.Path begins with a /, - * the form host/path does not add its own /. - * - if u.RawQuery is empty, ?query is omitted. - * - if u.Fragment is empty, #fragment is omitted. - * ``` + * UnreadByte returns an error if the most recent method called on the + * [Reader] was not a read operation. Notably, [Reader.Peek], [Reader.Discard], and [Reader.WriteTo] are not + * considered read operations. */ - string(): string + unreadByte(): void } - interface URL { + interface Reader { /** - * Redacted is like [URL.String] but replaces any password with "xxxxx". - * Only the password in u.User is redacted. + * ReadRune reads a single UTF-8 encoded Unicode character and returns the + * rune and its size in bytes. If the encoded rune is invalid, it consumes one byte + * and returns unicode.ReplacementChar (U+FFFD) with a size of 1. */ - redacted(): string + readRune(): [number, number] } - /** - * Values maps a string key to a list of values. - * It is typically used for query parameters and form values. - * Unlike in the http.Header map, the keys in a Values map - * are case-sensitive. - */ - interface Values extends _TygojaDict{} - interface Values { + interface Reader { /** - * Get gets the first value associated with the given key. - * If there are no values associated with the key, Get returns - * the empty string. To access multiple values, use the map - * directly. + * UnreadRune unreads the last rune. If the most recent method called on + * the [Reader] was not a [Reader.ReadRune], [Reader.UnreadRune] returns an error. (In this + * regard it is stricter than [Reader.UnreadByte], which will unread the last byte + * from any read operation.) */ - get(key: string): string + unreadRune(): void } - interface Values { + interface Reader { /** - * Set sets the key to value. It replaces any existing - * values. + * Buffered returns the number of bytes that can be read from the current buffer. */ - set(key: string, value: string): void + buffered(): number } - interface Values { + interface Reader { /** - * Add adds the value to key. It appends to any existing - * values associated with key. + * ReadSlice reads until the first occurrence of delim in the input, + * returning a slice pointing at the bytes in the buffer. + * The bytes stop being valid at the next read. + * If ReadSlice encounters an error before finding a delimiter, + * it returns all the data in the buffer and the error itself (often io.EOF). + * ReadSlice fails with error [ErrBufferFull] if the buffer fills without a delim. + * Because the data returned from ReadSlice will be overwritten + * by the next I/O operation, most clients should use + * [Reader.ReadBytes] or ReadString instead. + * ReadSlice returns err != nil if and only if line does not end in delim. */ - add(key: string, value: string): void + readSlice(delim: number): string|Array } - interface Values { + interface Reader { /** - * Del deletes the values associated with key. + * ReadLine is a low-level line-reading primitive. Most callers should use + * [Reader.ReadBytes]('\n') or [Reader.ReadString]('\n') instead or use a [Scanner]. + * + * ReadLine tries to return a single line, not including the end-of-line bytes. + * If the line was too long for the buffer then isPrefix is set and the + * beginning of the line is returned. The rest of the line will be returned + * from future calls. isPrefix will be false when returning the last fragment + * of the line. The returned buffer is only valid until the next call to + * ReadLine. ReadLine either returns a non-nil line or it returns an error, + * never both. + * + * The text returned from ReadLine does not include the line end ("\r\n" or "\n"). + * No indication or error is given if the input ends without a final line end. + * Calling [Reader.UnreadByte] after ReadLine will always unread the last byte read + * (possibly a character belonging to the line end) even if that byte is not + * part of the line returned by ReadLine. */ - del(key: string): void + readLine(): [string|Array, boolean] } - interface Values { + interface Reader { /** - * Has checks whether a given key is set. + * ReadBytes reads until the first occurrence of delim in the input, + * returning a slice containing the data up to and including the delimiter. + * If ReadBytes encounters an error before finding a delimiter, + * it returns the data read before the error and the error itself (often io.EOF). + * ReadBytes returns err != nil if and only if the returned data does not end in + * delim. + * For simple uses, a Scanner may be more convenient. */ - has(key: string): boolean + readBytes(delim: number): string|Array } - interface Values { + interface Reader { /** - * Clone creates a deep copy of the subject [Values]. + * ReadString reads until the first occurrence of delim in the input, + * returning a string containing the data up to and including the delimiter. + * If ReadString encounters an error before finding a delimiter, + * it returns the data read before the error and the error itself (often io.EOF). + * ReadString returns err != nil if and only if the returned data does not end in + * delim. + * For simple uses, a Scanner may be more convenient. */ - clone(): Values + readString(delim: number): string } - interface Values { + interface Reader { /** - * Encode encodes the values into “URL encoded” form - * ("bar=baz&foo=quux") sorted by key. + * WriteTo implements io.WriterTo. + * This may make multiple calls to the [Reader.Read] method of the underlying [Reader]. + * If the underlying reader supports the [Reader.WriteTo] method, + * this calls the underlying [Reader.WriteTo] without buffering. */ - encode(): string + writeTo(w: io.Writer): number } - interface URL { + /** + * Writer implements buffering for an [io.Writer] object. + * If an error occurs writing to a [Writer], no more data will be + * accepted and all subsequent writes, and [Writer.Flush], will return the error. + * After all data has been written, the client should call the + * [Writer.Flush] method to guarantee all data has been forwarded to + * the underlying [io.Writer]. + */ + interface Writer { + } + interface Writer { /** - * IsAbs reports whether the [URL] is absolute. - * Absolute means that it has a non-empty scheme. + * Size returns the size of the underlying buffer in bytes. */ - isAbs(): boolean + size(): number } - interface URL { + interface Writer { /** - * Parse parses a [URL] in the context of the receiver. The provided URL - * may be relative or absolute. Parse returns nil, err on parse - * failure, otherwise its return value is the same as [URL.ResolveReference]. + * Reset discards any unflushed buffered data, clears any error, and + * resets b to write its output to w. + * Calling Reset on the zero value of [Writer] initializes the internal buffer + * to the default size. + * Calling w.Reset(w) (that is, resetting a [Writer] to itself) does nothing. */ - parse(ref: string): (URL) + reset(w: io.Writer): void } - interface URL { + interface Writer { /** - * ResolveReference resolves a URI reference to an absolute URI from - * an absolute base URI u, per RFC 3986 Section 5.2. The URI reference - * may be relative or absolute. ResolveReference always returns a new - * [URL] instance, even if the returned URL is identical to either the - * base or reference. If ref is an absolute URL, then ResolveReference - * ignores base and returns a copy of ref. + * Flush writes any buffered data to the underlying [io.Writer]. */ - resolveReference(ref: URL): (URL) + flush(): void } - interface URL { + interface Writer { /** - * Query parses RawQuery and returns the corresponding values. - * It silently discards malformed value pairs. - * To check errors use [ParseQuery]. + * Available returns how many bytes are unused in the buffer. */ - query(): Values + available(): number } - interface URL { + interface Writer { /** - * RequestURI returns the encoded path?query or opaque?query - * string that would be used in an HTTP request for u. + * AvailableBuffer returns an empty buffer with b.Available() capacity. + * This buffer is intended to be appended to and + * passed to an immediately succeeding [Writer.Write] call. + * The buffer is only valid until the next write operation on b. */ - requestURI(): string + availableBuffer(): string|Array } - interface URL { + interface Writer { /** - * Hostname returns u.Host, stripping any valid port number if present. - * - * If the result is enclosed in square brackets, as literal IPv6 addresses are, - * the square brackets are removed from the result. + * Buffered returns the number of bytes that have been written into the current buffer. */ - hostname(): string + buffered(): number } - interface URL { + interface Writer { /** - * Port returns the port part of u.Host, without the leading colon. - * - * If u.Host doesn't contain a valid numeric port, Port returns an empty string. + * Write writes the contents of p into the buffer. + * It returns the number of bytes written. + * If nn < len(p), it also returns an error explaining + * why the write is short. */ - port(): string - } - interface URL { - marshalBinary(): string|Array + write(p: string|Array): number } - interface URL { - appendBinary(b: string|Array): string|Array + interface Writer { + /** + * WriteByte writes a single byte. + */ + writeByte(c: number): void } - interface URL { - unmarshalBinary(text: string|Array): void + interface Writer { + /** + * WriteRune writes a single Unicode code point, returning + * the number of bytes written and any error. + */ + writeRune(r: number): number } - interface URL { + interface Writer { /** - * JoinPath returns a new [URL] with the provided path elements joined to - * any existing path and the resulting path cleaned of any ./ or ../ elements. - * Any sequences of multiple / characters will be reduced to a single /. - * Path elements must already be in escaped form, as produced by [PathEscape]. + * WriteString writes a string. + * It returns the number of bytes written. + * If the count is less than len(s), it also returns an error explaining + * why the write is short. */ - joinPath(...elem: string[]): (URL) + writeString(s: string): number } - interface URL { + interface Writer { /** - * Clone creates a deep copy of the fields of the subject [URL]. + * ReadFrom implements [io.ReaderFrom]. If the underlying writer + * supports the ReadFrom method, this calls the underlying ReadFrom. + * If there is buffered data and an underlying ReadFrom, this fills + * the buffer and writes it before calling ReadFrom. */ - clone(): (URL) - } -} - -namespace net { - /** - * Addr represents a network end point address. - * - * The two methods [Addr.Network] and [Addr.String] conventionally return strings - * that can be passed as the arguments to [Dial], but the exact form - * and meaning of the strings is up to the implementation. - */ - interface Addr { - [key:string]: any; - network(): string // name of the network (for example, "tcp", "udp") - string(): string // string form of address (for example, "192.0.2.1:25", "[2001:db8::1]:80") + readFrom(r: io.Reader): number } - // @ts-ignore - import _cgopackage = cgo } /** @@ -23568,304 +23367,606 @@ namespace http { /** * HTTP1 reports whether p includes HTTP/1. */ - http1(): boolean - } - interface Protocols { + http1(): boolean + } + interface Protocols { + /** + * SetHTTP1 adds or removes HTTP/1 from p. + */ + setHTTP1(ok: boolean): void + } + interface Protocols { + /** + * HTTP2 reports whether p includes HTTP/2. + */ + http2(): boolean + } + interface Protocols { + /** + * SetHTTP2 adds or removes HTTP/2 from p. + */ + setHTTP2(ok: boolean): void + } + interface Protocols { + /** + * UnencryptedHTTP2 reports whether p includes unencrypted HTTP/2. + */ + unencryptedHTTP2(): boolean + } + interface Protocols { + /** + * SetUnencryptedHTTP2 adds or removes unencrypted HTTP/2 from p. + */ + setUnencryptedHTTP2(ok: boolean): void + } + interface Protocols { + string(): string + } + /** + * HTTP2Config defines HTTP/2 configuration parameters common to + * both [Transport] and [Server]. + */ + interface HTTP2Config { + /** + * MaxConcurrentStreams optionally specifies the number of + * concurrent streams that a client may have open at a time. + * If zero, MaxConcurrentStreams defaults to at least 100. + * + * This parameter only applies to Servers. + */ + maxConcurrentStreams: number + /** + * StrictMaxConcurrentRequests controls whether an HTTP/2 server's + * concurrency limit should be respected across all connections + * to that server. + * If true, new requests sent when a connection's concurrency limit + * has been exceeded will block until an existing request completes. + * If false, an additional connection will be opened if all + * existing connections are at their limit. + * + * This parameter only applies to Transports. + */ + strictMaxConcurrentRequests: boolean + /** + * MaxDecoderHeaderTableSize optionally specifies an upper limit for the + * size of the header compression table used for decoding headers sent + * by the peer. + * A valid value is less than 4MiB. + * If zero or invalid, a default value is used. + */ + maxDecoderHeaderTableSize: number + /** + * MaxEncoderHeaderTableSize optionally specifies an upper limit for the + * header compression table used for sending headers to the peer. + * A valid value is less than 4MiB. + * If zero or invalid, a default value is used. + */ + maxEncoderHeaderTableSize: number + /** + * MaxReadFrameSize optionally specifies the largest frame + * this endpoint is willing to read. + * A valid value is between 16KiB and 16MiB, inclusive. + * If zero or invalid, a default value is used. + */ + maxReadFrameSize: number + /** + * MaxReceiveBufferPerConnection is the maximum size of the + * flow control window for data received on a connection. + * A valid value is at least 64KiB and less than 4MiB. + * If invalid, a default value is used. + */ + maxReceiveBufferPerConnection: number + /** + * MaxReceiveBufferPerStream is the maximum size of + * the flow control window for data received on a stream (request). + * A valid value is less than 4MiB. + * If zero or invalid, a default value is used. + */ + maxReceiveBufferPerStream: number + /** + * SendPingTimeout is the timeout after which a health check using a ping + * frame will be carried out if no frame is received on a connection. + * If zero, no health check is performed. + */ + sendPingTimeout: time.Duration + /** + * PingTimeout is the timeout after which a connection will be closed + * if a response to a ping is not received. + * If zero, a default of 15 seconds is used. + */ + pingTimeout: time.Duration + /** + * WriteByteTimeout is the timeout after which a connection will be + * closed if no data can be written to it. The timeout begins when data is + * available to write, and is extended whenever any bytes are written. + */ + writeByteTimeout: time.Duration + /** + * PermitProhibitedCipherSuites, if true, permits the use of + * cipher suites prohibited by the HTTP/2 spec. + */ + permitProhibitedCipherSuites: boolean + /** + * CountError, if non-nil, is called on HTTP/2 errors. + * It is intended to increment a metric for monitoring. + * The errType contains only lowercase letters, digits, and underscores + * (a-z, 0-9, _). + */ + countError: (errType: string) => void + } + // @ts-ignore + import urlpkg = url + /** + * Response represents the response from an HTTP request. + * + * The [Client] and [Transport] return Responses from servers once + * the response headers have been received. The response body + * is streamed on demand as the Body field is read. + */ + interface Response { + status: string // e.g. "200 OK" + statusCode: number // e.g. 200 + proto: string // e.g. "HTTP/1.0" + protoMajor: number // e.g. 1 + protoMinor: number // e.g. 0 + /** + * Header maps header keys to values. If the response had multiple + * headers with the same key, they may be concatenated, with comma + * delimiters. (RFC 7230, section 3.2.2 requires that multiple headers + * be semantically equivalent to a comma-delimited sequence.) When + * Header values are duplicated by other fields in this struct (e.g., + * ContentLength, TransferEncoding, Trailer), the field values are + * authoritative. + * + * Keys in the map are canonicalized (see CanonicalHeaderKey). + */ + header: Header + /** + * Body represents the response body. + * + * The response body is streamed on demand as the Body field + * is read. If the network connection fails or the server + * terminates the response, Body.Read calls return an error. + * + * The http Client and Transport guarantee that Body is always + * non-nil, even on responses without a body or responses with + * a zero-length body. It is the caller's responsibility to + * close Body. The default HTTP client's Transport may not + * reuse HTTP/1.x "keep-alive" TCP connections if the Body is + * not read to completion and closed; however, manually reading + * the body to completion should not be needed in most cases, + * as closing the body will also cause the body to be read to + * completion asynchronously, up to a conservative limit. + * + * The Body is automatically dechunked if the server replied + * with a "chunked" Transfer-Encoding. + * + * As of Go 1.12, the Body will also implement io.Writer + * on a successful "101 Switching Protocols" response, + * as used by WebSockets and HTTP/2's "h2c" mode. + */ + body: io.ReadCloser + /** + * ContentLength records the length of the associated content. The + * value -1 indicates that the length is unknown. Unless Request.Method + * is "HEAD", values >= 0 indicate that the given number of bytes may + * be read from Body. + */ + contentLength: number + /** + * Contains transfer encodings from outer-most to inner-most. Value is + * nil, means that "identity" encoding is used. + */ + transferEncoding: Array + /** + * Close records whether the header directed that the connection be + * closed after reading Body. The value is advice for clients: neither + * ReadResponse nor Response.Write ever closes a connection. + */ + close: boolean + /** + * Uncompressed reports whether the response was sent compressed but + * was decompressed by the http package. When true, reading from + * Body yields the uncompressed content instead of the compressed + * content actually set from the server, ContentLength is set to -1, + * and the "Content-Length" and "Content-Encoding" fields are deleted + * from the responseHeader. To get the original response from + * the server, set Transport.DisableCompression to true. + */ + uncompressed: boolean + /** + * Trailer maps trailer keys to values in the same + * format as Header. + * + * The Trailer initially contains only nil values, one for + * each key specified in the server's "Trailer" header + * value. Those values are not added to Header. + * + * Trailer must not be accessed concurrently with Read calls + * on the Body. + * + * After Body.Read has returned io.EOF, Trailer will contain + * any trailer values sent by the server. + */ + trailer: Header + /** + * Request is the request that was sent to obtain this Response. + * Request's Body is nil (having already been consumed). + * This is only populated for Client requests. + */ + request?: Request /** - * SetHTTP1 adds or removes HTTP/1 from p. + * TLS contains information about the TLS connection on which the + * response was received. It is nil for unencrypted responses. + * The pointer is shared between responses and should not be + * modified. */ - setHTTP1(ok: boolean): void + tls?: any } - interface Protocols { + interface Response { /** - * HTTP2 reports whether p includes HTTP/2. + * Cookies parses and returns the cookies set in the Set-Cookie headers. */ - http2(): boolean + cookies(): Array<(Cookie | undefined)> } - interface Protocols { + interface Response { /** - * SetHTTP2 adds or removes HTTP/2 from p. + * Location returns the URL of the response's "Location" header, + * if present. Relative redirects are resolved relative to + * [Response.Request]. [ErrNoLocation] is returned if no + * Location header is present. */ - setHTTP2(ok: boolean): void + location(): (url.URL) } - interface Protocols { + interface Response { /** - * UnencryptedHTTP2 reports whether p includes unencrypted HTTP/2. + * ProtoAtLeast reports whether the HTTP protocol used + * in the response is at least major.minor. */ - unencryptedHTTP2(): boolean + protoAtLeast(major: number, minor: number): boolean } - interface Protocols { + interface Response { /** - * SetUnencryptedHTTP2 adds or removes unencrypted HTTP/2 from p. + * Write writes r to w in the HTTP/1.x server response format, + * including the status line, headers, body, and optional trailer. + * + * This method consults the following fields of the response r: + * + * ``` + * StatusCode + * ProtoMajor + * ProtoMinor + * Request.Method + * TransferEncoding + * Trailer + * Body + * ContentLength + * Header, values for non-canonical keys will have unpredictable behavior + * ``` + * + * The Response Body is closed after it is sent. */ - setUnencryptedHTTP2(ok: boolean): void + write(w: io.Writer): void } - interface Protocols { + /** + * A ConnState represents the state of a client connection to a server. + * It's used by the optional [Server.ConnState] hook. + */ + interface ConnState extends Number{} + interface ConnState { string(): string } +} + +/** + * Package oauth2 provides support for making + * OAuth2 authorized and authenticated HTTP requests, + * as specified in RFC 6749. + * It can additionally grant authorization with Bearer JWT. + */ +namespace oauth2 { /** - * HTTP2Config defines HTTP/2 configuration parameters common to - * both [Transport] and [Server]. + * An AuthCodeOption is passed to Config.AuthCodeURL. */ - interface HTTP2Config { + interface AuthCodeOption { + [key:string]: any; + } + /** + * Token represents the credentials used to authorize + * the requests to access protected resources on the OAuth 2.0 + * provider's backend. + * + * Most users of this package should not access fields of Token + * directly. They're exported mostly for use by related packages + * implementing derivative OAuth2 flows. + */ + interface Token { /** - * MaxConcurrentStreams optionally specifies the number of - * concurrent streams that a client may have open at a time. - * If zero, MaxConcurrentStreams defaults to at least 100. - * - * This parameter only applies to Servers. + * AccessToken is the token that authorizes and authenticates + * the requests. */ - maxConcurrentStreams: number + accessToken: string /** - * StrictMaxConcurrentRequests controls whether an HTTP/2 server's - * concurrency limit should be respected across all connections - * to that server. - * If true, new requests sent when a connection's concurrency limit - * has been exceeded will block until an existing request completes. - * If false, an additional connection will be opened if all - * existing connections are at their limit. - * - * This parameter only applies to Transports. + * TokenType is the type of token. + * The Type method returns either this or "Bearer", the default. */ - strictMaxConcurrentRequests: boolean + tokenType: string /** - * MaxDecoderHeaderTableSize optionally specifies an upper limit for the - * size of the header compression table used for decoding headers sent - * by the peer. - * A valid value is less than 4MiB. - * If zero or invalid, a default value is used. + * RefreshToken is a token that's used by the application + * (as opposed to the user) to refresh the access token + * if it expires. */ - maxDecoderHeaderTableSize: number + refreshToken: string /** - * MaxEncoderHeaderTableSize optionally specifies an upper limit for the - * header compression table used for sending headers to the peer. - * A valid value is less than 4MiB. - * If zero or invalid, a default value is used. + * Expiry is the optional expiration time of the access token. + * + * If zero, [TokenSource] implementations will reuse the same + * token forever and RefreshToken or equivalent + * mechanisms for that TokenSource will not be used. */ - maxEncoderHeaderTableSize: number + expiry: time.Time /** - * MaxReadFrameSize optionally specifies the largest frame - * this endpoint is willing to read. - * A valid value is between 16KiB and 16MiB, inclusive. - * If zero or invalid, a default value is used. + * ExpiresIn is the OAuth2 wire format "expires_in" field, + * which specifies how many seconds later the token expires, + * relative to an unknown time base approximately around "now". + * It is the application's responsibility to populate + * `Expiry` from `ExpiresIn` when required. */ - maxReadFrameSize: number + expiresIn: number + } + interface Token { /** - * MaxReceiveBufferPerConnection is the maximum size of the - * flow control window for data received on a connection. - * A valid value is at least 64KiB and less than 4MiB. - * If invalid, a default value is used. + * Type returns t.TokenType if non-empty, else "Bearer". */ - maxReceiveBufferPerConnection: number + type(): string + } + interface Token { /** - * MaxReceiveBufferPerStream is the maximum size of - * the flow control window for data received on a stream (request). - * A valid value is less than 4MiB. - * If zero or invalid, a default value is used. + * SetAuthHeader sets the Authorization header to r using the access + * token in t. + * + * This method is unnecessary when using [Transport] or an HTTP Client + * returned by this package. */ - maxReceiveBufferPerStream: number + setAuthHeader(r: http.Request): void + } + interface Token { /** - * SendPingTimeout is the timeout after which a health check using a ping - * frame will be carried out if no frame is received on a connection. - * If zero, no health check is performed. + * WithExtra returns a new [Token] that's a clone of t, but using the + * provided raw extra map. This is only intended for use by packages + * implementing derivative OAuth2 flows. */ - sendPingTimeout: time.Duration + withExtra(extra: any): (Token) + } + interface Token { /** - * PingTimeout is the timeout after which a connection will be closed - * if a response to a ping is not received. - * If zero, a default of 15 seconds is used. + * Extra returns an extra field. + * Extra fields are key-value pairs returned by the server as + * part of the token retrieval response. */ - pingTimeout: time.Duration + extra(key: string): any + } + interface Token { /** - * WriteByteTimeout is the timeout after which a connection will be - * closed if no data can be written to it. The timeout begins when data is - * available to write, and is extended whenever any bytes are written. + * Valid reports whether t is non-nil, has an AccessToken, and is not expired. */ - writeByteTimeout: time.Duration + valid(): boolean + } +} + +namespace sql { + /** + * IsolationLevel is the transaction isolation level used in [TxOptions]. + */ + interface IsolationLevel extends Number{} + interface IsolationLevel { /** - * PermitProhibitedCipherSuites, if true, permits the use of - * cipher suites prohibited by the HTTP/2 spec. + * String returns the name of the transaction isolation level. */ - permitProhibitedCipherSuites: boolean + string(): string + } + /** + * DBStats contains database statistics. + */ + interface DBStats { + maxOpenConnections: number // Maximum number of open connections to the database. /** - * CountError, if non-nil, is called on HTTP/2 errors. - * It is intended to increment a metric for monitoring. - * The errType contains only lowercase letters, digits, and underscores - * (a-z, 0-9, _). + * Pool Status */ - countError: (errType: string) => void + openConnections: number // The number of established connections both in use and idle. + inUse: number // The number of connections currently in use. + idle: number // The number of idle connections. + /** + * Counters + */ + waitCount: number // The total number of connections waited for. + waitDuration: time.Duration // The total time blocked waiting for a new connection. + maxIdleClosed: number // The total number of connections closed due to SetMaxIdleConns. + maxIdleTimeClosed: number // The total number of connections closed due to SetConnMaxIdleTime. + maxLifetimeClosed: number // The total number of connections closed due to SetConnMaxLifetime. } - // @ts-ignore - import urlpkg = url /** - * Response represents the response from an HTTP request. + * Conn represents a single database connection rather than a pool of database + * connections. Prefer running queries from [DB] unless there is a specific + * need for a continuous single database connection. * - * The [Client] and [Transport] return Responses from servers once - * the response headers have been received. The response body - * is streamed on demand as the Body field is read. + * A Conn must call [Conn.Close] to return the connection to the database pool + * and may do so concurrently with a running query. + * + * After a call to [Conn.Close], all operations on the + * connection fail with [ErrConnDone]. */ - interface Response { - status: string // e.g. "200 OK" - statusCode: number // e.g. 200 - proto: string // e.g. "HTTP/1.0" - protoMajor: number // e.g. 1 - protoMinor: number // e.g. 0 + interface Conn { + } + interface Conn { /** - * Header maps header keys to values. If the response had multiple - * headers with the same key, they may be concatenated, with comma - * delimiters. (RFC 7230, section 3.2.2 requires that multiple headers - * be semantically equivalent to a comma-delimited sequence.) When - * Header values are duplicated by other fields in this struct (e.g., - * ContentLength, TransferEncoding, Trailer), the field values are - * authoritative. - * - * Keys in the map are canonicalized (see CanonicalHeaderKey). + * PingContext verifies the connection to the database is still alive. */ - header: Header + pingContext(ctx: context.Context): void + } + interface Conn { /** - * Body represents the response body. - * - * The response body is streamed on demand as the Body field - * is read. If the network connection fails or the server - * terminates the response, Body.Read calls return an error. - * - * The http Client and Transport guarantee that Body is always - * non-nil, even on responses without a body or responses with - * a zero-length body. It is the caller's responsibility to - * close Body. The default HTTP client's Transport may not - * reuse HTTP/1.x "keep-alive" TCP connections if the Body is - * not read to completion and closed; however, manually reading - * the body to completion should not be needed in most cases, - * as closing the body will also cause the body to be read to - * completion asynchronously, up to a conservative limit. - * - * The Body is automatically dechunked if the server replied - * with a "chunked" Transfer-Encoding. - * - * As of Go 1.12, the Body will also implement io.Writer - * on a successful "101 Switching Protocols" response, - * as used by WebSockets and HTTP/2's "h2c" mode. + * ExecContext executes a query without returning any rows. + * The args are for any placeholder parameters in the query. */ - body: io.ReadCloser + execContext(ctx: context.Context, query: string, ...args: any[]): Result + } + interface Conn { /** - * ContentLength records the length of the associated content. The - * value -1 indicates that the length is unknown. Unless Request.Method - * is "HEAD", values >= 0 indicate that the given number of bytes may - * be read from Body. + * QueryContext executes a query that returns rows, typically a SELECT. + * The args are for any placeholder parameters in the query. */ - contentLength: number + queryContext(ctx: context.Context, query: string, ...args: any[]): (Rows) + } + interface Conn { /** - * Contains transfer encodings from outer-most to inner-most. Value is - * nil, means that "identity" encoding is used. + * QueryRowContext executes a query that is expected to return at most one row. + * QueryRowContext always returns a non-nil value. Errors are deferred until + * the [*Row.Scan] method is called. + * If the query selects no rows, the [*Row.Scan] will return [ErrNoRows]. + * Otherwise, the [*Row.Scan] scans the first selected row and discards + * the rest. */ - transferEncoding: Array + queryRowContext(ctx: context.Context, query: string, ...args: any[]): (Row) + } + interface Conn { /** - * Close records whether the header directed that the connection be - * closed after reading Body. The value is advice for clients: neither - * ReadResponse nor Response.Write ever closes a connection. + * PrepareContext creates a prepared statement for later queries or executions. + * Multiple queries or executions may be run concurrently from the + * returned statement. + * The caller must call the statement's [*Stmt.Close] method + * when the statement is no longer needed. + * + * The provided context is used for the preparation of the statement, not for the + * execution of the statement. */ - close: boolean + prepareContext(ctx: context.Context, query: string): (Stmt) + } + interface Conn { /** - * Uncompressed reports whether the response was sent compressed but - * was decompressed by the http package. When true, reading from - * Body yields the uncompressed content instead of the compressed - * content actually set from the server, ContentLength is set to -1, - * and the "Content-Length" and "Content-Encoding" fields are deleted - * from the responseHeader. To get the original response from - * the server, set Transport.DisableCompression to true. + * Raw executes f exposing the underlying driver connection for the + * duration of f. The driverConn must not be used outside of f. + * + * Once f returns and err is not [driver.ErrBadConn], the [Conn] will continue to be usable + * until [Conn.Close] is called. */ - uncompressed: boolean + raw(f: (driverConn: any) => void): void + } + interface Conn { /** - * Trailer maps trailer keys to values in the same - * format as Header. - * - * The Trailer initially contains only nil values, one for - * each key specified in the server's "Trailer" header - * value. Those values are not added to Header. + * BeginTx starts a transaction. * - * Trailer must not be accessed concurrently with Read calls - * on the Body. + * The provided context is used until the transaction is committed or rolled back. + * If the context is canceled, the sql package will roll back + * the transaction. [Tx.Commit] will return an error if the context provided to + * BeginTx is canceled. * - * After Body.Read has returned io.EOF, Trailer will contain - * any trailer values sent by the server. + * The provided [TxOptions] is optional and may be nil if defaults should be used. + * If a non-default isolation level is used that the driver doesn't support, + * an error will be returned. */ - trailer: Header + beginTx(ctx: context.Context, opts: TxOptions): (Tx) + } + interface Conn { /** - * Request is the request that was sent to obtain this Response. - * Request's Body is nil (having already been consumed). - * This is only populated for Client requests. + * Close returns the connection to the connection pool. + * All operations after a Close will return with [ErrConnDone]. + * Close is safe to call concurrently with other operations and will + * block until all other operations finish. It may be useful to first + * cancel any used context and then call close directly after. */ - request?: Request + close(): void + } + /** + * ColumnType contains the name and type of a column. + */ + interface ColumnType { + } + interface ColumnType { /** - * TLS contains information about the TLS connection on which the - * response was received. It is nil for unencrypted responses. - * The pointer is shared between responses and should not be - * modified. + * Name returns the name or alias of the column. */ - tls?: any + name(): string } - interface Response { + interface ColumnType { /** - * Cookies parses and returns the cookies set in the Set-Cookie headers. + * Length returns the column type length for variable length column types such + * as text and binary field types. If the type length is unbounded the value will + * be [math.MaxInt64] (any database limits will still apply). + * If the column type is not variable length, such as an int, or if not supported + * by the driver ok is false. */ - cookies(): Array<(Cookie | undefined)> + length(): [number, boolean] } - interface Response { + interface ColumnType { /** - * Location returns the URL of the response's "Location" header, - * if present. Relative redirects are resolved relative to - * [Response.Request]. [ErrNoLocation] is returned if no - * Location header is present. + * DecimalSize returns the scale and precision of a decimal type. + * If not applicable or if not supported ok is false. */ - location(): (url.URL) + decimalSize(): [number, number, boolean] } - interface Response { + interface ColumnType { /** - * ProtoAtLeast reports whether the HTTP protocol used - * in the response is at least major.minor. + * ScanType returns a Go type suitable for scanning into using [Rows.Scan]. + * If a driver does not support this property ScanType will return + * the type of an empty interface. */ - protoAtLeast(major: number, minor: number): boolean + scanType(): any } - interface Response { + interface ColumnType { /** - * Write writes r to w in the HTTP/1.x server response format, - * including the status line, headers, body, and optional trailer. - * - * This method consults the following fields of the response r: - * - * ``` - * StatusCode - * ProtoMajor - * ProtoMinor - * Request.Method - * TransferEncoding - * Trailer - * Body - * ContentLength - * Header, values for non-canonical keys will have unpredictable behavior - * ``` - * - * The Response Body is closed after it is sent. + * Nullable reports whether the column may be null. + * If a driver does not support this property ok will be false. */ - write(w: io.Writer): void + nullable(): [boolean, boolean] + } + interface ColumnType { + /** + * DatabaseTypeName returns the database system name of the column type. If an empty + * string is returned, then the driver type name is not supported. + * Consult your driver documentation for a list of driver data types. [ColumnType.Length] specifiers + * are not included. + * Common type names include "VARCHAR", "TEXT", "NVARCHAR", "DECIMAL", "BOOL", + * "INT", and "BIGINT". + */ + databaseTypeName(): string } /** - * A ConnState represents the state of a client connection to a server. - * It's used by the optional [Server.ConnState] hook. + * Row is the result of calling [DB.QueryRow] to select a single row. */ - interface ConnState extends Number{} - interface ConnState { - string(): string + interface Row { + } + interface Row { + /** + * Scan copies the columns from the matched row into the values + * pointed at by dest. See the documentation on [Rows.Scan] for details. + * If more than one row matches the query, + * Scan uses the first row and discards the rest. If no row matches + * the query, Scan returns [ErrNoRows]. + */ + scan(...dest: any[]): void + } + interface Row { + /** + * Err provides a way for wrapping packages to check for + * query errors without calling [Row.Scan]. + * Err returns the error, if any, that was encountered while running the query. + * If this error is not nil, this error will also be returned from [Row.Scan]. + */ + err(): void } } +namespace store { +} + namespace jwt { /** * NumericDate represents a JSON numeric date value, as referenced at * https://datatracker.ietf.org/doc/html/rfc7519#section-2. */ - type _sLEwbfo = time.Time - interface NumericDate extends _sLEwbfo { + type _sTZpnRR = time.Time + interface NumericDate extends _sTZpnRR { } interface NumericDate { /** @@ -23897,15 +23998,6 @@ namespace jwt { } } -namespace hook { - /** - * wrapped local Hook embedded struct to limit the public API surface. - */ - type _snJlIbJ = Hook - interface mainHook extends _snJlIbJ { - } -} - namespace types { } @@ -23932,6 +24024,15 @@ namespace search { interface NullFallbackPreference extends Number{} } +namespace hook { + /** + * wrapped local Hook embedded struct to limit the public API surface. + */ + type _siCQuEg = Hook + interface mainHook extends _siCQuEg { + } +} + namespace router { // @ts-ignore import validation = ozzo_validation @@ -24066,99 +24167,105 @@ namespace router { } } -/** - * Package oauth2 provides support for making - * OAuth2 authorized and authenticated HTTP requests, - * as specified in RFC 6749. - * It can additionally grant authorization with Bearer JWT. - */ -namespace oauth2 { +namespace cobra { + interface PositionalArgs {(cmd: Command, args: Array): void } + // @ts-ignore + import flag = pflag /** - * An AuthCodeOption is passed to Config.AuthCodeURL. + * FParseErrWhitelist configures Flag parse errors to be ignored */ - interface AuthCodeOption { - [key:string]: any; + interface FParseErrWhitelist extends _TygojaAny{} + /** + * Group Structure to manage groups for commands + */ + interface Group { + id: string + title: string } /** - * Token represents the credentials used to authorize - * the requests to access protected resources on the OAuth 2.0 - * provider's backend. - * - * Most users of this package should not access fields of Token - * directly. They're exported mostly for use by related packages - * implementing derivative OAuth2 flows. + * CompletionOptions are the options to control shell completion */ - interface Token { + interface CompletionOptions { /** - * AccessToken is the token that authorizes and authenticates - * the requests. + * DisableDefaultCmd prevents Cobra from creating a default 'completion' command */ - accessToken: string + disableDefaultCmd: boolean /** - * TokenType is the type of token. - * The Type method returns either this or "Bearer", the default. + * DisableNoDescFlag prevents Cobra from creating the '--no-descriptions' flag + * for shells that support completion descriptions */ - tokenType: string + disableNoDescFlag: boolean /** - * RefreshToken is a token that's used by the application - * (as opposed to the user) to refresh the access token - * if it expires. + * DisableDescriptions turns off all completion descriptions for shells + * that support them */ - refreshToken: string + disableDescriptions: boolean /** - * Expiry is the optional expiration time of the access token. - * - * If zero, [TokenSource] implementations will reuse the same - * token forever and RefreshToken or equivalent - * mechanisms for that TokenSource will not be used. + * HiddenDefaultCmd makes the default 'completion' command hidden */ - expiry: time.Time + hiddenDefaultCmd: boolean /** - * ExpiresIn is the OAuth2 wire format "expires_in" field, - * which specifies how many seconds later the token expires, - * relative to an unknown time base approximately around "now". - * It is the application's responsibility to populate - * `Expiry` from `ExpiresIn` when required. + * DefaultShellCompDirective sets the ShellCompDirective that is returned + * if no special directive can be determined */ - expiresIn: number + defaultShellCompDirective?: ShellCompDirective } - interface Token { - /** - * Type returns t.TokenType if non-empty, else "Bearer". - */ - type(): string + interface CompletionOptions { + setDefaultShellCompDirective(directive: ShellCompDirective): void } - interface Token { + /** + * Completion is a string that can be used for completions + * + * two formats are supported: + * ``` + * - the completion choice + * - the completion choice with a textual description (separated by a TAB). + * ``` + * + * [CompletionWithDesc] can be used to create a completion string with a textual description. + * + * Note: Go type alias is used to provide a more descriptive name in the documentation, but any string can be used. + */ + interface Completion extends String{} + /** + * CompletionFunc is a function that provides completion results. + */ + interface CompletionFunc {(cmd: Command, args: Array, toComplete: string): [Array, ShellCompDirective] } +} + +namespace subscriptions { +} + +namespace cron { + /** + * Job defines a single registered cron job. + */ + interface Job { + } + interface Job { /** - * SetAuthHeader sets the Authorization header to r using the access - * token in t. - * - * This method is unnecessary when using [Transport] or an HTTP Client - * returned by this package. + * Id returns the cron job id. */ - setAuthHeader(r: http.Request): void + id(): string } - interface Token { + interface Job { /** - * WithExtra returns a new [Token] that's a clone of t, but using the - * provided raw extra map. This is only intended for use by packages - * implementing derivative OAuth2 flows. + * Expression returns the plain cron job schedule expression. */ - withExtra(extra: any): (Token) + expression(): string } - interface Token { + interface Job { /** - * Extra returns an extra field. - * Extra fields are key-value pairs returned by the server as - * part of the token retrieval response. + * Run runs the cron job function. */ - extra(key: string): any + run(): void } - interface Token { + interface Job { /** - * Valid reports whether t is non-nil, has an AccessToken, and is not expired. + * MarshalJSON implements [json.Marshaler] and export the current + * jobs data into valid JSON. */ - valid(): boolean + marshalJSON(): string|Array } } @@ -24340,108 +24447,6 @@ namespace slog { import loginternal = internal } -namespace cobra { - interface PositionalArgs {(cmd: Command, args: Array): void } - // @ts-ignore - import flag = pflag - /** - * FParseErrWhitelist configures Flag parse errors to be ignored - */ - interface FParseErrWhitelist extends _TygojaAny{} - /** - * Group Structure to manage groups for commands - */ - interface Group { - id: string - title: string - } - /** - * CompletionOptions are the options to control shell completion - */ - interface CompletionOptions { - /** - * DisableDefaultCmd prevents Cobra from creating a default 'completion' command - */ - disableDefaultCmd: boolean - /** - * DisableNoDescFlag prevents Cobra from creating the '--no-descriptions' flag - * for shells that support completion descriptions - */ - disableNoDescFlag: boolean - /** - * DisableDescriptions turns off all completion descriptions for shells - * that support them - */ - disableDescriptions: boolean - /** - * HiddenDefaultCmd makes the default 'completion' command hidden - */ - hiddenDefaultCmd: boolean - /** - * DefaultShellCompDirective sets the ShellCompDirective that is returned - * if no special directive can be determined - */ - defaultShellCompDirective?: ShellCompDirective - } - interface CompletionOptions { - setDefaultShellCompDirective(directive: ShellCompDirective): void - } - /** - * Completion is a string that can be used for completions - * - * two formats are supported: - * ``` - * - the completion choice - * - the completion choice with a textual description (separated by a TAB). - * ``` - * - * [CompletionWithDesc] can be used to create a completion string with a textual description. - * - * Note: Go type alias is used to provide a more descriptive name in the documentation, but any string can be used. - */ - interface Completion extends String{} - /** - * CompletionFunc is a function that provides completion results. - */ - interface CompletionFunc {(cmd: Command, args: Array, toComplete: string): [Array, ShellCompDirective] } -} - -namespace cron { - /** - * Job defines a single registered cron job. - */ - interface Job { - } - interface Job { - /** - * Id returns the cron job id. - */ - id(): string - } - interface Job { - /** - * Expression returns the plain cron job schedule expression. - */ - expression(): string - } - interface Job { - /** - * Run runs the cron job function. - */ - run(): void - } - interface Job { - /** - * MarshalJSON implements [json.Marshaler] and export the current - * jobs data into valid JSON. - */ - marshalJSON(): string|Array - } -} - -namespace subscriptions { -} - namespace url { /** * The Userinfo type is an immutable encapsulation of username and @@ -24525,6 +24530,9 @@ namespace http { import urlpkg = url } +namespace oauth2 { +} + namespace search { /** * Join defines common fields required for a single SQL JOIN clause. @@ -24577,7 +24585,14 @@ namespace router { } } -namespace oauth2 { +namespace cobra { + // @ts-ignore + import flag = pflag + /** + * ShellCompDirective is a bit map representing the different behaviors the shell + * can be instructed to have once completions have been provided. + */ + interface ShellCompDirective extends Number{} } namespace slog { @@ -24760,14 +24775,9 @@ namespace slog { } } -namespace cobra { +namespace router { // @ts-ignore - import flag = pflag - /** - * ShellCompDirective is a bit map representing the different behaviors the shell - * can be instructed to have once completions have been provided. - */ - interface ShellCompDirective extends Number{} + import validation = ozzo_validation } namespace slog { @@ -24808,8 +24818,3 @@ namespace slog { logValue(): Value } } - -namespace router { - // @ts-ignore - import validation = ozzo_validation -} diff --git a/plugins/jsvm/internal/types/types.go b/plugins/jsvm/internal/types/types.go index a5fd6b5617..d489d7f2bb 100644 --- a/plugins/jsvm/internal/types/types.go +++ b/plugins/jsvm/internal/types/types.go @@ -129,7 +129,7 @@ type excludeHooks = { type CoreApp = excludeHooks // pocketbase.PocketBase without the on* hook methods -type PocketBase = excludeHooks +interface PocketBase extends excludeHooks{} /** * ` + "`$app`" + ` is the current running PocketBase instance that is globally diff --git a/plugins/migratecmd/templates.go b/plugins/migratecmd/templates.go index b135529b70..179817aff4 100644 --- a/plugins/migratecmd/templates.go +++ b/plugins/migratecmd/templates.go @@ -8,7 +8,6 @@ import ( "fmt" "path/filepath" "slices" - "strconv" "strings" "github.com/pocketbase/pocketbase/core" @@ -667,22 +666,11 @@ func init() { } func marhshalWithoutEscape(v any, prefix string, indent string) ([]byte, error) { - raw, err := json.Marshal(v, - json.Deterministic(true), + return json.Marshal(v, jsontext.WithIndentPrefix(prefix), jsontext.WithIndent(indent), + json.Deterministic(true), ) - if err != nil { - return nil, err - } - - // unescape escaped unicode characters - unescaped, err := strconv.Unquote(strings.ReplaceAll(strconv.Quote(string(raw)), `\\u`, `\u`)) - if err != nil { - return nil, err - } - - return []byte(unescaped), nil } func escapeBacktick(v string) string { diff --git a/tools/auth/oidc.go b/tools/auth/oidc.go index e9a30a8186..dfef2ad421 100644 --- a/tools/auth/oidc.go +++ b/tools/auth/oidc.go @@ -131,9 +131,9 @@ func (p *OIDC) FetchRawUserInfo(token *oauth2.Token) ([]byte, error) { } func (p *OIDC) parseIdToken(token *oauth2.Token) (jwt.MapClaims, error) { - idToken := token.Extra("id_token").(string) + idToken, _ := token.Extra("id_token").(string) if idToken == "" { - return nil, errors.New("empty id_token") + return nil, errors.New("empty or invalid id_token") } claims := jwt.MapClaims{} diff --git a/tools/dbutils/index.go b/tools/dbutils/index.go index 7ed026101c..40dc4a77a3 100644 --- a/tools/dbutils/index.go +++ b/tools/dbutils/index.go @@ -8,8 +8,8 @@ import ( ) var ( - indexRegex = regexp.MustCompile(`(?im)create\s+(unique\s+)?\s*index\s*(if\s+not\s+exists\s+)?(\S*)\s+on\s+(\S*)\s*\(([\s\S]*)\)(?:\s*where\s+([\s\S]*))?`) - indexColumnRegex = regexp.MustCompile(`(?im)^([\s\S]+?)(?:\s+collate\s+([\w]+))?(?:\s+(asc|desc))?$`) + indexRegex = regexp.MustCompile(`(?i)\s*create\s+(unique\s+)?\s*index\s*(if\s+not\s+exists\s+)?(\S*)\s+on\s+(\S*)\s*\(([\s\S]*?)\)(?:\s+where\s+([\s\S]*?))?\s*$`) + indexColumnRegex = regexp.MustCompile(`(?i)^([\s\S]+?)(?:\s+collate\s+([\w]+))?(?:\s+(asc|desc))?\s*$`) ) // IndexColumn represents a single parsed SQL index column. @@ -187,6 +187,11 @@ func ParseIndex(createIndexExpr string) Index { }) } + if len(rawColumns) != len(result.Columns) { + // unset to trigger validation error + result.Columns = []IndexColumn{} + } + // WHERE expression // --- result.Where = strings.TrimSpace(matches[6]) diff --git a/tools/dbutils/index_test.go b/tools/dbutils/index_test.go index 2a32b32607..74692353fe 100644 --- a/tools/dbutils/index_test.go +++ b/tools/dbutils/index_test.go @@ -3,7 +3,6 @@ package dbutils_test import ( "bytes" "encoding/json/v2" - "fmt" "strings" "testing" @@ -12,27 +11,28 @@ import ( func TestParseIndex(t *testing.T) { scenarios := []struct { + name string index string expected dbutils.Index }{ - // invalid { + "invalid", `invalid`, dbutils.Index{}, }, - // no names { + "no names", `create index on ()`, dbutils.Index{}, }, - // invalid index name { + "invalid index name", `create index a.b.c on ()`, dbutils.Index{}, }, - // simple (multiple spaces between the table and columns list) { - `create index indexname on tablename (col1)`, + "simple (multiple spaces as prefix, suffix, between the table and columns list)", + ` create index indexname on tablename (col1) `, dbutils.Index{ IndexName: "indexname", TableName: "tablename", @@ -41,8 +41,8 @@ func TestParseIndex(t *testing.T) { }, }, }, - // simple (no space between the table and the columns list) { + "simple (no space between the table and the columns list)", `create index indexname on tablename(col1)`, dbutils.Index{ IndexName: "indexname", @@ -52,15 +52,15 @@ func TestParseIndex(t *testing.T) { }, }, }, - // all fields { + "all fields", `CREATE UNIQUE INDEX IF NOT EXISTS "schemaname".[indexname] on 'tablename' ( col0, ` + "`" + `col1` + "`" + `, - json_extract("col2", "$.a") asc, + json_extract("col2_multiline",` + "\n" + ` "$.a") asc, "col3" collate NOCASE, "col4" collate RTRIM desc - ) where test = 1`, + ) where cast(test1 as ` + "\n" + `int) = 1 and test2 != ''`, dbutils.Index{ Unique: true, Optional: true, @@ -70,17 +70,17 @@ func TestParseIndex(t *testing.T) { Columns: []dbutils.IndexColumn{ {Name: "col0"}, {Name: "col1"}, - {Name: `json_extract("col2", "$.a")`, Sort: "ASC"}, + {Name: `json_extract("col2_multiline",` + "\n" + ` "$.a")`, Sort: "ASC"}, {Name: `col3`, Collate: "NOCASE"}, {Name: `col4`, Collate: "RTRIM", Sort: "DESC"}, }, - Where: "test = 1", + Where: "cast(test1 as \nint) = 1 and test2 != ''", }, }, } - for i, s := range scenarios { - t.Run(fmt.Sprintf("scenario_%d", i), func(t *testing.T) { + for _, s := range scenarios { + t.Run(s.name, func(t *testing.T) { result := dbutils.ParseIndex(s.index) resultRaw, err := json.Marshal(result) diff --git a/tools/picker/pick.go b/tools/picker/pick.go index c58a19a6fd..887e151d25 100644 --- a/tools/picker/pick.go +++ b/tools/picker/pick.go @@ -3,12 +3,16 @@ package picker import ( "encoding/json/jsontext" "encoding/json/v2" + "errors" + "fmt" "strings" "github.com/pocketbase/pocketbase/tools/search" "github.com/pocketbase/pocketbase/tools/tokenizer" ) +var ErrInvalidModifierData = errors.New("failed to apply some of the field modifiers for the provided data") + // Pick converts data into a []any, map[string]any, etc. (using json marshal->unmarshal) // containing only the fields from the parsed rawFields expression. // @@ -16,6 +20,10 @@ import ( // Nested fields should be listed with dot-notation. // Fields value modifiers are also supported using the `:modifier(args)` format (see Modifiers). // +// In case some data fails to apply against the registered modifiers +// a wrapped [ErrInvalidModifierData] is returned that you can inspect and +// decide to ignore or propagate further up the execution chain. +// // Example: // // data := map[string]any{"a": 1, "b": 2, "c": map[string]any{"c1": 11, "c2": 22}} @@ -33,15 +41,20 @@ func Pick(data any, rawFields string) (any, error) { // Note that invalid UTF8 characters are mangled for compatibility // with earlier versions and to prevent unnecessary causing an error. // + // Duplicated keys are also enabled for just in case of old jsonv1 data + // (new db entries are usually validated against the jsonv2 semantics). + // // @todo research other approaches to avoid the double serialization // --- - encoded, err := json.Marshal(data, jsontext.AllowInvalidUTF8(true)) + encoded, err := json.Marshal(data, jsontext.AllowDuplicateNames(true), jsontext.AllowInvalidUTF8(true)) if err != nil { return nil, err } var decoded any - if err := json.Unmarshal(encoded, &decoded); err != nil { + + err = json.Unmarshal(encoded, &decoded, jsontext.AllowDuplicateNames(true)) + if err != nil { return nil, err } // --- @@ -55,10 +68,16 @@ func Pick(data any, rawFields string) (any, error) { if isSearchResult { if decodedMap, ok := decoded.(map[string]any); ok { - pickParsedFields(decodedMap["items"], parsedFields) + err = pickParsedFields(decodedMap["items"], parsedFields) + if err != nil { + return nil, fmt.Errorf("%w: %w", ErrInvalidModifierData, err) + } } } else { - pickParsedFields(decoded, parsedFields) + err = pickParsedFields(decoded, parsedFields) + if err != nil { + return nil, fmt.Errorf("%w: %w", ErrInvalidModifierData, err) + } } return decoded, nil @@ -94,7 +113,10 @@ func parseFields(rawFields string) (map[string]Modifier, error) { func pickParsedFields(data any, fields map[string]Modifier) error { switch v := data.(type) { case map[string]any: - pickMapFields(v, fields) + err := pickMapFields(v, fields) + if err != nil { + return err + } case []map[string]any: for _, item := range v { if err := pickMapFields(item, fields); err != nil { @@ -112,7 +134,7 @@ func pickParsedFields(data any, fields map[string]Modifier) error { for _, item := range v { if err := pickMapFields(item.(map[string]any), fields); err != nil { - return nil + return err } } } diff --git a/tools/picker/pick_test.go b/tools/picker/pick_test.go index 4f2ea37cac..590c841520 100644 --- a/tools/picker/pick_test.go +++ b/tools/picker/pick_test.go @@ -1,13 +1,28 @@ package picker_test import ( + "encoding/json/jsontext" "encoding/json/v2" + "errors" "testing" "github.com/pocketbase/pocketbase/tools/picker" "github.com/pocketbase/pocketbase/tools/search" ) +type brokenModifier struct { +} + +func (m *brokenModifier) Modify(val any) (any, error) { + return nil, errors.New("test_error") +} + +func init() { + picker.Modifiers["broken"] = func(args ...string) (picker.Modifier, error) { + return &brokenModifier{}, nil + } +} + func TestPickFields(t *testing.T) { scenarios := []struct { name string @@ -223,6 +238,13 @@ func TestPickFields(t *testing.T) { false, `{"id":"123","rel":{"id":"456","sub":{"id":"789"},"title":"rel_title"}}`, }, + { + "with modifer.Modify error", + map[string]any{"a": 1}, + "*:broken", + true, + `{"a":1}`, + }, { "invalid excerpt modifier", map[string]any{"a": 1, "b": 2, "c": "test"}, @@ -248,6 +270,13 @@ func TestPickFields(t *testing.T) { false, `{"id":"12","rel":{"title":"rel..."},"title":"lo"}`, }, + { + "jsonv1 values", + map[string]any{"a": "test\xc3", "b": jsontext.Value(`{"a":1,"a":2}`)}, + "a, b", + false, + `{"a":"test�","b":{"a":2}}`, + }, } for _, s := range scenarios { @@ -263,7 +292,12 @@ func TestPickFields(t *testing.T) { return } - serialized, err := json.Marshal(result, json.Deterministic(true)) + serialized, err := json.Marshal( + result, + json.Deterministic(true), + jsontext.AllowInvalidUTF8(true), + jsontext.AllowDuplicateNames(true), + ) if err != nil { t.Fatal(err) } diff --git a/tools/router/event.go b/tools/router/event.go index cff155ca87..5c00e4ca78 100644 --- a/tools/router/event.go +++ b/tools/router/event.go @@ -189,23 +189,31 @@ const jsonFieldsParam = "fields" // Note that invalid UTF8 characters are mangled for compatibility // with earlier versions and to prevent unnecessary causing a response error. func (e *Event) JSON(status int, data any) error { - e.setResponseHeaderIfEmpty(headerContentType, "application/json") - e.Response.WriteHeader(status) - + // try to pick only the requested fields (currently allowed only for "success" responses) rawFields := e.Request.URL.Query().Get(jsonFieldsParam) - - // error response or no fields to pick - if rawFields == "" || status < 200 || status > 299 { - return json.MarshalWrite(e.Response, data, jsontext.AllowInvalidUTF8(true)) + if rawFields != "" && status >= 200 && status <= 299 { + modified, err := picker.Pick(data, rawFields) + if err == nil { + data = modified + } else if !errors.Is(err, picker.ErrInvalidModifierData) { + // @todo ignore for now modifier data errors to avoid introducing + // breaking changes but once the router is merged with core consider + // at least logging for dev purposes + return err + } } - // pick only the requested fields - modified, err := picker.Pick(data, rawFields) - if err != nil { - return err - } + e.setResponseHeaderIfEmpty(headerContentType, "application/json") + e.Response.WriteHeader(status) - return json.MarshalWrite(e.Response, modified, jsontext.AllowInvalidUTF8(true)) + return json.MarshalWrite( + e.Response, + data, + // for compliance with old data (and slightly better performance) + jsontext.AllowDuplicateNames(true), + // preserve the old jsonv1 behavior in case of invalid data + jsontext.AllowInvalidUTF8(true), + ) } // XML writes an XML response. diff --git a/tools/router/event_test.go b/tools/router/event_test.go index 28f1138116..542ed98e60 100644 --- a/tools/router/event_test.go +++ b/tools/router/event_test.go @@ -3,6 +3,7 @@ package router_test import ( "bytes" "crypto/tls" + "encoding/json/jsontext" "encoding/json/v2" "encoding/xml" "errors" @@ -19,7 +20,9 @@ import ( "testing" validation "github.com/pocketbase/ozzo-validation/v4" + "github.com/pocketbase/pocketbase/tools/picker" "github.com/pocketbase/pocketbase/tools/router" + "github.com/pocketbase/pocketbase/tools/types" ) type unwrapTester struct { @@ -220,6 +223,8 @@ func TestEventRemoteIP(t *testing.T) { } func TestFindUploadedFiles(t *testing.T) { + t.Parallel() + scenarios := []struct { filename string expectedPattern string @@ -273,6 +278,8 @@ func TestFindUploadedFiles(t *testing.T) { } func TestFindUploadedFilesMissing(t *testing.T) { + t.Parallel() + body := new(bytes.Buffer) mp := multipart.NewWriter(body) mp.Close() @@ -293,6 +300,8 @@ func TestFindUploadedFilesMissing(t *testing.T) { } func TestEventSetGet(t *testing.T) { + t.Parallel() + event := router.Event{} // get before any set (ensures that doesn't panic) @@ -324,6 +333,8 @@ func TestEventSetGet(t *testing.T) { } func TestEventSetAllGetAll(t *testing.T) { + t.Parallel() + data := map[string]any{ "a": 123, "b": 456, @@ -351,6 +362,8 @@ func TestEventSetAllGetAll(t *testing.T) { } func TestEventString(t *testing.T) { + t.Parallel() + scenarios := []testResponseWriteScenario[string]{ { name: "no explicit content-type", @@ -380,6 +393,8 @@ func TestEventString(t *testing.T) { } func TestEventHTML(t *testing.T) { + t.Parallel() + scenarios := []testResponseWriteScenario[string]{ { name: "no explicit content-type", @@ -409,14 +424,17 @@ func TestEventHTML(t *testing.T) { } func TestEventJSON(t *testing.T) { + t.Parallel() + body := map[string]any{ "a": 123, "b": true, "c": "test", - "d": "\xc3", /* invalid utf8 char to test mangling */ + "d": "\xc3", // invalid utf8 char to test mangling + "e": types.JSONRaw(`{"a":1,"a":2}`), // duplicated keys to ensure compliance with old data } expectedPickedBody := `{"a":123,"c":"test"}` - expectedFullBody := `{"a":123,"b":true,"c":"test","d":"�"}` + expectedFullBody := `{"a":123,"b":true,"c":"test","d":"�","e":{"a":2}}` scenarios := []testResponseWriteScenario[any]{ { @@ -456,7 +474,93 @@ func TestEventJSON(t *testing.T) { } } +func TestEventJSONPickError(t *testing.T) { + t.Parallel() + + req, err := http.NewRequest(http.MethodGet, "/?fields=a:excerpt(-1)", nil) + if err != nil { + t.Fatal(err) + } + + rec := httptest.NewRecorder() + + event := &router.Event{ + Request: req, + Response: &router.ResponseWriter{ResponseWriter: rec}, + } + + err = event.JSON(200, map[string]any{"a": "test"}) + if err == nil { + t.Fatal("Expected JSON to return modifier args err, got nil") + } + + // ensure that no explicit status code was written yet by attempting to write one + // (should do nothing if it was already written) + rec.WriteHeader(567) + + result := rec.Result() + defer result.Body.Close() + + if result.StatusCode != 567 { + t.Fatalf("Expected custom status code, got %d", result.StatusCode) + } +} + +type brokenModifier struct { +} + +func (m *brokenModifier) Modify(val any) (any, error) { + return nil, errors.New("test_error") +} + +func TestEventJSONIgnoredError(t *testing.T) { + t.Parallel() + + picker.Modifiers["broken_ignore"] = func(args ...string) (picker.Modifier, error) { + return &brokenModifier{}, nil + } + + req, err := http.NewRequest(http.MethodGet, "/?fields=a:broken_ignore", nil) + if err != nil { + t.Fatal(err) + } + + rec := httptest.NewRecorder() + + event := &router.Event{ + Request: req, + Response: &router.ResponseWriter{ResponseWriter: rec}, + } + + err = event.JSON(200, map[string]any{"a": "test"}) + if err != nil { + t.Fatalf("Expected nil JSON result, got error %v", err) + } + + // (should do nothing if it was already written) + rec.WriteHeader(567) + + result := rec.Result() + defer result.Body.Close() + + rawBody, err := io.ReadAll(result.Body) + if err != nil { + t.Fatal(err) + } + + if result.StatusCode != http.StatusOK { + t.Fatalf("Expected %d status code, got %d", http.StatusOK, result.StatusCode) + } + + expected := `{"a":"test"}` + if string(rawBody) != expected { + t.Fatalf("Expected json\n%s\ngot\n%s", expected, rawBody) + } +} + func TestEventXML(t *testing.T) { + t.Parallel() + scenarios := []testResponseWriteScenario[string]{ { name: "no explicit content-type", @@ -486,6 +590,8 @@ func TestEventXML(t *testing.T) { } func TestEventStream(t *testing.T) { + t.Parallel() + scenarios := []testResponseWriteScenario[string]{ { name: "stream", @@ -506,6 +612,8 @@ func TestEventStream(t *testing.T) { } func TestEventBlob(t *testing.T) { + t.Parallel() + scenarios := []testResponseWriteScenario[[]byte]{ { name: "blob", @@ -526,6 +634,8 @@ func TestEventBlob(t *testing.T) { } func TestEventNoContent(t *testing.T) { + t.Parallel() + s := testResponseWriteScenario[any]{ name: "no content", status: 234, @@ -542,6 +652,8 @@ func TestEventNoContent(t *testing.T) { } func TestEventFlush(t *testing.T) { + t.Parallel() + rec := httptest.NewRecorder() event := &router.Event{ @@ -556,6 +668,8 @@ func TestEventFlush(t *testing.T) { } func TestEventRedirect(t *testing.T) { + t.Parallel() + scenarios := []testResponseWriteScenario[any]{ { name: "non-30x status", @@ -580,6 +694,8 @@ func TestEventRedirect(t *testing.T) { } func TestEventFileFS(t *testing.T) { + t.Parallel() + // stub test files // --- dir, err := os.MkdirTemp("", "EventFileFS") @@ -676,6 +792,8 @@ func TestEventFileFS(t *testing.T) { } func TestEventError(t *testing.T) { + t.Parallel() + err := new(router.Event).Error(123, "message_test", map[string]any{"a": validation.Required, "b": "test"}) result, _ := json.Marshal(err, json.Deterministic(true)) @@ -687,6 +805,8 @@ func TestEventError(t *testing.T) { } func TestEventBadRequestError(t *testing.T) { + t.Parallel() + err := new(router.Event).BadRequestError("message_test", map[string]any{"a": validation.Required, "b": "test"}) result, _ := json.Marshal(err, json.Deterministic(true)) @@ -698,6 +818,8 @@ func TestEventBadRequestError(t *testing.T) { } func TestEventNotFoundError(t *testing.T) { + t.Parallel() + err := new(router.Event).NotFoundError("message_test", map[string]any{"a": validation.Required, "b": "test"}) result, _ := json.Marshal(err, json.Deterministic(true)) @@ -709,6 +831,8 @@ func TestEventNotFoundError(t *testing.T) { } func TestEventForbiddenError(t *testing.T) { + t.Parallel() + err := new(router.Event).ForbiddenError("message_test", map[string]any{"a": validation.Required, "b": "test"}) result, _ := json.Marshal(err, json.Deterministic(true)) @@ -720,6 +844,8 @@ func TestEventForbiddenError(t *testing.T) { } func TestEventUnauthorizedError(t *testing.T) { + t.Parallel() + err := new(router.Event).UnauthorizedError("message_test", map[string]any{"a": validation.Required, "b": "test"}) result, _ := json.Marshal(err, json.Deterministic(true)) @@ -731,6 +857,8 @@ func TestEventUnauthorizedError(t *testing.T) { } func TestEventTooManyRequestsError(t *testing.T) { + t.Parallel() + err := new(router.Event).TooManyRequestsError("message_test", map[string]any{"a": validation.Required, "b": "test"}) result, _ := json.Marshal(err, json.Deterministic(true)) @@ -742,6 +870,8 @@ func TestEventTooManyRequestsError(t *testing.T) { } func TestEventInternalServerError(t *testing.T) { + t.Parallel() + err := new(router.Event).InternalServerError("message_test", map[string]any{"a": validation.Required, "b": "test"}) result, _ := json.Marshal(err, json.Deterministic(true)) @@ -753,6 +883,8 @@ func TestEventInternalServerError(t *testing.T) { } func TestEventBindBody(t *testing.T) { + t.Parallel() + type testDstStruct struct { A int `json:"a" xml:"a" form:"a"` B int `json:"b" xml:"b" form:"b"` @@ -945,9 +1077,9 @@ func testEventResponseWrite[T any]( // try to deserialize into a map and then serialize again in a // deterministic manner in case it is json var jsonBody any - err = json.Unmarshal(rawBody, &jsonBody) + err = json.Unmarshal(rawBody, &jsonBody, jsontext.AllowDuplicateNames(true)) if err == nil { - normalized, err := json.Marshal(jsonBody, json.Deterministic(true)) + normalized, err := json.Marshal(jsonBody, json.Deterministic(true), jsontext.AllowDuplicateNames(true)) if err != nil { t.Fatalf("Failed to deterministicly serialize json body\n%s\ngot\n%v", jsonBody, err) } diff --git a/tools/search/filter_test.go b/tools/search/filter_test.go index 6f5d766338..9322bdd510 100644 --- a/tools/search/filter_test.go +++ b/tools/search/filter_test.go @@ -144,7 +144,7 @@ func TestFilterDataBuildExpr(t *testing.T) { "geoDistance function", "geoDistance(1,2,3,4) < 567", false, - "(6371 * acos(cos(radians({:TEST})) * cos(radians({:TEST})) * cos(radians({:TEST}) - radians({:TEST})) + sin(radians({:TEST})) * sin(radians({:TEST})))) < {:TEST}", + "(6371 * acos(min(1, max(-1, cos(radians({:TEST})) * cos(radians({:TEST})) * cos(radians({:TEST}) - radians({:TEST})) + sin(radians({:TEST})) * sin(radians({:TEST})))))) < {:TEST}", }, } diff --git a/tools/search/token_functions.go b/tools/search/token_functions.go index 1fc5449a78..03edd5e63e 100644 --- a/tools/search/token_functions.go +++ b/tools/search/token_functions.go @@ -49,11 +49,14 @@ var TokenFunctions = map[string]func( return &ResolverResult{ NullFallback: NullFallbackDisabled, - Identifier: `(6371 * acos(` + + // the clamping is to prevent floating point rounding errors for values like + // "1.0002" that could occur for example when comparing identical points + // (see the NULL note for arccosine in https://sqlite.org/lang_mathfunc.html#overview) + Identifier: `(6371 * acos(min(1, max(-1, ` + `cos(radians(` + latA + `)) * cos(radians(` + latB + `)) * ` + `cos(radians(` + lonB + `) - radians(` + lonA + `)) + ` + `sin(radians(` + latA + `)) * sin(radians(` + latB + `))` + - `))`, + `))))`, Params: mergeParams(resolvedArgs[0].Params, resolvedArgs[1].Params, resolvedArgs[2].Params, resolvedArgs[3].Params), }, nil }, diff --git a/tools/search/token_functions_test.go b/tools/search/token_functions_test.go index fa9ed6a43e..7221145e59 100644 --- a/tools/search/token_functions_test.go +++ b/tools/search/token_functions_test.go @@ -117,7 +117,7 @@ func TestTokenFunctionsGeoDistance(t *testing.T) { baseTokenResolver, &ResolverResult{ NullFallback: NullFallbackDisabled, - Identifier: `(6371 * acos(cos(radians({:latA})) * cos(radians({:latB})) * cos(radians({:lonB}) - radians({:lonA})) + sin(radians({:latA})) * sin(radians({:latB}))))`, + Identifier: `(6371 * acos(min(1, max(-1, 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, @@ -138,7 +138,7 @@ func TestTokenFunctionsGeoDistance(t *testing.T) { baseTokenResolver, &ResolverResult{ NullFallback: NullFallbackDisabled, - Identifier: `(6371 * acos(cos(radians({:latA})) * cos(radians({:latB})) * cos(radians({:lonB}) - radians({:lonA})) + sin(radians({:latA})) * sin(radians({:latB}))))`, + Identifier: `(6371 * acos(min(1, max(-1, 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, @@ -178,34 +178,64 @@ func TestTokenFunctionsGeoDistanceExec(t *testing.T) { t.Error("Expected geoDistance 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 + scenarios := []struct { + name string + coords []string // [lonA, latA, lonB, latB] + expected string + }{ + { + "distinct points", + []string{ + "23.23033854945808", + "42.713146090563384", + "23.44920680886216", + "42.7078484153991", + }, + "17.89", + }, + { + "identical points (rounding check with 8 lat)", + []string{"0", "8", "0", "8"}, // 8 is an example latitude where rounding happens to result in > 1.0 + "0.00", + }, + { + "identical points (rounding check with 45 lat)", + []string{"0", "45", "0", "45"}, // 45 is an example latitude where rounding happens to result in > 1.0 + "0.00", }, - fexpr.Token{Literal: "23.23033854945808", Type: fexpr.TokenNumber}, - fexpr.Token{Literal: "42.713146090563384", Type: fexpr.TokenNumber}, - fexpr.Token{Literal: "23.44920680886216", Type: fexpr.TokenNumber}, - fexpr.Token{Literal: "42.7078484153991", Type: fexpr.TokenNumber}, - ) - if err != nil { - t.Fatal(err) } - column := []float64{} - err = testDB.NewQuery("select " + result.Identifier).Bind(result.Params).Column(&column) - if err != nil { - t.Fatal(err) - } + for _, s := range scenarios { + t.Run(s.name, func(t *testing.T) { + 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: s.coords[0], Type: fexpr.TokenNumber}, + fexpr.Token{Literal: s.coords[1], Type: fexpr.TokenNumber}, + fexpr.Token{Literal: s.coords[2], Type: fexpr.TokenNumber}, + fexpr.Token{Literal: s.coords[3], Type: fexpr.TokenNumber}, + ) + if err != nil { + t.Fatal(err) + } - if len(column) != 1 { - t.Fatalf("Expected exactly 1 column value as result, got %v", column) - } + column := []float64{} + err = testDB.NewQuery("select " + result.Identifier).Bind(result.Params).Column(&column) + if err != nil { + t.Fatal(err) + } - expected := "17.89" - distance := fmt.Sprintf("%.2f", column[0]) - if distance != expected { - t.Fatalf("Expected distance value %s, got %s", expected, distance) + if len(column) != 1 { + t.Fatalf("Expected exactly 1 column value as result, got %v", column) + } + + distance := fmt.Sprintf("%.2f", column[0]) + if distance != s.expected { + t.Fatalf("Expected distance value %s, got %s", s.expected, distance) + } + }) } } diff --git a/tools/types/json_raw.go b/tools/types/json_raw.go index d228e41ce5..cb0ba093af 100644 --- a/tools/types/json_raw.go +++ b/tools/types/json_raw.go @@ -7,6 +7,8 @@ import ( "errors" ) +// @todo consider deprecating in favour of jsontext.Value + // JSONRaw defines a json value type that is safe for db read/write. type JSONRaw []byte diff --git a/ui/.env b/ui/.env index 9210a03beb..959e41dd60 100644 --- a/ui/.env +++ b/ui/.env @@ -12,4 +12,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.40.2" +PB_VERSION = "v0.40.3" diff --git a/ui/dist/assets/index-CZinEv5W.css b/ui/dist/assets/index-CZinEv5W.css deleted file mode 100644 index df55213a29..0000000000 --- a/ui/dist/assets/index-CZinEv5W.css +++ /dev/null @@ -1 +0,0 @@ -@font-face{font-display:block;font-family:remixicon;src:url(../fonts/remixicon/remixicon.woff2?t=1734404658139)format("woff2")}@font-face{font-display:block;font-family:IBM Plex Sans;font-style:normal;font-weight:400;src:url(../fonts/ibm-plex-sans/ibm-plex-sans-v23-cyrillic_latin_latin-ext-regular.woff2)format("woff2")}@font-face{font-display:block;font-family:IBM Plex Sans;font-style:italic;font-weight:400;src:url(../fonts/ibm-plex-sans/ibm-plex-sans-v23-cyrillic_latin_latin-ext-italic.woff2)format("woff2")}@font-face{font-display:block;font-family:IBM Plex Sans;font-style:normal;font-weight:600;src:url(../fonts/ibm-plex-sans/ibm-plex-sans-v23-cyrillic_latin_latin-ext-600.woff2)format("woff2")}@font-face{font-display:block;font-family:IBM Plex Sans;font-style:italic;font-weight:600;src:url(../fonts/ibm-plex-sans/ibm-plex-sans-v23-cyrillic_latin_latin-ext-600italic.woff2)format("woff2")}@font-face{font-display:swap;font-family:IBM Plex Mono;font-style:normal;font-weight:400;src:url(../fonts/ibm-plex-mono/ibm-plex-mono-v20-latin-regular.woff2)format("woff2")}@font-face{font-display:swap;font-family:IBM Plex Mono;font-style:normal;font-weight:600;src:url(../fonts/ibm-plex-mono/ibm-plex-mono-v20-latin-600.woff2)format("woff2")}.ri-24-hours-fill:before{content:""}.ri-24-hours-line:before{content:""}.ri-4k-fill:before{content:""}.ri-4k-line:before{content:""}.ri-a-b:before{content:""}.ri-account-box-fill:before{content:""}.ri-account-box-line:before{content:""}.ri-account-circle-fill:before{content:""}.ri-account-circle-line:before{content:""}.ri-account-pin-box-fill:before{content:""}.ri-account-pin-box-line:before{content:""}.ri-account-pin-circle-fill:before{content:""}.ri-account-pin-circle-line:before{content:""}.ri-add-box-fill:before{content:""}.ri-add-box-line:before{content:""}.ri-add-circle-fill:before{content:""}.ri-add-circle-line:before{content:""}.ri-add-fill:before{content:""}.ri-add-line:before{content:""}.ri-admin-fill:before{content:""}.ri-admin-line:before{content:""}.ri-advertisement-fill:before{content:""}.ri-advertisement-line:before{content:""}.ri-airplay-fill:before{content:""}.ri-airplay-line:before{content:""}.ri-alarm-fill:before{content:""}.ri-alarm-line:before{content:""}.ri-alarm-warning-fill:before{content:""}.ri-alarm-warning-line:before{content:""}.ri-album-fill:before{content:""}.ri-album-line:before{content:""}.ri-alert-fill:before{content:""}.ri-alert-line:before{content:""}.ri-aliens-fill:before{content:""}.ri-aliens-line:before{content:""}.ri-align-bottom:before{content:""}.ri-align-center:before{content:""}.ri-align-justify:before{content:""}.ri-align-left:before{content:""}.ri-align-right:before{content:""}.ri-align-top:before{content:""}.ri-align-vertically:before{content:""}.ri-alipay-fill:before{content:""}.ri-alipay-line:before{content:""}.ri-amazon-fill:before{content:""}.ri-amazon-line:before{content:""}.ri-anchor-fill:before{content:""}.ri-anchor-line:before{content:""}.ri-ancient-gate-fill:before{content:""}.ri-ancient-gate-line:before{content:""}.ri-ancient-pavilion-fill:before{content:""}.ri-ancient-pavilion-line:before{content:""}.ri-android-fill:before{content:""}.ri-android-line:before{content:""}.ri-angularjs-fill:before{content:""}.ri-angularjs-line:before{content:""}.ri-anticlockwise-2-fill:before{content:""}.ri-anticlockwise-2-line:before{content:""}.ri-anticlockwise-fill:before{content:""}.ri-anticlockwise-line:before{content:""}.ri-app-store-fill:before{content:""}.ri-app-store-line:before{content:""}.ri-apple-fill:before{content:""}.ri-apple-line:before{content:""}.ri-apps-2-fill:before{content:""}.ri-apps-2-line:before{content:""}.ri-apps-fill:before{content:""}.ri-apps-line:before{content:""}.ri-archive-drawer-fill:before{content:""}.ri-archive-drawer-line:before{content:""}.ri-archive-fill:before{content:""}.ri-archive-line:before{content:""}.ri-arrow-down-circle-fill:before{content:""}.ri-arrow-down-circle-line:before{content:""}.ri-arrow-down-fill:before{content:""}.ri-arrow-down-line:before{content:""}.ri-arrow-down-s-fill:before{content:""}.ri-arrow-down-s-line:before{content:""}.ri-arrow-drop-down-fill:before{content:""}.ri-arrow-drop-down-line:before{content:""}.ri-arrow-drop-left-fill:before{content:""}.ri-arrow-drop-left-line:before{content:""}.ri-arrow-drop-right-fill:before{content:""}.ri-arrow-drop-right-line:before{content:""}.ri-arrow-drop-up-fill:before{content:""}.ri-arrow-drop-up-line:before{content:""}.ri-arrow-go-back-fill:before{content:""}.ri-arrow-go-back-line:before{content:""}.ri-arrow-go-forward-fill:before{content:""}.ri-arrow-go-forward-line:before{content:""}.ri-arrow-left-circle-fill:before{content:""}.ri-arrow-left-circle-line:before{content:""}.ri-arrow-left-down-fill:before{content:""}.ri-arrow-left-down-line:before{content:""}.ri-arrow-left-fill:before{content:""}.ri-arrow-left-line:before{content:""}.ri-arrow-left-right-fill:before{content:""}.ri-arrow-left-right-line:before{content:""}.ri-arrow-left-s-fill:before{content:""}.ri-arrow-left-s-line:before{content:""}.ri-arrow-left-up-fill:before{content:""}.ri-arrow-left-up-line:before{content:""}.ri-arrow-right-circle-fill:before{content:""}.ri-arrow-right-circle-line:before{content:""}.ri-arrow-right-down-fill:before{content:""}.ri-arrow-right-down-line:before{content:""}.ri-arrow-right-fill:before{content:""}.ri-arrow-right-line:before{content:""}.ri-arrow-right-s-fill:before{content:""}.ri-arrow-right-s-line:before{content:""}.ri-arrow-right-up-fill:before{content:""}.ri-arrow-right-up-line:before{content:""}.ri-arrow-up-circle-fill:before{content:""}.ri-arrow-up-circle-line:before{content:""}.ri-arrow-up-down-fill:before{content:""}.ri-arrow-up-down-line:before{content:""}.ri-arrow-up-fill:before{content:""}.ri-arrow-up-line:before{content:""}.ri-arrow-up-s-fill:before{content:""}.ri-arrow-up-s-line:before{content:""}.ri-artboard-2-fill:before{content:""}.ri-artboard-2-line:before{content:""}.ri-artboard-fill:before{content:""}.ri-artboard-line:before{content:""}.ri-article-fill:before{content:""}.ri-article-line:before{content:""}.ri-aspect-ratio-fill:before{content:""}.ri-aspect-ratio-line:before{content:""}.ri-asterisk:before{content:""}.ri-at-fill:before{content:""}.ri-at-line:before{content:""}.ri-attachment-2:before{content:""}.ri-attachment-fill:before{content:""}.ri-attachment-line:before{content:""}.ri-auction-fill:before{content:""}.ri-auction-line:before{content:""}.ri-award-fill:before{content:""}.ri-award-line:before{content:""}.ri-baidu-fill:before{content:""}.ri-baidu-line:before{content:""}.ri-ball-pen-fill:before{content:""}.ri-ball-pen-line:before{content:""}.ri-bank-card-2-fill:before{content:""}.ri-bank-card-2-line:before{content:""}.ri-bank-card-fill:before{content:""}.ri-bank-card-line:before{content:""}.ri-bank-fill:before{content:""}.ri-bank-line:before{content:""}.ri-bar-chart-2-fill:before{content:""}.ri-bar-chart-2-line:before{content:""}.ri-bar-chart-box-fill:before{content:""}.ri-bar-chart-box-line:before{content:""}.ri-bar-chart-fill:before{content:""}.ri-bar-chart-grouped-fill:before{content:""}.ri-bar-chart-grouped-line:before{content:""}.ri-bar-chart-horizontal-fill:before{content:""}.ri-bar-chart-horizontal-line:before{content:""}.ri-bar-chart-line:before{content:""}.ri-barcode-box-fill:before{content:""}.ri-barcode-box-line:before{content:""}.ri-barcode-fill:before{content:""}.ri-barcode-line:before{content:""}.ri-barricade-fill:before{content:""}.ri-barricade-line:before{content:""}.ri-base-station-fill:before{content:""}.ri-base-station-line:before{content:""}.ri-basketball-fill:before{content:""}.ri-basketball-line:before{content:""}.ri-battery-2-charge-fill:before{content:""}.ri-battery-2-charge-line:before{content:""}.ri-battery-2-fill:before{content:""}.ri-battery-2-line:before{content:""}.ri-battery-charge-fill:before{content:""}.ri-battery-charge-line:before{content:""}.ri-battery-fill:before{content:""}.ri-battery-line:before{content:""}.ri-battery-low-fill:before{content:""}.ri-battery-low-line:before{content:""}.ri-battery-saver-fill:before{content:""}.ri-battery-saver-line:before{content:""}.ri-battery-share-fill:before{content:""}.ri-battery-share-line:before{content:""}.ri-bear-smile-fill:before{content:""}.ri-bear-smile-line:before{content:""}.ri-behance-fill:before{content:""}.ri-behance-line:before{content:""}.ri-bell-fill:before{content:""}.ri-bell-line:before{content:""}.ri-bike-fill:before{content:""}.ri-bike-line:before{content:""}.ri-bilibili-fill:before{content:""}.ri-bilibili-line:before{content:""}.ri-bill-fill:before{content:""}.ri-bill-line:before{content:""}.ri-billiards-fill:before{content:""}.ri-billiards-line:before{content:""}.ri-bit-coin-fill:before{content:""}.ri-bit-coin-line:before{content:""}.ri-blaze-fill:before{content:""}.ri-blaze-line:before{content:""}.ri-bluetooth-connect-fill:before{content:""}.ri-bluetooth-connect-line:before{content:""}.ri-bluetooth-fill:before{content:""}.ri-bluetooth-line:before{content:""}.ri-blur-off-fill:before{content:""}.ri-blur-off-line:before{content:""}.ri-body-scan-fill:before{content:""}.ri-body-scan-line:before{content:""}.ri-bold:before{content:""}.ri-book-2-fill:before{content:""}.ri-book-2-line:before{content:""}.ri-book-3-fill:before{content:""}.ri-book-3-line:before{content:""}.ri-book-fill:before{content:""}.ri-book-line:before{content:""}.ri-book-marked-fill:before{content:""}.ri-book-marked-line:before{content:""}.ri-book-open-fill:before{content:""}.ri-book-open-line:before{content:""}.ri-book-read-fill:before{content:""}.ri-book-read-line:before{content:""}.ri-booklet-fill:before{content:""}.ri-booklet-line:before{content:""}.ri-bookmark-2-fill:before{content:""}.ri-bookmark-2-line:before{content:""}.ri-bookmark-3-fill:before{content:""}.ri-bookmark-3-line:before{content:""}.ri-bookmark-fill:before{content:""}.ri-bookmark-line:before{content:""}.ri-boxing-fill:before{content:""}.ri-boxing-line:before{content:""}.ri-braces-fill:before{content:""}.ri-braces-line:before{content:""}.ri-brackets-fill:before{content:""}.ri-brackets-line:before{content:""}.ri-briefcase-2-fill:before{content:""}.ri-briefcase-2-line:before{content:""}.ri-briefcase-3-fill:before{content:""}.ri-briefcase-3-line:before{content:""}.ri-briefcase-4-fill:before{content:""}.ri-briefcase-4-line:before{content:""}.ri-briefcase-5-fill:before{content:""}.ri-briefcase-5-line:before{content:""}.ri-briefcase-fill:before{content:""}.ri-briefcase-line:before{content:""}.ri-bring-forward:before{content:""}.ri-bring-to-front:before{content:""}.ri-broadcast-fill:before{content:""}.ri-broadcast-line:before{content:""}.ri-brush-2-fill:before{content:""}.ri-brush-2-line:before{content:""}.ri-brush-3-fill:before{content:""}.ri-brush-3-line:before{content:""}.ri-brush-4-fill:before{content:""}.ri-brush-4-line:before{content:""}.ri-brush-fill:before{content:""}.ri-brush-line:before{content:""}.ri-bubble-chart-fill:before{content:""}.ri-bubble-chart-line:before{content:""}.ri-bug-2-fill:before{content:""}.ri-bug-2-line:before{content:""}.ri-bug-fill:before{content:""}.ri-bug-line:before{content:""}.ri-building-2-fill:before{content:""}.ri-building-2-line:before{content:""}.ri-building-3-fill:before{content:""}.ri-building-3-line:before{content:""}.ri-building-4-fill:before{content:""}.ri-building-4-line:before{content:""}.ri-building-fill:before{content:""}.ri-building-line:before{content:""}.ri-bus-2-fill:before{content:""}.ri-bus-2-line:before{content:""}.ri-bus-fill:before{content:""}.ri-bus-line:before{content:""}.ri-bus-wifi-fill:before{content:""}.ri-bus-wifi-line:before{content:""}.ri-cactus-fill:before{content:""}.ri-cactus-line:before{content:""}.ri-cake-2-fill:before{content:""}.ri-cake-2-line:before{content:""}.ri-cake-3-fill:before{content:""}.ri-cake-3-line:before{content:""}.ri-cake-fill:before{content:""}.ri-cake-line:before{content:""}.ri-calculator-fill:before{content:""}.ri-calculator-line:before{content:""}.ri-calendar-2-fill:before{content:""}.ri-calendar-2-line:before{content:""}.ri-calendar-check-fill:before{content:""}.ri-calendar-check-line:before{content:""}.ri-calendar-event-fill:before{content:""}.ri-calendar-event-line:before{content:""}.ri-calendar-fill:before{content:""}.ri-calendar-line:before{content:""}.ri-calendar-todo-fill:before{content:""}.ri-calendar-todo-line:before{content:""}.ri-camera-2-fill:before{content:""}.ri-camera-2-line:before{content:""}.ri-camera-3-fill:before{content:""}.ri-camera-3-line:before{content:""}.ri-camera-fill:before{content:""}.ri-camera-lens-fill:before{content:""}.ri-camera-lens-line:before{content:""}.ri-camera-line:before{content:""}.ri-camera-off-fill:before{content:""}.ri-camera-off-line:before{content:""}.ri-camera-switch-fill:before{content:""}.ri-camera-switch-line:before{content:""}.ri-capsule-fill:before{content:""}.ri-capsule-line:before{content:""}.ri-car-fill:before{content:""}.ri-car-line:before{content:""}.ri-car-washing-fill:before{content:""}.ri-car-washing-line:before{content:""}.ri-caravan-fill:before{content:""}.ri-caravan-line:before{content:""}.ri-cast-fill:before{content:""}.ri-cast-line:before{content:""}.ri-cellphone-fill:before{content:""}.ri-cellphone-line:before{content:""}.ri-celsius-fill:before{content:""}.ri-celsius-line:before{content:""}.ri-centos-fill:before{content:""}.ri-centos-line:before{content:""}.ri-character-recognition-fill:before{content:""}.ri-character-recognition-line:before{content:""}.ri-charging-pile-2-fill:before{content:""}.ri-charging-pile-2-line:before{content:""}.ri-charging-pile-fill:before{content:""}.ri-charging-pile-line:before{content:""}.ri-chat-1-fill:before{content:""}.ri-chat-1-line:before{content:""}.ri-chat-2-fill:before{content:""}.ri-chat-2-line:before{content:""}.ri-chat-3-fill:before{content:""}.ri-chat-3-line:before{content:""}.ri-chat-4-fill:before{content:""}.ri-chat-4-line:before{content:""}.ri-chat-check-fill:before{content:""}.ri-chat-check-line:before{content:""}.ri-chat-delete-fill:before{content:""}.ri-chat-delete-line:before{content:""}.ri-chat-download-fill:before{content:""}.ri-chat-download-line:before{content:""}.ri-chat-follow-up-fill:before{content:""}.ri-chat-follow-up-line:before{content:""}.ri-chat-forward-fill:before{content:""}.ri-chat-forward-line:before{content:""}.ri-chat-heart-fill:before{content:""}.ri-chat-heart-line:before{content:""}.ri-chat-history-fill:before{content:""}.ri-chat-history-line:before{content:""}.ri-chat-new-fill:before{content:""}.ri-chat-new-line:before{content:""}.ri-chat-off-fill:before{content:""}.ri-chat-off-line:before{content:""}.ri-chat-poll-fill:before{content:""}.ri-chat-poll-line:before{content:""}.ri-chat-private-fill:before{content:""}.ri-chat-private-line:before{content:""}.ri-chat-quote-fill:before{content:""}.ri-chat-quote-line:before{content:""}.ri-chat-settings-fill:before{content:""}.ri-chat-settings-line:before{content:""}.ri-chat-smile-2-fill:before{content:""}.ri-chat-smile-2-line:before{content:""}.ri-chat-smile-3-fill:before{content:""}.ri-chat-smile-3-line:before{content:""}.ri-chat-smile-fill:before{content:""}.ri-chat-smile-line:before{content:""}.ri-chat-upload-fill:before{content:""}.ri-chat-upload-line:before{content:""}.ri-chat-voice-fill:before{content:""}.ri-chat-voice-line:before{content:""}.ri-check-double-fill:before{content:""}.ri-check-double-line:before{content:""}.ri-check-fill:before{content:""}.ri-check-line:before{content:""}.ri-checkbox-blank-circle-fill:before{content:""}.ri-checkbox-blank-circle-line:before{content:""}.ri-checkbox-blank-fill:before{content:""}.ri-checkbox-blank-line:before{content:""}.ri-checkbox-circle-fill:before{content:""}.ri-checkbox-circle-line:before{content:""}.ri-checkbox-fill:before{content:""}.ri-checkbox-indeterminate-fill:before{content:""}.ri-checkbox-indeterminate-line:before{content:""}.ri-checkbox-line:before{content:""}.ri-checkbox-multiple-blank-fill:before{content:""}.ri-checkbox-multiple-blank-line:before{content:""}.ri-checkbox-multiple-fill:before{content:""}.ri-checkbox-multiple-line:before{content:""}.ri-china-railway-fill:before{content:""}.ri-china-railway-line:before{content:""}.ri-chrome-fill:before{content:""}.ri-chrome-line:before{content:""}.ri-clapperboard-fill:before{content:""}.ri-clapperboard-line:before{content:""}.ri-clipboard-fill:before{content:""}.ri-clipboard-line:before{content:""}.ri-clockwise-2-fill:before{content:""}.ri-clockwise-2-line:before{content:""}.ri-clockwise-fill:before{content:""}.ri-clockwise-line:before{content:""}.ri-close-circle-fill:before{content:""}.ri-close-circle-line:before{content:""}.ri-close-fill:before{content:""}.ri-close-line:before{content:""}.ri-closed-captioning-fill:before{content:""}.ri-closed-captioning-line:before{content:""}.ri-cloud-fill:before{content:""}.ri-cloud-line:before{content:""}.ri-cloud-off-fill:before{content:""}.ri-cloud-off-line:before{content:""}.ri-cloud-windy-fill:before{content:""}.ri-cloud-windy-line:before{content:""}.ri-cloudy-2-fill:before{content:""}.ri-cloudy-2-line:before{content:""}.ri-cloudy-fill:before{content:""}.ri-cloudy-line:before{content:""}.ri-code-box-fill:before{content:""}.ri-code-box-line:before{content:""}.ri-code-fill:before{content:""}.ri-code-line:before{content:""}.ri-code-s-fill:before{content:""}.ri-code-s-line:before{content:""}.ri-code-s-slash-fill:before{content:""}.ri-code-s-slash-line:before{content:""}.ri-code-view:before{content:""}.ri-codepen-fill:before{content:""}.ri-codepen-line:before{content:""}.ri-coin-fill:before{content:""}.ri-coin-line:before{content:""}.ri-coins-fill:before{content:""}.ri-coins-line:before{content:""}.ri-collage-fill:before{content:""}.ri-collage-line:before{content:""}.ri-command-fill:before{content:""}.ri-command-line:before{content:""}.ri-community-fill:before{content:""}.ri-community-line:before{content:""}.ri-compass-2-fill:before{content:""}.ri-compass-2-line:before{content:""}.ri-compass-3-fill:before{content:""}.ri-compass-3-line:before{content:""}.ri-compass-4-fill:before{content:""}.ri-compass-4-line:before{content:""}.ri-compass-discover-fill:before{content:""}.ri-compass-discover-line:before{content:""}.ri-compass-fill:before{content:""}.ri-compass-line:before{content:""}.ri-compasses-2-fill:before{content:""}.ri-compasses-2-line:before{content:""}.ri-compasses-fill:before{content:""}.ri-compasses-line:before{content:""}.ri-computer-fill:before{content:""}.ri-computer-line:before{content:""}.ri-contacts-book-2-fill:before{content:""}.ri-contacts-book-2-line:before{content:""}.ri-contacts-book-fill:before{content:""}.ri-contacts-book-line:before{content:""}.ri-contacts-book-upload-fill:before{content:""}.ri-contacts-book-upload-line:before{content:""}.ri-contacts-fill:before{content:""}.ri-contacts-line:before{content:""}.ri-contrast-2-fill:before{content:""}.ri-contrast-2-line:before{content:""}.ri-contrast-drop-2-fill:before{content:""}.ri-contrast-drop-2-line:before{content:""}.ri-contrast-drop-fill:before{content:""}.ri-contrast-drop-line:before{content:""}.ri-contrast-fill:before{content:""}.ri-contrast-line:before{content:""}.ri-copper-coin-fill:before{content:""}.ri-copper-coin-line:before{content:""}.ri-copper-diamond-fill:before{content:""}.ri-copper-diamond-line:before{content:""}.ri-copyleft-fill:before{content:""}.ri-copyleft-line:before{content:""}.ri-copyright-fill:before{content:""}.ri-copyright-line:before{content:""}.ri-coreos-fill:before{content:""}.ri-coreos-line:before{content:""}.ri-coupon-2-fill:before{content:""}.ri-coupon-2-line:before{content:""}.ri-coupon-3-fill:before{content:""}.ri-coupon-3-line:before{content:""}.ri-coupon-4-fill:before{content:""}.ri-coupon-4-line:before{content:""}.ri-coupon-5-fill:before{content:""}.ri-coupon-5-line:before{content:""}.ri-coupon-fill:before{content:""}.ri-coupon-line:before{content:""}.ri-cpu-fill:before{content:""}.ri-cpu-line:before{content:""}.ri-creative-commons-by-fill:before{content:""}.ri-creative-commons-by-line:before{content:""}.ri-creative-commons-fill:before{content:""}.ri-creative-commons-line:before{content:""}.ri-creative-commons-nc-fill:before{content:""}.ri-creative-commons-nc-line:before{content:""}.ri-creative-commons-nd-fill:before{content:""}.ri-creative-commons-nd-line:before{content:""}.ri-creative-commons-sa-fill:before{content:""}.ri-creative-commons-sa-line:before{content:""}.ri-creative-commons-zero-fill:before{content:""}.ri-creative-commons-zero-line:before{content:""}.ri-criminal-fill:before{content:""}.ri-criminal-line:before{content:""}.ri-crop-2-fill:before{content:""}.ri-crop-2-line:before{content:""}.ri-crop-fill:before{content:""}.ri-crop-line:before{content:""}.ri-css3-fill:before{content:""}.ri-css3-line:before{content:""}.ri-cup-fill:before{content:""}.ri-cup-line:before{content:""}.ri-currency-fill:before{content:""}.ri-currency-line:before{content:""}.ri-cursor-fill:before{content:""}.ri-cursor-line:before{content:""}.ri-customer-service-2-fill:before{content:""}.ri-customer-service-2-line:before{content:""}.ri-customer-service-fill:before{content:""}.ri-customer-service-line:before{content:""}.ri-dashboard-2-fill:before{content:""}.ri-dashboard-2-line:before{content:""}.ri-dashboard-3-fill:before{content:""}.ri-dashboard-3-line:before{content:""}.ri-dashboard-fill:before{content:""}.ri-dashboard-line:before{content:""}.ri-database-2-fill:before{content:""}.ri-database-2-line:before{content:""}.ri-database-fill:before{content:""}.ri-database-line:before{content:""}.ri-delete-back-2-fill:before{content:""}.ri-delete-back-2-line:before{content:""}.ri-delete-back-fill:before{content:""}.ri-delete-back-line:before{content:""}.ri-delete-bin-2-fill:before{content:""}.ri-delete-bin-2-line:before{content:""}.ri-delete-bin-3-fill:before{content:""}.ri-delete-bin-3-line:before{content:""}.ri-delete-bin-4-fill:before{content:""}.ri-delete-bin-4-line:before{content:""}.ri-delete-bin-5-fill:before{content:""}.ri-delete-bin-5-line:before{content:""}.ri-delete-bin-6-fill:before{content:""}.ri-delete-bin-6-line:before{content:""}.ri-delete-bin-7-fill:before{content:""}.ri-delete-bin-7-line:before{content:""}.ri-delete-bin-fill:before{content:""}.ri-delete-bin-line:before{content:""}.ri-delete-column:before{content:""}.ri-delete-row:before{content:""}.ri-device-fill:before{content:""}.ri-device-line:before{content:""}.ri-device-recover-fill:before{content:""}.ri-device-recover-line:before{content:""}.ri-dingding-fill:before{content:""}.ri-dingding-line:before{content:""}.ri-direction-fill:before{content:""}.ri-direction-line:before{content:""}.ri-disc-fill:before{content:""}.ri-disc-line:before{content:""}.ri-discord-fill:before{content:""}.ri-discord-line:before{content:""}.ri-discuss-fill:before{content:""}.ri-discuss-line:before{content:""}.ri-dislike-fill:before{content:""}.ri-dislike-line:before{content:""}.ri-disqus-fill:before{content:""}.ri-disqus-line:before{content:""}.ri-divide-fill:before{content:""}.ri-divide-line:before{content:""}.ri-donut-chart-fill:before{content:""}.ri-donut-chart-line:before{content:""}.ri-door-closed-fill:before{content:""}.ri-door-closed-line:before{content:""}.ri-door-fill:before{content:""}.ri-door-line:before{content:""}.ri-door-lock-box-fill:before{content:""}.ri-door-lock-box-line:before{content:""}.ri-door-lock-fill:before{content:""}.ri-door-lock-line:before{content:""}.ri-door-open-fill:before{content:""}.ri-door-open-line:before{content:""}.ri-dossier-fill:before{content:""}.ri-dossier-line:before{content:""}.ri-douban-fill:before{content:""}.ri-douban-line:before{content:""}.ri-double-quotes-l:before{content:""}.ri-double-quotes-r:before{content:""}.ri-download-2-fill:before{content:""}.ri-download-2-line:before{content:""}.ri-download-cloud-2-fill:before{content:""}.ri-download-cloud-2-line:before{content:""}.ri-download-cloud-fill:before{content:""}.ri-download-cloud-line:before{content:""}.ri-download-fill:before{content:""}.ri-download-line:before{content:""}.ri-draft-fill:before{content:""}.ri-draft-line:before{content:""}.ri-drag-drop-fill:before{content:""}.ri-drag-drop-line:before{content:""}.ri-drag-move-2-fill:before{content:""}.ri-drag-move-2-line:before{content:""}.ri-drag-move-fill:before{content:""}.ri-drag-move-line:before{content:""}.ri-dribbble-fill:before{content:""}.ri-dribbble-line:before{content:""}.ri-drive-fill:before{content:""}.ri-drive-line:before{content:""}.ri-drizzle-fill:before{content:""}.ri-drizzle-line:before{content:""}.ri-drop-fill:before{content:""}.ri-drop-line:before{content:""}.ri-dropbox-fill:before{content:""}.ri-dropbox-line:before{content:""}.ri-dual-sim-1-fill:before{content:""}.ri-dual-sim-1-line:before{content:""}.ri-dual-sim-2-fill:before{content:""}.ri-dual-sim-2-line:before{content:""}.ri-dv-fill:before{content:""}.ri-dv-line:before{content:""}.ri-dvd-fill:before{content:""}.ri-dvd-line:before{content:""}.ri-e-bike-2-fill:before{content:""}.ri-e-bike-2-line:before{content:""}.ri-e-bike-fill:before{content:""}.ri-e-bike-line:before{content:""}.ri-earth-fill:before{content:""}.ri-earth-line:before{content:""}.ri-earthquake-fill:before{content:""}.ri-earthquake-line:before{content:""}.ri-edge-fill:before{content:""}.ri-edge-line:before{content:""}.ri-edit-2-fill:before{content:""}.ri-edit-2-line:before{content:""}.ri-edit-box-fill:before{content:""}.ri-edit-box-line:before{content:""}.ri-edit-circle-fill:before{content:""}.ri-edit-circle-line:before{content:""}.ri-edit-fill:before{content:""}.ri-edit-line:before{content:""}.ri-eject-fill:before{content:""}.ri-eject-line:before{content:""}.ri-emotion-2-fill:before{content:""}.ri-emotion-2-line:before{content:""}.ri-emotion-fill:before{content:""}.ri-emotion-happy-fill:before{content:""}.ri-emotion-happy-line:before{content:""}.ri-emotion-laugh-fill:before{content:""}.ri-emotion-laugh-line:before{content:""}.ri-emotion-line:before{content:""}.ri-emotion-normal-fill:before{content:""}.ri-emotion-normal-line:before{content:""}.ri-emotion-sad-fill:before{content:""}.ri-emotion-sad-line:before{content:""}.ri-emotion-unhappy-fill:before{content:""}.ri-emotion-unhappy-line:before{content:""}.ri-empathize-fill:before{content:""}.ri-empathize-line:before{content:""}.ri-emphasis-cn:before{content:""}.ri-emphasis:before{content:""}.ri-english-input:before{content:""}.ri-equalizer-fill:before{content:""}.ri-equalizer-line:before{content:""}.ri-eraser-fill:before{content:""}.ri-eraser-line:before{content:""}.ri-error-warning-fill:before{content:""}.ri-error-warning-line:before{content:""}.ri-evernote-fill:before{content:""}.ri-evernote-line:before{content:""}.ri-exchange-box-fill:before{content:""}.ri-exchange-box-line:before{content:""}.ri-exchange-cny-fill:before{content:""}.ri-exchange-cny-line:before{content:""}.ri-exchange-dollar-fill:before{content:""}.ri-exchange-dollar-line:before{content:""}.ri-exchange-fill:before{content:""}.ri-exchange-funds-fill:before{content:""}.ri-exchange-funds-line:before{content:""}.ri-exchange-line:before{content:""}.ri-external-link-fill:before{content:""}.ri-external-link-line:before{content:""}.ri-eye-2-fill:before{content:""}.ri-eye-2-line:before{content:""}.ri-eye-close-fill:before{content:""}.ri-eye-close-line:before{content:""}.ri-eye-fill:before{content:""}.ri-eye-line:before{content:""}.ri-eye-off-fill:before{content:""}.ri-eye-off-line:before{content:""}.ri-facebook-box-fill:before{content:""}.ri-facebook-box-line:before{content:""}.ri-facebook-circle-fill:before{content:""}.ri-facebook-circle-line:before{content:""}.ri-facebook-fill:before{content:""}.ri-facebook-line:before{content:""}.ri-fahrenheit-fill:before{content:""}.ri-fahrenheit-line:before{content:""}.ri-feedback-fill:before{content:""}.ri-feedback-line:before{content:""}.ri-file-2-fill:before{content:""}.ri-file-2-line:before{content:""}.ri-file-3-fill:before{content:""}.ri-file-3-line:before{content:""}.ri-file-4-fill:before{content:""}.ri-file-4-line:before{content:""}.ri-file-add-fill:before{content:""}.ri-file-add-line:before{content:""}.ri-file-chart-2-fill:before{content:""}.ri-file-chart-2-line:before{content:""}.ri-file-chart-fill:before{content:""}.ri-file-chart-line:before{content:""}.ri-file-cloud-fill:before{content:""}.ri-file-cloud-line:before{content:""}.ri-file-code-fill:before{content:""}.ri-file-code-line:before{content:""}.ri-file-copy-2-fill:before{content:""}.ri-file-copy-2-line:before{content:""}.ri-file-copy-fill:before{content:""}.ri-file-copy-line:before{content:""}.ri-file-damage-fill:before{content:""}.ri-file-damage-line:before{content:""}.ri-file-download-fill:before{content:""}.ri-file-download-line:before{content:""}.ri-file-edit-fill:before{content:""}.ri-file-edit-line:before{content:""}.ri-file-excel-2-fill:before{content:""}.ri-file-excel-2-line:before{content:""}.ri-file-excel-fill:before{content:""}.ri-file-excel-line:before{content:""}.ri-file-fill:before{content:""}.ri-file-forbid-fill:before{content:""}.ri-file-forbid-line:before{content:""}.ri-file-gif-fill:before{content:""}.ri-file-gif-line:before{content:""}.ri-file-history-fill:before{content:""}.ri-file-history-line:before{content:""}.ri-file-hwp-fill:before{content:""}.ri-file-hwp-line:before{content:""}.ri-file-info-fill:before{content:""}.ri-file-info-line:before{content:""}.ri-file-line:before{content:""}.ri-file-list-2-fill:before{content:""}.ri-file-list-2-line:before{content:""}.ri-file-list-3-fill:before{content:""}.ri-file-list-3-line:before{content:""}.ri-file-list-fill:before{content:""}.ri-file-list-line:before{content:""}.ri-file-lock-fill:before{content:""}.ri-file-lock-line:before{content:""}.ri-file-marked-fill:before{content:""}.ri-file-marked-line:before{content:""}.ri-file-music-fill:before{content:""}.ri-file-music-line:before{content:""}.ri-file-paper-2-fill:before{content:""}.ri-file-paper-2-line:before{content:""}.ri-file-paper-fill:before{content:""}.ri-file-paper-line:before{content:""}.ri-file-pdf-fill:before{content:""}.ri-file-pdf-line:before{content:""}.ri-file-ppt-2-fill:before{content:""}.ri-file-ppt-2-line:before{content:""}.ri-file-ppt-fill:before{content:""}.ri-file-ppt-line:before{content:""}.ri-file-reduce-fill:before{content:""}.ri-file-reduce-line:before{content:""}.ri-file-search-fill:before{content:""}.ri-file-search-line:before{content:""}.ri-file-settings-fill:before{content:""}.ri-file-settings-line:before{content:""}.ri-file-shield-2-fill:before{content:""}.ri-file-shield-2-line:before{content:""}.ri-file-shield-fill:before{content:""}.ri-file-shield-line:before{content:""}.ri-file-shred-fill:before{content:""}.ri-file-shred-line:before{content:""}.ri-file-text-fill:before{content:""}.ri-file-text-line:before{content:""}.ri-file-transfer-fill:before{content:""}.ri-file-transfer-line:before{content:""}.ri-file-unknow-fill:before{content:""}.ri-file-unknow-line:before{content:""}.ri-file-upload-fill:before{content:""}.ri-file-upload-line:before{content:""}.ri-file-user-fill:before{content:""}.ri-file-user-line:before{content:""}.ri-file-warning-fill:before{content:""}.ri-file-warning-line:before{content:""}.ri-file-word-2-fill:before{content:""}.ri-file-word-2-line:before{content:""}.ri-file-word-fill:before{content:""}.ri-file-word-line:before{content:""}.ri-file-zip-fill:before{content:""}.ri-file-zip-line:before{content:""}.ri-film-fill:before{content:""}.ri-film-line:before{content:""}.ri-filter-2-fill:before{content:""}.ri-filter-2-line:before{content:""}.ri-filter-3-fill:before{content:""}.ri-filter-3-line:before{content:""}.ri-filter-fill:before{content:""}.ri-filter-line:before{content:""}.ri-filter-off-fill:before{content:""}.ri-filter-off-line:before{content:""}.ri-find-replace-fill:before{content:""}.ri-find-replace-line:before{content:""}.ri-finder-fill:before{content:""}.ri-finder-line:before{content:""}.ri-fingerprint-2-fill:before{content:""}.ri-fingerprint-2-line:before{content:""}.ri-fingerprint-fill:before{content:""}.ri-fingerprint-line:before{content:""}.ri-fire-fill:before{content:""}.ri-fire-line:before{content:""}.ri-firefox-fill:before{content:""}.ri-firefox-line:before{content:""}.ri-first-aid-kit-fill:before{content:""}.ri-first-aid-kit-line:before{content:""}.ri-flag-2-fill:before{content:""}.ri-flag-2-line:before{content:""}.ri-flag-fill:before{content:""}.ri-flag-line:before{content:""}.ri-flashlight-fill:before{content:""}.ri-flashlight-line:before{content:""}.ri-flask-fill:before{content:""}.ri-flask-line:before{content:""}.ri-flight-land-fill:before{content:""}.ri-flight-land-line:before{content:""}.ri-flight-takeoff-fill:before{content:""}.ri-flight-takeoff-line:before{content:""}.ri-flood-fill:before{content:""}.ri-flood-line:before{content:""}.ri-flow-chart:before{content:""}.ri-flutter-fill:before{content:""}.ri-flutter-line:before{content:""}.ri-focus-2-fill:before{content:""}.ri-focus-2-line:before{content:""}.ri-focus-3-fill:before{content:""}.ri-focus-3-line:before{content:""}.ri-focus-fill:before{content:""}.ri-focus-line:before{content:""}.ri-foggy-fill:before{content:""}.ri-foggy-line:before{content:""}.ri-folder-2-fill:before{content:""}.ri-folder-2-line:before{content:""}.ri-folder-3-fill:before{content:""}.ri-folder-3-line:before{content:""}.ri-folder-4-fill:before{content:""}.ri-folder-4-line:before{content:""}.ri-folder-5-fill:before{content:""}.ri-folder-5-line:before{content:""}.ri-folder-add-fill:before{content:""}.ri-folder-add-line:before{content:""}.ri-folder-chart-2-fill:before{content:""}.ri-folder-chart-2-line:before{content:""}.ri-folder-chart-fill:before{content:""}.ri-folder-chart-line:before{content:""}.ri-folder-download-fill:before{content:""}.ri-folder-download-line:before{content:""}.ri-folder-fill:before{content:""}.ri-folder-forbid-fill:before{content:""}.ri-folder-forbid-line:before{content:""}.ri-folder-history-fill:before{content:""}.ri-folder-history-line:before{content:""}.ri-folder-info-fill:before{content:""}.ri-folder-info-line:before{content:""}.ri-folder-keyhole-fill:before{content:""}.ri-folder-keyhole-line:before{content:""}.ri-folder-line:before{content:""}.ri-folder-lock-fill:before{content:""}.ri-folder-lock-line:before{content:""}.ri-folder-music-fill:before{content:""}.ri-folder-music-line:before{content:""}.ri-folder-open-fill:before{content:""}.ri-folder-open-line:before{content:""}.ri-folder-received-fill:before{content:""}.ri-folder-received-line:before{content:""}.ri-folder-reduce-fill:before{content:""}.ri-folder-reduce-line:before{content:""}.ri-folder-settings-fill:before{content:""}.ri-folder-settings-line:before{content:""}.ri-folder-shared-fill:before{content:""}.ri-folder-shared-line:before{content:""}.ri-folder-shield-2-fill:before{content:""}.ri-folder-shield-2-line:before{content:""}.ri-folder-shield-fill:before{content:""}.ri-folder-shield-line:before{content:""}.ri-folder-transfer-fill:before{content:""}.ri-folder-transfer-line:before{content:""}.ri-folder-unknow-fill:before{content:""}.ri-folder-unknow-line:before{content:""}.ri-folder-upload-fill:before{content:""}.ri-folder-upload-line:before{content:""}.ri-folder-user-fill:before{content:""}.ri-folder-user-line:before{content:""}.ri-folder-warning-fill:before{content:""}.ri-folder-warning-line:before{content:""}.ri-folder-zip-fill:before{content:""}.ri-folder-zip-line:before{content:""}.ri-folders-fill:before{content:""}.ri-folders-line:before{content:""}.ri-font-color:before{content:""}.ri-font-size-2:before{content:""}.ri-font-size:before{content:""}.ri-football-fill:before{content:""}.ri-football-line:before{content:""}.ri-footprint-fill:before{content:""}.ri-footprint-line:before{content:""}.ri-forbid-2-fill:before{content:""}.ri-forbid-2-line:before{content:""}.ri-forbid-fill:before{content:""}.ri-forbid-line:before{content:""}.ri-format-clear:before{content:""}.ri-fridge-fill:before{content:""}.ri-fridge-line:before{content:""}.ri-fullscreen-exit-fill:before{content:""}.ri-fullscreen-exit-line:before{content:""}.ri-fullscreen-fill:before{content:""}.ri-fullscreen-line:before{content:""}.ri-function-fill:before{content:""}.ri-function-line:before{content:""}.ri-functions:before{content:""}.ri-funds-box-fill:before{content:""}.ri-funds-box-line:before{content:""}.ri-funds-fill:before{content:""}.ri-funds-line:before{content:""}.ri-gallery-fill:before{content:""}.ri-gallery-line:before{content:""}.ri-gallery-upload-fill:before{content:""}.ri-gallery-upload-line:before{content:""}.ri-game-fill:before{content:""}.ri-game-line:before{content:""}.ri-gamepad-fill:before{content:""}.ri-gamepad-line:before{content:""}.ri-gas-station-fill:before{content:""}.ri-gas-station-line:before{content:""}.ri-gatsby-fill:before{content:""}.ri-gatsby-line:before{content:""}.ri-genderless-fill:before{content:""}.ri-genderless-line:before{content:""}.ri-ghost-2-fill:before{content:""}.ri-ghost-2-line:before{content:""}.ri-ghost-fill:before{content:""}.ri-ghost-line:before{content:""}.ri-ghost-smile-fill:before{content:""}.ri-ghost-smile-line:before{content:""}.ri-gift-2-fill:before{content:""}.ri-gift-2-line:before{content:""}.ri-gift-fill:before{content:""}.ri-gift-line:before{content:""}.ri-git-branch-fill:before{content:""}.ri-git-branch-line:before{content:""}.ri-git-commit-fill:before{content:""}.ri-git-commit-line:before{content:""}.ri-git-merge-fill:before{content:""}.ri-git-merge-line:before{content:""}.ri-git-pull-request-fill:before{content:""}.ri-git-pull-request-line:before{content:""}.ri-git-repository-commits-fill:before{content:""}.ri-git-repository-commits-line:before{content:""}.ri-git-repository-fill:before{content:""}.ri-git-repository-line:before{content:""}.ri-git-repository-private-fill:before{content:""}.ri-git-repository-private-line:before{content:""}.ri-github-fill:before{content:""}.ri-github-line:before{content:""}.ri-gitlab-fill:before{content:""}.ri-gitlab-line:before{content:""}.ri-global-fill:before{content:""}.ri-global-line:before{content:""}.ri-globe-fill:before{content:""}.ri-globe-line:before{content:""}.ri-goblet-fill:before{content:""}.ri-goblet-line:before{content:""}.ri-google-fill:before{content:""}.ri-google-line:before{content:""}.ri-google-play-fill:before{content:""}.ri-google-play-line:before{content:""}.ri-government-fill:before{content:""}.ri-government-line:before{content:""}.ri-gps-fill:before{content:""}.ri-gps-line:before{content:""}.ri-gradienter-fill:before{content:""}.ri-gradienter-line:before{content:""}.ri-grid-fill:before{content:""}.ri-grid-line:before{content:""}.ri-group-2-fill:before{content:""}.ri-group-2-line:before{content:""}.ri-group-fill:before{content:""}.ri-group-line:before{content:""}.ri-guide-fill:before{content:""}.ri-guide-line:before{content:""}.ri-h-1:before{content:""}.ri-h-2:before{content:""}.ri-h-3:before{content:""}.ri-h-4:before{content:""}.ri-h-5:before{content:""}.ri-h-6:before{content:""}.ri-hail-fill:before{content:""}.ri-hail-line:before{content:""}.ri-hammer-fill:before{content:""}.ri-hammer-line:before{content:""}.ri-hand-coin-fill:before{content:""}.ri-hand-coin-line:before{content:""}.ri-hand-heart-fill:before{content:""}.ri-hand-heart-line:before{content:""}.ri-hand-sanitizer-fill:before{content:""}.ri-hand-sanitizer-line:before{content:""}.ri-handbag-fill:before{content:""}.ri-handbag-line:before{content:""}.ri-hard-drive-2-fill:before{content:""}.ri-hard-drive-2-line:before{content:""}.ri-hard-drive-fill:before{content:""}.ri-hard-drive-line:before{content:""}.ri-hashtag:before{content:""}.ri-haze-2-fill:before{content:""}.ri-haze-2-line:before{content:""}.ri-haze-fill:before{content:""}.ri-haze-line:before{content:""}.ri-hd-fill:before{content:""}.ri-hd-line:before{content:""}.ri-heading:before{content:""}.ri-headphone-fill:before{content:""}.ri-headphone-line:before{content:""}.ri-health-book-fill:before{content:""}.ri-health-book-line:before{content:""}.ri-heart-2-fill:before{content:""}.ri-heart-2-line:before{content:""}.ri-heart-3-fill:before{content:""}.ri-heart-3-line:before{content:""}.ri-heart-add-fill:before{content:""}.ri-heart-add-line:before{content:""}.ri-heart-fill:before{content:""}.ri-heart-line:before{content:""}.ri-heart-pulse-fill:before{content:""}.ri-heart-pulse-line:before{content:""}.ri-hearts-fill:before{content:""}.ri-hearts-line:before{content:""}.ri-heavy-showers-fill:before{content:""}.ri-heavy-showers-line:before{content:""}.ri-history-fill:before{content:""}.ri-history-line:before{content:""}.ri-home-2-fill:before{content:""}.ri-home-2-line:before{content:""}.ri-home-3-fill:before{content:""}.ri-home-3-line:before{content:""}.ri-home-4-fill:before{content:""}.ri-home-4-line:before{content:""}.ri-home-5-fill:before{content:""}.ri-home-5-line:before{content:""}.ri-home-6-fill:before{content:""}.ri-home-6-line:before{content:""}.ri-home-7-fill:before{content:""}.ri-home-7-line:before{content:""}.ri-home-8-fill:before{content:""}.ri-home-8-line:before{content:""}.ri-home-fill:before{content:""}.ri-home-gear-fill:before{content:""}.ri-home-gear-line:before{content:""}.ri-home-heart-fill:before{content:""}.ri-home-heart-line:before{content:""}.ri-home-line:before{content:""}.ri-home-smile-2-fill:before{content:""}.ri-home-smile-2-line:before{content:""}.ri-home-smile-fill:before{content:""}.ri-home-smile-line:before{content:""}.ri-home-wifi-fill:before{content:""}.ri-home-wifi-line:before{content:""}.ri-honor-of-kings-fill:before{content:""}.ri-honor-of-kings-line:before{content:""}.ri-honour-fill:before{content:""}.ri-honour-line:before{content:""}.ri-hospital-fill:before{content:""}.ri-hospital-line:before{content:""}.ri-hotel-bed-fill:before{content:""}.ri-hotel-bed-line:before{content:""}.ri-hotel-fill:before{content:""}.ri-hotel-line:before{content:""}.ri-hotspot-fill:before{content:""}.ri-hotspot-line:before{content:""}.ri-hq-fill:before{content:""}.ri-hq-line:before{content:""}.ri-html5-fill:before{content:""}.ri-html5-line:before{content:""}.ri-ie-fill:before{content:""}.ri-ie-line:before{content:""}.ri-image-2-fill:before{content:""}.ri-image-2-line:before{content:""}.ri-image-add-fill:before{content:""}.ri-image-add-line:before{content:""}.ri-image-edit-fill:before{content:""}.ri-image-edit-line:before{content:""}.ri-image-fill:before{content:""}.ri-image-line:before{content:""}.ri-inbox-archive-fill:before{content:""}.ri-inbox-archive-line:before{content:""}.ri-inbox-fill:before{content:""}.ri-inbox-line:before{content:""}.ri-inbox-unarchive-fill:before{content:""}.ri-inbox-unarchive-line:before{content:""}.ri-increase-decrease-fill:before{content:""}.ri-increase-decrease-line:before{content:""}.ri-indent-decrease:before{content:""}.ri-indent-increase:before{content:""}.ri-indeterminate-circle-fill:before{content:""}.ri-indeterminate-circle-line:before{content:""}.ri-information-fill:before{content:""}.ri-information-line:before{content:""}.ri-infrared-thermometer-fill:before{content:""}.ri-infrared-thermometer-line:before{content:""}.ri-ink-bottle-fill:before{content:""}.ri-ink-bottle-line:before{content:""}.ri-input-cursor-move:before{content:""}.ri-input-method-fill:before{content:""}.ri-input-method-line:before{content:""}.ri-insert-column-left:before{content:""}.ri-insert-column-right:before{content:""}.ri-insert-row-bottom:before{content:""}.ri-insert-row-top:before{content:""}.ri-instagram-fill:before{content:""}.ri-instagram-line:before{content:""}.ri-install-fill:before{content:""}.ri-install-line:before{content:""}.ri-invision-fill:before{content:""}.ri-invision-line:before{content:""}.ri-italic:before{content:""}.ri-kakao-talk-fill:before{content:""}.ri-kakao-talk-line:before{content:""}.ri-key-2-fill:before{content:""}.ri-key-2-line:before{content:""}.ri-key-fill:before{content:""}.ri-key-line:before{content:""}.ri-keyboard-box-fill:before{content:""}.ri-keyboard-box-line:before{content:""}.ri-keyboard-fill:before{content:""}.ri-keyboard-line:before{content:""}.ri-keynote-fill:before{content:""}.ri-keynote-line:before{content:""}.ri-knife-blood-fill:before{content:""}.ri-knife-blood-line:before{content:""}.ri-knife-fill:before{content:""}.ri-knife-line:before{content:""}.ri-landscape-fill:before{content:""}.ri-landscape-line:before{content:""}.ri-layout-2-fill:before{content:""}.ri-layout-2-line:before{content:""}.ri-layout-3-fill:before{content:""}.ri-layout-3-line:before{content:""}.ri-layout-4-fill:before{content:""}.ri-layout-4-line:before{content:""}.ri-layout-5-fill:before{content:""}.ri-layout-5-line:before{content:""}.ri-layout-6-fill:before{content:""}.ri-layout-6-line:before{content:""}.ri-layout-bottom-2-fill:before{content:""}.ri-layout-bottom-2-line:before{content:""}.ri-layout-bottom-fill:before{content:""}.ri-layout-bottom-line:before{content:""}.ri-layout-column-fill:before{content:""}.ri-layout-column-line:before{content:""}.ri-layout-fill:before{content:""}.ri-layout-grid-fill:before{content:""}.ri-layout-grid-line:before{content:""}.ri-layout-left-2-fill:before{content:""}.ri-layout-left-2-line:before{content:""}.ri-layout-left-fill:before{content:""}.ri-layout-left-line:before{content:""}.ri-layout-line:before{content:""}.ri-layout-masonry-fill:before{content:""}.ri-layout-masonry-line:before{content:""}.ri-layout-right-2-fill:before{content:""}.ri-layout-right-2-line:before{content:""}.ri-layout-right-fill:before{content:""}.ri-layout-right-line:before{content:""}.ri-layout-row-fill:before{content:""}.ri-layout-row-line:before{content:""}.ri-layout-top-2-fill:before{content:""}.ri-layout-top-2-line:before{content:""}.ri-layout-top-fill:before{content:""}.ri-layout-top-line:before{content:""}.ri-leaf-fill:before{content:""}.ri-leaf-line:before{content:""}.ri-lifebuoy-fill:before{content:""}.ri-lifebuoy-line:before{content:""}.ri-lightbulb-fill:before{content:""}.ri-lightbulb-flash-fill:before{content:""}.ri-lightbulb-flash-line:before{content:""}.ri-lightbulb-line:before{content:""}.ri-line-chart-fill:before{content:""}.ri-line-chart-line:before{content:""}.ri-line-fill:before{content:""}.ri-line-height:before{content:""}.ri-line-line:before{content:""}.ri-link-m:before{content:""}.ri-link-unlink-m:before{content:""}.ri-link-unlink:before{content:""}.ri-link:before{content:""}.ri-linkedin-box-fill:before{content:""}.ri-linkedin-box-line:before{content:""}.ri-linkedin-fill:before{content:""}.ri-linkedin-line:before{content:""}.ri-links-fill:before{content:""}.ri-links-line:before{content:""}.ri-list-check-2:before{content:""}.ri-list-check:before{content:""}.ri-list-ordered:before{content:""}.ri-list-settings-fill:before{content:""}.ri-list-settings-line:before{content:""}.ri-list-unordered:before{content:""}.ri-live-fill:before{content:""}.ri-live-line:before{content:""}.ri-loader-2-fill:before{content:""}.ri-loader-2-line:before{content:""}.ri-loader-3-fill:before{content:""}.ri-loader-3-line:before{content:""}.ri-loader-4-fill:before{content:""}.ri-loader-4-line:before{content:""}.ri-loader-5-fill:before{content:""}.ri-loader-5-line:before{content:""}.ri-loader-fill:before{content:""}.ri-loader-line:before{content:""}.ri-lock-2-fill:before{content:""}.ri-lock-2-line:before{content:""}.ri-lock-fill:before{content:""}.ri-lock-line:before{content:""}.ri-lock-password-fill:before{content:""}.ri-lock-password-line:before{content:""}.ri-lock-unlock-fill:before{content:""}.ri-lock-unlock-line:before{content:""}.ri-login-box-fill:before{content:""}.ri-login-box-line:before{content:""}.ri-login-circle-fill:before{content:""}.ri-login-circle-line:before{content:""}.ri-logout-box-fill:before{content:""}.ri-logout-box-line:before{content:""}.ri-logout-box-r-fill:before{content:""}.ri-logout-box-r-line:before{content:""}.ri-logout-circle-fill:before{content:""}.ri-logout-circle-line:before{content:""}.ri-logout-circle-r-fill:before{content:""}.ri-logout-circle-r-line:before{content:""}.ri-luggage-cart-fill:before{content:""}.ri-luggage-cart-line:before{content:""}.ri-luggage-deposit-fill:before{content:""}.ri-luggage-deposit-line:before{content:""}.ri-lungs-fill:before{content:""}.ri-lungs-line:before{content:""}.ri-mac-fill:before{content:""}.ri-mac-line:before{content:""}.ri-macbook-fill:before{content:""}.ri-macbook-line:before{content:""}.ri-magic-fill:before{content:""}.ri-magic-line:before{content:""}.ri-mail-add-fill:before{content:""}.ri-mail-add-line:before{content:""}.ri-mail-check-fill:before{content:""}.ri-mail-check-line:before{content:""}.ri-mail-close-fill:before{content:""}.ri-mail-close-line:before{content:""}.ri-mail-download-fill:before{content:""}.ri-mail-download-line:before{content:""}.ri-mail-fill:before{content:""}.ri-mail-forbid-fill:before{content:""}.ri-mail-forbid-line:before{content:""}.ri-mail-line:before{content:""}.ri-mail-lock-fill:before{content:""}.ri-mail-lock-line:before{content:""}.ri-mail-open-fill:before{content:""}.ri-mail-open-line:before{content:""}.ri-mail-send-fill:before{content:""}.ri-mail-send-line:before{content:""}.ri-mail-settings-fill:before{content:""}.ri-mail-settings-line:before{content:""}.ri-mail-star-fill:before{content:""}.ri-mail-star-line:before{content:""}.ri-mail-unread-fill:before{content:""}.ri-mail-unread-line:before{content:""}.ri-mail-volume-fill:before{content:""}.ri-mail-volume-line:before{content:""}.ri-map-2-fill:before{content:""}.ri-map-2-line:before{content:""}.ri-map-fill:before{content:""}.ri-map-line:before{content:""}.ri-map-pin-2-fill:before{content:""}.ri-map-pin-2-line:before{content:""}.ri-map-pin-3-fill:before{content:""}.ri-map-pin-3-line:before{content:""}.ri-map-pin-4-fill:before{content:""}.ri-map-pin-4-line:before{content:""}.ri-map-pin-5-fill:before{content:""}.ri-map-pin-5-line:before{content:""}.ri-map-pin-add-fill:before{content:""}.ri-map-pin-add-line:before{content:""}.ri-map-pin-fill:before{content:""}.ri-map-pin-line:before{content:""}.ri-map-pin-range-fill:before{content:""}.ri-map-pin-range-line:before{content:""}.ri-map-pin-time-fill:before{content:""}.ri-map-pin-time-line:before{content:""}.ri-map-pin-user-fill:before{content:""}.ri-map-pin-user-line:before{content:""}.ri-mark-pen-fill:before{content:""}.ri-mark-pen-line:before{content:""}.ri-markdown-fill:before{content:""}.ri-markdown-line:before{content:""}.ri-markup-fill:before{content:""}.ri-markup-line:before{content:""}.ri-mastercard-fill:before{content:""}.ri-mastercard-line:before{content:""}.ri-mastodon-fill:before{content:""}.ri-mastodon-line:before{content:""}.ri-medal-2-fill:before{content:""}.ri-medal-2-line:before{content:""}.ri-medal-fill:before{content:""}.ri-medal-line:before{content:""}.ri-medicine-bottle-fill:before{content:""}.ri-medicine-bottle-line:before{content:""}.ri-medium-fill:before{content:""}.ri-medium-line:before{content:""}.ri-men-fill:before{content:""}.ri-men-line:before{content:""}.ri-mental-health-fill:before{content:""}.ri-mental-health-line:before{content:""}.ri-menu-2-fill:before{content:""}.ri-menu-2-line:before{content:""}.ri-menu-3-fill:before{content:""}.ri-menu-3-line:before{content:""}.ri-menu-4-fill:before{content:""}.ri-menu-4-line:before{content:""}.ri-menu-5-fill:before{content:""}.ri-menu-5-line:before{content:""}.ri-menu-add-fill:before{content:""}.ri-menu-add-line:before{content:""}.ri-menu-fill:before{content:""}.ri-menu-fold-fill:before{content:""}.ri-menu-fold-line:before{content:""}.ri-menu-line:before{content:""}.ri-menu-unfold-fill:before{content:""}.ri-menu-unfold-line:before{content:""}.ri-merge-cells-horizontal:before{content:""}.ri-merge-cells-vertical:before{content:""}.ri-message-2-fill:before{content:""}.ri-message-2-line:before{content:""}.ri-message-3-fill:before{content:""}.ri-message-3-line:before{content:""}.ri-message-fill:before{content:""}.ri-message-line:before{content:""}.ri-messenger-fill:before{content:""}.ri-messenger-line:before{content:""}.ri-meteor-fill:before{content:""}.ri-meteor-line:before{content:""}.ri-mic-2-fill:before{content:""}.ri-mic-2-line:before{content:""}.ri-mic-fill:before{content:""}.ri-mic-line:before{content:""}.ri-mic-off-fill:before{content:""}.ri-mic-off-line:before{content:""}.ri-mickey-fill:before{content:""}.ri-mickey-line:before{content:""}.ri-microscope-fill:before{content:""}.ri-microscope-line:before{content:""}.ri-microsoft-fill:before{content:""}.ri-microsoft-line:before{content:""}.ri-mind-map:before{content:""}.ri-mini-program-fill:before{content:""}.ri-mini-program-line:before{content:""}.ri-mist-fill:before{content:""}.ri-mist-line:before{content:""}.ri-money-cny-box-fill:before{content:""}.ri-money-cny-box-line:before{content:""}.ri-money-cny-circle-fill:before{content:""}.ri-money-cny-circle-line:before{content:""}.ri-money-dollar-box-fill:before{content:""}.ri-money-dollar-box-line:before{content:""}.ri-money-dollar-circle-fill:before{content:""}.ri-money-dollar-circle-line:before{content:""}.ri-money-euro-box-fill:before{content:""}.ri-money-euro-box-line:before{content:""}.ri-money-euro-circle-fill:before{content:""}.ri-money-euro-circle-line:before{content:""}.ri-money-pound-box-fill:before{content:""}.ri-money-pound-box-line:before{content:""}.ri-money-pound-circle-fill:before{content:""}.ri-money-pound-circle-line:before{content:""}.ri-moon-clear-fill:before{content:""}.ri-moon-clear-line:before{content:""}.ri-moon-cloudy-fill:before{content:""}.ri-moon-cloudy-line:before{content:""}.ri-moon-fill:before{content:""}.ri-moon-foggy-fill:before{content:""}.ri-moon-foggy-line:before{content:""}.ri-moon-line:before{content:""}.ri-more-2-fill:before{content:""}.ri-more-2-line:before{content:""}.ri-more-fill:before{content:""}.ri-more-line:before{content:""}.ri-motorbike-fill:before{content:""}.ri-motorbike-line:before{content:""}.ri-mouse-fill:before{content:""}.ri-mouse-line:before{content:""}.ri-movie-2-fill:before{content:""}.ri-movie-2-line:before{content:""}.ri-movie-fill:before{content:""}.ri-movie-line:before{content:""}.ri-music-2-fill:before{content:""}.ri-music-2-line:before{content:""}.ri-music-fill:before{content:""}.ri-music-line:before{content:""}.ri-mv-fill:before{content:""}.ri-mv-line:before{content:""}.ri-navigation-fill:before{content:""}.ri-navigation-line:before{content:""}.ri-netease-cloud-music-fill:before{content:""}.ri-netease-cloud-music-line:before{content:""}.ri-netflix-fill:before{content:""}.ri-netflix-line:before{content:""}.ri-newspaper-fill:before{content:""}.ri-newspaper-line:before{content:""}.ri-node-tree:before{content:""}.ri-notification-2-fill:before{content:""}.ri-notification-2-line:before{content:""}.ri-notification-3-fill:before{content:""}.ri-notification-3-line:before{content:""}.ri-notification-4-fill:before{content:""}.ri-notification-4-line:before{content:""}.ri-notification-badge-fill:before{content:""}.ri-notification-badge-line:before{content:""}.ri-notification-fill:before{content:""}.ri-notification-line:before{content:""}.ri-notification-off-fill:before{content:""}.ri-notification-off-line:before{content:""}.ri-npmjs-fill:before{content:""}.ri-npmjs-line:before{content:""}.ri-number-0:before{content:""}.ri-number-1:before{content:""}.ri-number-2:before{content:""}.ri-number-3:before{content:""}.ri-number-4:before{content:""}.ri-number-5:before{content:""}.ri-number-6:before{content:""}.ri-number-7:before{content:""}.ri-number-8:before{content:""}.ri-number-9:before{content:""}.ri-numbers-fill:before{content:""}.ri-numbers-line:before{content:""}.ri-nurse-fill:before{content:""}.ri-nurse-line:before{content:""}.ri-oil-fill:before{content:""}.ri-oil-line:before{content:""}.ri-omega:before{content:""}.ri-open-arm-fill:before{content:""}.ri-open-arm-line:before{content:""}.ri-open-source-fill:before{content:""}.ri-open-source-line:before{content:""}.ri-opera-fill:before{content:""}.ri-opera-line:before{content:""}.ri-order-play-fill:before{content:""}.ri-order-play-line:before{content:""}.ri-organization-chart:before{content:""}.ri-outlet-2-fill:before{content:""}.ri-outlet-2-line:before{content:""}.ri-outlet-fill:before{content:""}.ri-outlet-line:before{content:""}.ri-page-separator:before{content:""}.ri-pages-fill:before{content:""}.ri-pages-line:before{content:""}.ri-paint-brush-fill:before{content:""}.ri-paint-brush-line:before{content:""}.ri-paint-fill:before{content:""}.ri-paint-line:before{content:""}.ri-palette-fill:before{content:""}.ri-palette-line:before{content:""}.ri-pantone-fill:before{content:""}.ri-pantone-line:before{content:""}.ri-paragraph:before{content:""}.ri-parent-fill:before{content:""}.ri-parent-line:before{content:""}.ri-parentheses-fill:before{content:""}.ri-parentheses-line:before{content:""}.ri-parking-box-fill:before{content:""}.ri-parking-box-line:before{content:""}.ri-parking-fill:before{content:""}.ri-parking-line:before{content:""}.ri-passport-fill:before{content:""}.ri-passport-line:before{content:""}.ri-patreon-fill:before{content:""}.ri-patreon-line:before{content:""}.ri-pause-circle-fill:before{content:""}.ri-pause-circle-line:before{content:""}.ri-pause-fill:before{content:""}.ri-pause-line:before{content:""}.ri-pause-mini-fill:before{content:""}.ri-pause-mini-line:before{content:""}.ri-paypal-fill:before{content:""}.ri-paypal-line:before{content:""}.ri-pen-nib-fill:before{content:""}.ri-pen-nib-line:before{content:""}.ri-pencil-fill:before{content:""}.ri-pencil-line:before{content:""}.ri-pencil-ruler-2-fill:before{content:""}.ri-pencil-ruler-2-line:before{content:""}.ri-pencil-ruler-fill:before{content:""}.ri-pencil-ruler-line:before{content:""}.ri-percent-fill:before{content:""}.ri-percent-line:before{content:""}.ri-phone-camera-fill:before{content:""}.ri-phone-camera-line:before{content:""}.ri-phone-fill:before{content:""}.ri-phone-find-fill:before{content:""}.ri-phone-find-line:before{content:""}.ri-phone-line:before{content:""}.ri-phone-lock-fill:before{content:""}.ri-phone-lock-line:before{content:""}.ri-picture-in-picture-2-fill:before{content:""}.ri-picture-in-picture-2-line:before{content:""}.ri-picture-in-picture-exit-fill:before{content:""}.ri-picture-in-picture-exit-line:before{content:""}.ri-picture-in-picture-fill:before{content:""}.ri-picture-in-picture-line:before{content:""}.ri-pie-chart-2-fill:before{content:""}.ri-pie-chart-2-line:before{content:""}.ri-pie-chart-box-fill:before{content:""}.ri-pie-chart-box-line:before{content:""}.ri-pie-chart-fill:before{content:""}.ri-pie-chart-line:before{content:""}.ri-pin-distance-fill:before{content:""}.ri-pin-distance-line:before{content:""}.ri-ping-pong-fill:before{content:""}.ri-ping-pong-line:before{content:""}.ri-pinterest-fill:before{content:""}.ri-pinterest-line:before{content:""}.ri-pinyin-input:before{content:""}.ri-pixelfed-fill:before{content:""}.ri-pixelfed-line:before{content:""}.ri-plane-fill:before{content:""}.ri-plane-line:before{content:""}.ri-plant-fill:before{content:""}.ri-plant-line:before{content:""}.ri-play-circle-fill:before{content:""}.ri-play-circle-line:before{content:""}.ri-play-fill:before{content:""}.ri-play-line:before{content:""}.ri-play-list-2-fill:before{content:""}.ri-play-list-2-line:before{content:""}.ri-play-list-add-fill:before{content:""}.ri-play-list-add-line:before{content:""}.ri-play-list-fill:before{content:""}.ri-play-list-line:before{content:""}.ri-play-mini-fill:before{content:""}.ri-play-mini-line:before{content:""}.ri-playstation-fill:before{content:""}.ri-playstation-line:before{content:""}.ri-plug-2-fill:before{content:""}.ri-plug-2-line:before{content:""}.ri-plug-fill:before{content:""}.ri-plug-line:before{content:""}.ri-polaroid-2-fill:before{content:""}.ri-polaroid-2-line:before{content:""}.ri-polaroid-fill:before{content:""}.ri-polaroid-line:before{content:""}.ri-police-car-fill:before{content:""}.ri-police-car-line:before{content:""}.ri-price-tag-2-fill:before{content:""}.ri-price-tag-2-line:before{content:""}.ri-price-tag-3-fill:before{content:""}.ri-price-tag-3-line:before{content:""}.ri-price-tag-fill:before{content:""}.ri-price-tag-line:before{content:""}.ri-printer-cloud-fill:before{content:""}.ri-printer-cloud-line:before{content:""}.ri-printer-fill:before{content:""}.ri-printer-line:before{content:""}.ri-product-hunt-fill:before{content:""}.ri-product-hunt-line:before{content:""}.ri-profile-fill:before{content:""}.ri-profile-line:before{content:""}.ri-projector-2-fill:before{content:""}.ri-projector-2-line:before{content:""}.ri-projector-fill:before{content:""}.ri-projector-line:before{content:""}.ri-psychotherapy-fill:before{content:""}.ri-psychotherapy-line:before{content:""}.ri-pulse-fill:before{content:""}.ri-pulse-line:before{content:""}.ri-pushpin-2-fill:before{content:""}.ri-pushpin-2-line:before{content:""}.ri-pushpin-fill:before{content:""}.ri-pushpin-line:before{content:""}.ri-qq-fill:before{content:""}.ri-qq-line:before{content:""}.ri-qr-code-fill:before{content:""}.ri-qr-code-line:before{content:""}.ri-qr-scan-2-fill:before{content:""}.ri-qr-scan-2-line:before{content:""}.ri-qr-scan-fill:before{content:""}.ri-qr-scan-line:before{content:""}.ri-question-answer-fill:before{content:""}.ri-question-answer-line:before{content:""}.ri-question-fill:before{content:""}.ri-question-line:before{content:""}.ri-question-mark:before{content:""}.ri-questionnaire-fill:before{content:""}.ri-questionnaire-line:before{content:""}.ri-quill-pen-fill:before{content:""}.ri-quill-pen-line:before{content:""}.ri-radar-fill:before{content:""}.ri-radar-line:before{content:""}.ri-radio-2-fill:before{content:""}.ri-radio-2-line:before{content:""}.ri-radio-button-fill:before{content:""}.ri-radio-button-line:before{content:""}.ri-radio-fill:before{content:""}.ri-radio-line:before{content:""}.ri-rainbow-fill:before{content:""}.ri-rainbow-line:before{content:""}.ri-rainy-fill:before{content:""}.ri-rainy-line:before{content:""}.ri-reactjs-fill:before{content:""}.ri-reactjs-line:before{content:""}.ri-record-circle-fill:before{content:""}.ri-record-circle-line:before{content:""}.ri-record-mail-fill:before{content:""}.ri-record-mail-line:before{content:""}.ri-recycle-fill:before{content:""}.ri-recycle-line:before{content:""}.ri-red-packet-fill:before{content:""}.ri-red-packet-line:before{content:""}.ri-reddit-fill:before{content:""}.ri-reddit-line:before{content:""}.ri-refresh-fill:before{content:""}.ri-refresh-line:before{content:""}.ri-refund-2-fill:before{content:""}.ri-refund-2-line:before{content:""}.ri-refund-fill:before{content:""}.ri-refund-line:before{content:""}.ri-registered-fill:before{content:""}.ri-registered-line:before{content:""}.ri-remixicon-fill:before{content:""}.ri-remixicon-line:before{content:""}.ri-remote-control-2-fill:before{content:""}.ri-remote-control-2-line:before{content:""}.ri-remote-control-fill:before{content:""}.ri-remote-control-line:before{content:""}.ri-repeat-2-fill:before{content:""}.ri-repeat-2-line:before{content:""}.ri-repeat-fill:before{content:""}.ri-repeat-line:before{content:""}.ri-repeat-one-fill:before{content:""}.ri-repeat-one-line:before{content:""}.ri-reply-all-fill:before{content:""}.ri-reply-all-line:before{content:""}.ri-reply-fill:before{content:""}.ri-reply-line:before{content:""}.ri-reserved-fill:before{content:""}.ri-reserved-line:before{content:""}.ri-rest-time-fill:before{content:""}.ri-rest-time-line:before{content:""}.ri-restart-fill:before{content:""}.ri-restart-line:before{content:""}.ri-restaurant-2-fill:before{content:""}.ri-restaurant-2-line:before{content:""}.ri-restaurant-fill:before{content:""}.ri-restaurant-line:before{content:""}.ri-rewind-fill:before{content:""}.ri-rewind-line:before{content:""}.ri-rewind-mini-fill:before{content:""}.ri-rewind-mini-line:before{content:""}.ri-rhythm-fill:before{content:""}.ri-rhythm-line:before{content:""}.ri-riding-fill:before{content:""}.ri-riding-line:before{content:""}.ri-road-map-fill:before{content:""}.ri-road-map-line:before{content:""}.ri-roadster-fill:before{content:""}.ri-roadster-line:before{content:""}.ri-robot-fill:before{content:""}.ri-robot-line:before{content:""}.ri-rocket-2-fill:before{content:""}.ri-rocket-2-line:before{content:""}.ri-rocket-fill:before{content:""}.ri-rocket-line:before{content:""}.ri-rotate-lock-fill:before{content:""}.ri-rotate-lock-line:before{content:""}.ri-rounded-corner:before{content:""}.ri-route-fill:before{content:""}.ri-route-line:before{content:""}.ri-router-fill:before{content:""}.ri-router-line:before{content:""}.ri-rss-fill:before{content:""}.ri-rss-line:before{content:""}.ri-ruler-2-fill:before{content:""}.ri-ruler-2-line:before{content:""}.ri-ruler-fill:before{content:""}.ri-ruler-line:before{content:""}.ri-run-fill:before{content:""}.ri-run-line:before{content:""}.ri-safari-fill:before{content:""}.ri-safari-line:before{content:""}.ri-safe-2-fill:before{content:""}.ri-safe-2-line:before{content:""}.ri-safe-fill:before{content:""}.ri-safe-line:before{content:""}.ri-sailboat-fill:before{content:""}.ri-sailboat-line:before{content:""}.ri-save-2-fill:before{content:""}.ri-save-2-line:before{content:""}.ri-save-3-fill:before{content:""}.ri-save-3-line:before{content:""}.ri-save-fill:before{content:""}.ri-save-line:before{content:""}.ri-scales-2-fill:before{content:""}.ri-scales-2-line:before{content:""}.ri-scales-3-fill:before{content:""}.ri-scales-3-line:before{content:""}.ri-scales-fill:before{content:""}.ri-scales-line:before{content:""}.ri-scan-2-fill:before{content:""}.ri-scan-2-line:before{content:""}.ri-scan-fill:before{content:""}.ri-scan-line:before{content:""}.ri-scissors-2-fill:before{content:""}.ri-scissors-2-line:before{content:""}.ri-scissors-cut-fill:before{content:""}.ri-scissors-cut-line:before{content:""}.ri-scissors-fill:before{content:""}.ri-scissors-line:before{content:""}.ri-screenshot-2-fill:before{content:""}.ri-screenshot-2-line:before{content:""}.ri-screenshot-fill:before{content:""}.ri-screenshot-line:before{content:""}.ri-sd-card-fill:before{content:""}.ri-sd-card-line:before{content:""}.ri-sd-card-mini-fill:before{content:""}.ri-sd-card-mini-line:before{content:""}.ri-search-2-fill:before{content:""}.ri-search-2-line:before{content:""}.ri-search-eye-fill:before{content:""}.ri-search-eye-line:before{content:""}.ri-search-fill:before{content:""}.ri-search-line:before{content:""}.ri-secure-payment-fill:before{content:""}.ri-secure-payment-line:before{content:""}.ri-seedling-fill:before{content:""}.ri-seedling-line:before{content:""}.ri-send-backward:before{content:""}.ri-send-plane-2-fill:before{content:""}.ri-send-plane-2-line:before{content:""}.ri-send-plane-fill:before{content:""}.ri-send-plane-line:before{content:""}.ri-send-to-back:before{content:""}.ri-sensor-fill:before{content:""}.ri-sensor-line:before{content:""}.ri-separator:before{content:""}.ri-server-fill:before{content:""}.ri-server-line:before{content:""}.ri-service-fill:before{content:""}.ri-service-line:before{content:""}.ri-settings-2-fill:before{content:""}.ri-settings-2-line:before{content:""}.ri-settings-3-fill:before{content:""}.ri-settings-3-line:before{content:""}.ri-settings-4-fill:before{content:""}.ri-settings-4-line:before{content:""}.ri-settings-5-fill:before{content:""}.ri-settings-5-line:before{content:""}.ri-settings-6-fill:before{content:""}.ri-settings-6-line:before{content:""}.ri-settings-fill:before{content:""}.ri-settings-line:before{content:""}.ri-shape-2-fill:before{content:""}.ri-shape-2-line:before{content:""}.ri-shape-fill:before{content:""}.ri-shape-line:before{content:""}.ri-share-box-fill:before{content:""}.ri-share-box-line:before{content:""}.ri-share-circle-fill:before{content:""}.ri-share-circle-line:before{content:""}.ri-share-fill:before{content:""}.ri-share-forward-2-fill:before{content:""}.ri-share-forward-2-line:before{content:""}.ri-share-forward-box-fill:before{content:""}.ri-share-forward-box-line:before{content:""}.ri-share-forward-fill:before{content:""}.ri-share-forward-line:before{content:""}.ri-share-line:before{content:""}.ri-shield-check-fill:before{content:""}.ri-shield-check-line:before{content:""}.ri-shield-cross-fill:before{content:""}.ri-shield-cross-line:before{content:""}.ri-shield-fill:before{content:""}.ri-shield-flash-fill:before{content:""}.ri-shield-flash-line:before{content:""}.ri-shield-keyhole-fill:before{content:""}.ri-shield-keyhole-line:before{content:""}.ri-shield-line:before{content:""}.ri-shield-star-fill:before{content:""}.ri-shield-star-line:before{content:""}.ri-shield-user-fill:before{content:""}.ri-shield-user-line:before{content:""}.ri-ship-2-fill:before{content:""}.ri-ship-2-line:before{content:""}.ri-ship-fill:before{content:""}.ri-ship-line:before{content:""}.ri-shirt-fill:before{content:""}.ri-shirt-line:before{content:""}.ri-shopping-bag-2-fill:before{content:""}.ri-shopping-bag-2-line:before{content:""}.ri-shopping-bag-3-fill:before{content:""}.ri-shopping-bag-3-line:before{content:""}.ri-shopping-bag-fill:before{content:""}.ri-shopping-bag-line:before{content:""}.ri-shopping-basket-2-fill:before{content:""}.ri-shopping-basket-2-line:before{content:""}.ri-shopping-basket-fill:before{content:""}.ri-shopping-basket-line:before{content:""}.ri-shopping-cart-2-fill:before{content:""}.ri-shopping-cart-2-line:before{content:""}.ri-shopping-cart-fill:before{content:""}.ri-shopping-cart-line:before{content:""}.ri-showers-fill:before{content:""}.ri-showers-line:before{content:""}.ri-shuffle-fill:before{content:""}.ri-shuffle-line:before{content:""}.ri-shut-down-fill:before{content:""}.ri-shut-down-line:before{content:""}.ri-side-bar-fill:before{content:""}.ri-side-bar-line:before{content:""}.ri-signal-tower-fill:before{content:""}.ri-signal-tower-line:before{content:""}.ri-signal-wifi-1-fill:before{content:""}.ri-signal-wifi-1-line:before{content:""}.ri-signal-wifi-2-fill:before{content:""}.ri-signal-wifi-2-line:before{content:""}.ri-signal-wifi-3-fill:before{content:""}.ri-signal-wifi-3-line:before{content:""}.ri-signal-wifi-error-fill:before{content:""}.ri-signal-wifi-error-line:before{content:""}.ri-signal-wifi-fill:before{content:""}.ri-signal-wifi-line:before{content:""}.ri-signal-wifi-off-fill:before{content:""}.ri-signal-wifi-off-line:before{content:""}.ri-sim-card-2-fill:before{content:""}.ri-sim-card-2-line:before{content:""}.ri-sim-card-fill:before{content:""}.ri-sim-card-line:before{content:""}.ri-single-quotes-l:before{content:""}.ri-single-quotes-r:before{content:""}.ri-sip-fill:before{content:""}.ri-sip-line:before{content:""}.ri-skip-back-fill:before{content:""}.ri-skip-back-line:before{content:""}.ri-skip-back-mini-fill:before{content:""}.ri-skip-back-mini-line:before{content:""}.ri-skip-forward-fill:before{content:""}.ri-skip-forward-line:before{content:""}.ri-skip-forward-mini-fill:before{content:""}.ri-skip-forward-mini-line:before{content:""}.ri-skull-2-fill:before{content:""}.ri-skull-2-line:before{content:""}.ri-skull-fill:before{content:""}.ri-skull-line:before{content:""}.ri-skype-fill:before{content:""}.ri-skype-line:before{content:""}.ri-slack-fill:before{content:""}.ri-slack-line:before{content:""}.ri-slice-fill:before{content:""}.ri-slice-line:before{content:""}.ri-slideshow-2-fill:before{content:""}.ri-slideshow-2-line:before{content:""}.ri-slideshow-3-fill:before{content:""}.ri-slideshow-3-line:before{content:""}.ri-slideshow-4-fill:before{content:""}.ri-slideshow-4-line:before{content:""}.ri-slideshow-fill:before{content:""}.ri-slideshow-line:before{content:""}.ri-smartphone-fill:before{content:""}.ri-smartphone-line:before{content:""}.ri-snapchat-fill:before{content:""}.ri-snapchat-line:before{content:""}.ri-snowy-fill:before{content:""}.ri-snowy-line:before{content:""}.ri-sort-asc:before{content:""}.ri-sort-desc:before{content:""}.ri-sound-module-fill:before{content:""}.ri-sound-module-line:before{content:""}.ri-soundcloud-fill:before{content:""}.ri-soundcloud-line:before{content:""}.ri-space-ship-fill:before{content:""}.ri-space-ship-line:before{content:""}.ri-space:before{content:""}.ri-spam-2-fill:before{content:""}.ri-spam-2-line:before{content:""}.ri-spam-3-fill:before{content:""}.ri-spam-3-line:before{content:""}.ri-spam-fill:before{content:""}.ri-spam-line:before{content:""}.ri-speaker-2-fill:before{content:""}.ri-speaker-2-line:before{content:""}.ri-speaker-3-fill:before{content:""}.ri-speaker-3-line:before{content:""}.ri-speaker-fill:before{content:""}.ri-speaker-line:before{content:""}.ri-spectrum-fill:before{content:""}.ri-spectrum-line:before{content:""}.ri-speed-fill:before{content:""}.ri-speed-line:before{content:""}.ri-speed-mini-fill:before{content:""}.ri-speed-mini-line:before{content:""}.ri-split-cells-horizontal:before{content:""}.ri-split-cells-vertical:before{content:""}.ri-spotify-fill:before{content:""}.ri-spotify-line:before{content:""}.ri-spy-fill:before{content:""}.ri-spy-line:before{content:""}.ri-stack-fill:before{content:""}.ri-stack-line:before{content:""}.ri-stack-overflow-fill:before{content:""}.ri-stack-overflow-line:before{content:""}.ri-stackshare-fill:before{content:""}.ri-stackshare-line:before{content:""}.ri-star-fill:before{content:""}.ri-star-half-fill:before{content:""}.ri-star-half-line:before{content:""}.ri-star-half-s-fill:before{content:""}.ri-star-half-s-line:before{content:""}.ri-star-line:before{content:""}.ri-star-s-fill:before{content:""}.ri-star-s-line:before{content:""}.ri-star-smile-fill:before{content:""}.ri-star-smile-line:before{content:""}.ri-steam-fill:before{content:""}.ri-steam-line:before{content:""}.ri-steering-2-fill:before{content:""}.ri-steering-2-line:before{content:""}.ri-steering-fill:before{content:""}.ri-steering-line:before{content:""}.ri-stethoscope-fill:before{content:""}.ri-stethoscope-line:before{content:""}.ri-sticky-note-2-fill:before{content:""}.ri-sticky-note-2-line:before{content:""}.ri-sticky-note-fill:before{content:""}.ri-sticky-note-line:before{content:""}.ri-stock-fill:before{content:""}.ri-stock-line:before{content:""}.ri-stop-circle-fill:before{content:""}.ri-stop-circle-line:before{content:""}.ri-stop-fill:before{content:""}.ri-stop-line:before{content:""}.ri-stop-mini-fill:before{content:""}.ri-stop-mini-line:before{content:""}.ri-store-2-fill:before{content:""}.ri-store-2-line:before{content:""}.ri-store-3-fill:before{content:""}.ri-store-3-line:before{content:""}.ri-store-fill:before{content:""}.ri-store-line:before{content:""}.ri-strikethrough-2:before{content:""}.ri-strikethrough:before{content:""}.ri-subscript-2:before{content:""}.ri-subscript:before{content:""}.ri-subtract-fill:before{content:""}.ri-subtract-line:before{content:""}.ri-subway-fill:before{content:""}.ri-subway-line:before{content:""}.ri-subway-wifi-fill:before{content:""}.ri-subway-wifi-line:before{content:""}.ri-suitcase-2-fill:before{content:""}.ri-suitcase-2-line:before{content:""}.ri-suitcase-3-fill:before{content:""}.ri-suitcase-3-line:before{content:""}.ri-suitcase-fill:before{content:""}.ri-suitcase-line:before{content:""}.ri-sun-cloudy-fill:before{content:""}.ri-sun-cloudy-line:before{content:""}.ri-sun-fill:before{content:""}.ri-sun-foggy-fill:before{content:""}.ri-sun-foggy-line:before{content:""}.ri-sun-line:before{content:""}.ri-superscript-2:before{content:""}.ri-superscript:before{content:""}.ri-surgical-mask-fill:before{content:""}.ri-surgical-mask-line:before{content:""}.ri-surround-sound-fill:before{content:""}.ri-surround-sound-line:before{content:""}.ri-survey-fill:before{content:""}.ri-survey-line:before{content:""}.ri-swap-box-fill:before{content:""}.ri-swap-box-line:before{content:""}.ri-swap-fill:before{content:""}.ri-swap-line:before{content:""}.ri-switch-fill:before{content:""}.ri-switch-line:before{content:""}.ri-sword-fill:before{content:""}.ri-sword-line:before{content:""}.ri-syringe-fill:before{content:""}.ri-syringe-line:before{content:""}.ri-t-box-fill:before{content:""}.ri-t-box-line:before{content:""}.ri-t-shirt-2-fill:before{content:""}.ri-t-shirt-2-line:before{content:""}.ri-t-shirt-air-fill:before{content:""}.ri-t-shirt-air-line:before{content:""}.ri-t-shirt-fill:before{content:""}.ri-t-shirt-line:before{content:""}.ri-table-2:before{content:""}.ri-table-alt-fill:before{content:""}.ri-table-alt-line:before{content:""}.ri-table-fill:before{content:""}.ri-table-line:before{content:""}.ri-tablet-fill:before{content:""}.ri-tablet-line:before{content:""}.ri-takeaway-fill:before{content:""}.ri-takeaway-line:before{content:""}.ri-taobao-fill:before{content:""}.ri-taobao-line:before{content:""}.ri-tape-fill:before{content:""}.ri-tape-line:before{content:""}.ri-task-fill:before{content:""}.ri-task-line:before{content:""}.ri-taxi-fill:before{content:""}.ri-taxi-line:before{content:""}.ri-taxi-wifi-fill:before{content:""}.ri-taxi-wifi-line:before{content:""}.ri-team-fill:before{content:""}.ri-team-line:before{content:""}.ri-telegram-fill:before{content:""}.ri-telegram-line:before{content:""}.ri-temp-cold-fill:before{content:""}.ri-temp-cold-line:before{content:""}.ri-temp-hot-fill:before{content:""}.ri-temp-hot-line:before{content:""}.ri-terminal-box-fill:before{content:""}.ri-terminal-box-line:before{content:""}.ri-terminal-fill:before{content:""}.ri-terminal-line:before{content:""}.ri-terminal-window-fill:before{content:""}.ri-terminal-window-line:before{content:""}.ri-test-tube-fill:before{content:""}.ri-test-tube-line:before{content:""}.ri-text-direction-l:before{content:""}.ri-text-direction-r:before{content:""}.ri-text-spacing:before{content:""}.ri-text-wrap:before{content:""}.ri-text:before{content:""}.ri-thermometer-fill:before{content:""}.ri-thermometer-line:before{content:""}.ri-thumb-down-fill:before{content:""}.ri-thumb-down-line:before{content:""}.ri-thumb-up-fill:before{content:""}.ri-thumb-up-line:before{content:""}.ri-thunderstorms-fill:before{content:""}.ri-thunderstorms-line:before{content:""}.ri-ticket-2-fill:before{content:""}.ri-ticket-2-line:before{content:""}.ri-ticket-fill:before{content:""}.ri-ticket-line:before{content:""}.ri-time-fill:before{content:""}.ri-time-line:before{content:""}.ri-timer-2-fill:before{content:""}.ri-timer-2-line:before{content:""}.ri-timer-fill:before{content:""}.ri-timer-flash-fill:before{content:""}.ri-timer-flash-line:before{content:""}.ri-timer-line:before{content:""}.ri-todo-fill:before{content:""}.ri-todo-line:before{content:""}.ri-toggle-fill:before{content:""}.ri-toggle-line:before{content:""}.ri-tools-fill:before{content:""}.ri-tools-line:before{content:""}.ri-tornado-fill:before{content:""}.ri-tornado-line:before{content:""}.ri-trademark-fill:before{content:""}.ri-trademark-line:before{content:""}.ri-traffic-light-fill:before{content:""}.ri-traffic-light-line:before{content:""}.ri-train-fill:before{content:""}.ri-train-line:before{content:""}.ri-train-wifi-fill:before{content:""}.ri-train-wifi-line:before{content:""}.ri-translate-2:before{content:""}.ri-translate:before{content:""}.ri-travesti-fill:before{content:""}.ri-travesti-line:before{content:""}.ri-treasure-map-fill:before{content:""}.ri-treasure-map-line:before{content:""}.ri-trello-fill:before{content:""}.ri-trello-line:before{content:""}.ri-trophy-fill:before{content:""}.ri-trophy-line:before{content:""}.ri-truck-fill:before{content:""}.ri-truck-line:before{content:""}.ri-tumblr-fill:before{content:""}.ri-tumblr-line:before{content:""}.ri-tv-2-fill:before{content:""}.ri-tv-2-line:before{content:""}.ri-tv-fill:before{content:""}.ri-tv-line:before{content:""}.ri-twitch-fill:before{content:""}.ri-twitch-line:before{content:""}.ri-twitter-fill:before{content:""}.ri-twitter-line:before{content:""}.ri-typhoon-fill:before{content:""}.ri-typhoon-line:before{content:""}.ri-u-disk-fill:before{content:""}.ri-u-disk-line:before{content:""}.ri-ubuntu-fill:before{content:""}.ri-ubuntu-line:before{content:""}.ri-umbrella-fill:before{content:""}.ri-umbrella-line:before{content:""}.ri-underline:before{content:""}.ri-uninstall-fill:before{content:""}.ri-uninstall-line:before{content:""}.ri-unsplash-fill:before{content:""}.ri-unsplash-line:before{content:""}.ri-upload-2-fill:before{content:""}.ri-upload-2-line:before{content:""}.ri-upload-cloud-2-fill:before{content:""}.ri-upload-cloud-2-line:before{content:""}.ri-upload-cloud-fill:before{content:""}.ri-upload-cloud-line:before{content:""}.ri-upload-fill:before{content:""}.ri-upload-line:before{content:""}.ri-usb-fill:before{content:""}.ri-usb-line:before{content:""}.ri-user-2-fill:before{content:""}.ri-user-2-line:before{content:""}.ri-user-3-fill:before{content:""}.ri-user-3-line:before{content:""}.ri-user-4-fill:before{content:""}.ri-user-4-line:before{content:""}.ri-user-5-fill:before{content:""}.ri-user-5-line:before{content:""}.ri-user-6-fill:before{content:""}.ri-user-6-line:before{content:""}.ri-user-add-fill:before{content:""}.ri-user-add-line:before{content:""}.ri-user-fill:before{content:""}.ri-user-follow-fill:before{content:""}.ri-user-follow-line:before{content:""}.ri-user-heart-fill:before{content:""}.ri-user-heart-line:before{content:""}.ri-user-line:before{content:""}.ri-user-location-fill:before{content:""}.ri-user-location-line:before{content:""}.ri-user-received-2-fill:before{content:""}.ri-user-received-2-line:before{content:""}.ri-user-received-fill:before{content:""}.ri-user-received-line:before{content:""}.ri-user-search-fill:before{content:""}.ri-user-search-line:before{content:""}.ri-user-settings-fill:before{content:""}.ri-user-settings-line:before{content:""}.ri-user-shared-2-fill:before{content:""}.ri-user-shared-2-line:before{content:""}.ri-user-shared-fill:before{content:""}.ri-user-shared-line:before{content:""}.ri-user-smile-fill:before{content:""}.ri-user-smile-line:before{content:""}.ri-user-star-fill:before{content:""}.ri-user-star-line:before{content:""}.ri-user-unfollow-fill:before{content:""}.ri-user-unfollow-line:before{content:""}.ri-user-voice-fill:before{content:""}.ri-user-voice-line:before{content:""}.ri-video-add-fill:before{content:""}.ri-video-add-line:before{content:""}.ri-video-chat-fill:before{content:""}.ri-video-chat-line:before{content:""}.ri-video-download-fill:before{content:""}.ri-video-download-line:before{content:""}.ri-video-fill:before{content:""}.ri-video-line:before{content:""}.ri-video-upload-fill:before{content:""}.ri-video-upload-line:before{content:""}.ri-vidicon-2-fill:before{content:""}.ri-vidicon-2-line:before{content:""}.ri-vidicon-fill:before{content:""}.ri-vidicon-line:before{content:""}.ri-vimeo-fill:before{content:""}.ri-vimeo-line:before{content:""}.ri-vip-crown-2-fill:before{content:""}.ri-vip-crown-2-line:before{content:""}.ri-vip-crown-fill:before{content:""}.ri-vip-crown-line:before{content:""}.ri-vip-diamond-fill:before{content:""}.ri-vip-diamond-line:before{content:""}.ri-vip-fill:before{content:""}.ri-vip-line:before{content:""}.ri-virus-fill:before{content:""}.ri-virus-line:before{content:""}.ri-visa-fill:before{content:""}.ri-visa-line:before{content:""}.ri-voice-recognition-fill:before{content:""}.ri-voice-recognition-line:before{content:""}.ri-voiceprint-fill:before{content:""}.ri-voiceprint-line:before{content:""}.ri-volume-down-fill:before{content:""}.ri-volume-down-line:before{content:""}.ri-volume-mute-fill:before{content:""}.ri-volume-mute-line:before{content:""}.ri-volume-off-vibrate-fill:before{content:""}.ri-volume-off-vibrate-line:before{content:""}.ri-volume-up-fill:before{content:""}.ri-volume-up-line:before{content:""}.ri-volume-vibrate-fill:before{content:""}.ri-volume-vibrate-line:before{content:""}.ri-vuejs-fill:before{content:""}.ri-vuejs-line:before{content:""}.ri-walk-fill:before{content:""}.ri-walk-line:before{content:""}.ri-wallet-2-fill:before{content:""}.ri-wallet-2-line:before{content:""}.ri-wallet-3-fill:before{content:""}.ri-wallet-3-line:before{content:""}.ri-wallet-fill:before{content:""}.ri-wallet-line:before{content:""}.ri-water-flash-fill:before{content:""}.ri-water-flash-line:before{content:""}.ri-webcam-fill:before{content:""}.ri-webcam-line:before{content:""}.ri-wechat-2-fill:before{content:""}.ri-wechat-2-line:before{content:""}.ri-wechat-fill:before{content:""}.ri-wechat-line:before{content:""}.ri-wechat-pay-fill:before{content:""}.ri-wechat-pay-line:before{content:""}.ri-weibo-fill:before{content:""}.ri-weibo-line:before{content:""}.ri-whatsapp-fill:before{content:""}.ri-whatsapp-line:before{content:""}.ri-wheelchair-fill:before{content:""}.ri-wheelchair-line:before{content:""}.ri-wifi-fill:before{content:""}.ri-wifi-line:before{content:""}.ri-wifi-off-fill:before{content:""}.ri-wifi-off-line:before{content:""}.ri-window-2-fill:before{content:""}.ri-window-2-line:before{content:""}.ri-window-fill:before{content:""}.ri-window-line:before{content:""}.ri-windows-fill:before{content:""}.ri-windows-line:before{content:""}.ri-windy-fill:before{content:""}.ri-windy-line:before{content:""}.ri-wireless-charging-fill:before{content:""}.ri-wireless-charging-line:before{content:""}.ri-women-fill:before{content:""}.ri-women-line:before{content:""}.ri-wubi-input:before{content:""}.ri-xbox-fill:before{content:""}.ri-xbox-line:before{content:""}.ri-xing-fill:before{content:""}.ri-xing-line:before{content:""}.ri-youtube-fill:before{content:""}.ri-youtube-line:before{content:""}.ri-zcool-fill:before{content:""}.ri-zcool-line:before{content:""}.ri-zhihu-fill:before{content:""}.ri-zhihu-line:before{content:""}.ri-zoom-in-fill:before{content:""}.ri-zoom-in-line:before{content:""}.ri-zoom-out-fill:before{content:""}.ri-zoom-out-line:before{content:""}.ri-zzz-fill:before{content:""}.ri-zzz-line:before{content:""}.ri-arrow-down-double-fill:before{content:""}.ri-arrow-down-double-line:before{content:""}.ri-arrow-left-double-fill:before{content:""}.ri-arrow-left-double-line:before{content:""}.ri-arrow-right-double-fill:before{content:""}.ri-arrow-right-double-line:before{content:""}.ri-arrow-turn-back-fill:before{content:""}.ri-arrow-turn-back-line:before{content:""}.ri-arrow-turn-forward-fill:before{content:""}.ri-arrow-turn-forward-line:before{content:""}.ri-arrow-up-double-fill:before{content:""}.ri-arrow-up-double-line:before{content:""}.ri-bard-fill:before{content:""}.ri-bard-line:before{content:""}.ri-bootstrap-fill:before{content:""}.ri-bootstrap-line:before{content:""}.ri-box-1-fill:before{content:""}.ri-box-1-line:before{content:""}.ri-box-2-fill:before{content:""}.ri-box-2-line:before{content:""}.ri-box-3-fill:before{content:""}.ri-box-3-line:before{content:""}.ri-brain-fill:before{content:""}.ri-brain-line:before{content:""}.ri-candle-fill:before{content:""}.ri-candle-line:before{content:""}.ri-cash-fill:before{content:""}.ri-cash-line:before{content:""}.ri-contract-left-fill:before{content:""}.ri-contract-left-line:before{content:""}.ri-contract-left-right-fill:before{content:""}.ri-contract-left-right-line:before{content:""}.ri-contract-right-fill:before{content:""}.ri-contract-right-line:before{content:""}.ri-contract-up-down-fill:before{content:""}.ri-contract-up-down-line:before{content:""}.ri-copilot-fill:before{content:""}.ri-copilot-line:before{content:""}.ri-corner-down-left-fill:before{content:""}.ri-corner-down-left-line:before{content:""}.ri-corner-down-right-fill:before{content:""}.ri-corner-down-right-line:before{content:""}.ri-corner-left-down-fill:before{content:""}.ri-corner-left-down-line:before{content:""}.ri-corner-left-up-fill:before{content:""}.ri-corner-left-up-line:before{content:""}.ri-corner-right-down-fill:before{content:""}.ri-corner-right-down-line:before{content:""}.ri-corner-right-up-fill:before{content:""}.ri-corner-right-up-line:before{content:""}.ri-corner-up-left-double-fill:before{content:""}.ri-corner-up-left-double-line:before{content:""}.ri-corner-up-left-fill:before{content:""}.ri-corner-up-left-line:before{content:""}.ri-corner-up-right-double-fill:before{content:""}.ri-corner-up-right-double-line:before{content:""}.ri-corner-up-right-fill:before{content:""}.ri-corner-up-right-line:before{content:""}.ri-cross-fill:before{content:""}.ri-cross-line:before{content:""}.ri-edge-new-fill:before{content:""}.ri-edge-new-line:before{content:""}.ri-equal-fill:before{content:""}.ri-equal-line:before{content:""}.ri-expand-left-fill:before{content:""}.ri-expand-left-line:before{content:""}.ri-expand-left-right-fill:before{content:""}.ri-expand-left-right-line:before{content:""}.ri-expand-right-fill:before{content:""}.ri-expand-right-line:before{content:""}.ri-expand-up-down-fill:before{content:""}.ri-expand-up-down-line:before{content:""}.ri-flickr-fill:before{content:""}.ri-flickr-line:before{content:""}.ri-forward-10-fill:before{content:""}.ri-forward-10-line:before{content:""}.ri-forward-15-fill:before{content:""}.ri-forward-15-line:before{content:""}.ri-forward-30-fill:before{content:""}.ri-forward-30-line:before{content:""}.ri-forward-5-fill:before{content:""}.ri-forward-5-line:before{content:""}.ri-graduation-cap-fill:before{content:""}.ri-graduation-cap-line:before{content:""}.ri-home-office-fill:before{content:""}.ri-home-office-line:before{content:""}.ri-hourglass-2-fill:before{content:""}.ri-hourglass-2-line:before{content:""}.ri-hourglass-fill:before{content:""}.ri-hourglass-line:before{content:""}.ri-javascript-fill:before{content:""}.ri-javascript-line:before{content:""}.ri-loop-left-fill:before{content:""}.ri-loop-left-line:before{content:""}.ri-loop-right-fill:before{content:""}.ri-loop-right-line:before{content:""}.ri-memories-fill:before{content:""}.ri-memories-line:before{content:""}.ri-meta-fill:before{content:""}.ri-meta-line:before{content:""}.ri-microsoft-loop-fill:before{content:""}.ri-microsoft-loop-line:before{content:""}.ri-nft-fill:before{content:""}.ri-nft-line:before{content:""}.ri-notion-fill:before{content:""}.ri-notion-line:before{content:""}.ri-openai-fill:before{content:""}.ri-openai-line:before{content:""}.ri-overline:before{content:""}.ri-p2p-fill:before{content:""}.ri-p2p-line:before{content:""}.ri-presentation-fill:before{content:""}.ri-presentation-line:before{content:""}.ri-replay-10-fill:before{content:""}.ri-replay-10-line:before{content:""}.ri-replay-15-fill:before{content:""}.ri-replay-15-line:before{content:""}.ri-replay-30-fill:before{content:""}.ri-replay-30-line:before{content:""}.ri-replay-5-fill:before{content:""}.ri-replay-5-line:before{content:""}.ri-school-fill:before{content:""}.ri-school-line:before{content:""}.ri-shining-2-fill:before{content:""}.ri-shining-2-line:before{content:""}.ri-shining-fill:before{content:""}.ri-shining-line:before{content:""}.ri-sketching:before{content:""}.ri-skip-down-fill:before{content:""}.ri-skip-down-line:before{content:""}.ri-skip-left-fill:before{content:""}.ri-skip-left-line:before{content:""}.ri-skip-right-fill:before{content:""}.ri-skip-right-line:before{content:""}.ri-skip-up-fill:before{content:""}.ri-skip-up-line:before{content:""}.ri-slow-down-fill:before{content:""}.ri-slow-down-line:before{content:""}.ri-sparkling-2-fill:before{content:""}.ri-sparkling-2-line:before{content:""}.ri-sparkling-fill:before{content:""}.ri-sparkling-line:before{content:""}.ri-speak-fill:before{content:""}.ri-speak-line:before{content:""}.ri-speed-up-fill:before{content:""}.ri-speed-up-line:before{content:""}.ri-tiktok-fill:before{content:""}.ri-tiktok-line:before{content:""}.ri-token-swap-fill:before{content:""}.ri-token-swap-line:before{content:""}.ri-unpin-fill:before{content:""}.ri-unpin-line:before{content:""}.ri-wechat-channels-fill:before{content:""}.ri-wechat-channels-line:before{content:""}.ri-wordpress-fill:before{content:""}.ri-wordpress-line:before{content:""}.ri-blender-fill:before{content:""}.ri-blender-line:before{content:""}.ri-emoji-sticker-fill:before{content:""}.ri-emoji-sticker-line:before{content:""}.ri-git-close-pull-request-fill:before{content:""}.ri-git-close-pull-request-line:before{content:""}.ri-instance-fill:before{content:""}.ri-instance-line:before{content:""}.ri-megaphone-fill:before{content:""}.ri-megaphone-line:before{content:""}.ri-pass-expired-fill:before{content:""}.ri-pass-expired-line:before{content:""}.ri-pass-pending-fill:before{content:""}.ri-pass-pending-line:before{content:""}.ri-pass-valid-fill:before{content:""}.ri-pass-valid-line:before{content:""}.ri-ai-generate:before{content:""}.ri-calendar-close-fill:before{content:""}.ri-calendar-close-line:before{content:""}.ri-draggable:before{content:""}.ri-font-family:before{content:""}.ri-font-mono:before{content:""}.ri-font-sans-serif:before{content:""}.ri-font-sans:before{content:""}.ri-hard-drive-3-fill:before{content:""}.ri-hard-drive-3-line:before{content:""}.ri-kick-fill:before{content:""}.ri-kick-line:before{content:""}.ri-list-check-3:before{content:""}.ri-list-indefinite:before{content:""}.ri-list-ordered-2:before{content:""}.ri-list-radio:before{content:""}.ri-openbase-fill:before{content:""}.ri-openbase-line:before{content:""}.ri-planet-fill:before{content:""}.ri-planet-line:before{content:""}.ri-prohibited-fill:before{content:""}.ri-prohibited-line:before{content:""}.ri-quote-text:before{content:""}.ri-seo-fill:before{content:""}.ri-seo-line:before{content:""}.ri-slash-commands:before{content:""}.ri-archive-2-fill:before{content:""}.ri-archive-2-line:before{content:""}.ri-inbox-2-fill:before{content:""}.ri-inbox-2-line:before{content:""}.ri-shake-hands-fill:before{content:""}.ri-shake-hands-line:before{content:""}.ri-supabase-fill:before{content:""}.ri-supabase-line:before{content:""}.ri-water-percent-fill:before{content:""}.ri-water-percent-line:before{content:""}.ri-yuque-fill:before{content:""}.ri-yuque-line:before{content:""}.ri-crosshair-2-fill:before{content:""}.ri-crosshair-2-line:before{content:""}.ri-crosshair-fill:before{content:""}.ri-crosshair-line:before{content:""}.ri-file-close-fill:before{content:""}.ri-file-close-line:before{content:""}.ri-infinity-fill:before{content:""}.ri-infinity-line:before{content:""}.ri-rfid-fill:before{content:""}.ri-rfid-line:before{content:""}.ri-slash-commands-2:before{content:""}.ri-user-forbid-fill:before{content:""}.ri-user-forbid-line:before{content:""}.ri-beer-fill:before{content:""}.ri-beer-line:before{content:""}.ri-circle-fill:before{content:""}.ri-circle-line:before{content:""}.ri-dropdown-list:before{content:""}.ri-file-image-fill:before{content:""}.ri-file-image-line:before{content:""}.ri-file-pdf-2-fill:before{content:""}.ri-file-pdf-2-line:before{content:""}.ri-file-video-fill:before{content:""}.ri-file-video-line:before{content:""}.ri-folder-image-fill:before{content:""}.ri-folder-image-line:before{content:""}.ri-folder-video-fill:before{content:""}.ri-folder-video-line:before{content:""}.ri-hexagon-fill:before{content:""}.ri-hexagon-line:before{content:""}.ri-menu-search-fill:before{content:""}.ri-menu-search-line:before{content:""}.ri-octagon-fill:before{content:""}.ri-octagon-line:before{content:""}.ri-pentagon-fill:before{content:""}.ri-pentagon-line:before{content:""}.ri-rectangle-fill:before{content:""}.ri-rectangle-line:before{content:""}.ri-robot-2-fill:before{content:""}.ri-robot-2-line:before{content:""}.ri-shapes-fill:before{content:""}.ri-shapes-line:before{content:""}.ri-square-fill:before{content:""}.ri-square-line:before{content:""}.ri-tent-fill:before{content:""}.ri-tent-line:before{content:""}.ri-threads-fill:before{content:""}.ri-threads-line:before{content:""}.ri-tree-fill:before{content:""}.ri-tree-line:before{content:""}.ri-triangle-fill:before{content:""}.ri-triangle-line:before{content:""}.ri-twitter-x-fill:before{content:""}.ri-twitter-x-line:before{content:""}.ri-verified-badge-fill:before{content:""}.ri-verified-badge-line:before{content:""}.ri-armchair-fill:before{content:""}.ri-armchair-line:before{content:""}.ri-bnb-fill:before{content:""}.ri-bnb-line:before{content:""}.ri-bread-fill:before{content:""}.ri-bread-line:before{content:""}.ri-btc-fill:before{content:""}.ri-btc-line:before{content:""}.ri-calendar-schedule-fill:before{content:""}.ri-calendar-schedule-line:before{content:""}.ri-dice-1-fill:before{content:""}.ri-dice-1-line:before{content:""}.ri-dice-2-fill:before{content:""}.ri-dice-2-line:before{content:""}.ri-dice-3-fill:before{content:""}.ri-dice-3-line:before{content:""}.ri-dice-4-fill:before{content:""}.ri-dice-4-line:before{content:""}.ri-dice-5-fill:before{content:""}.ri-dice-5-line:before{content:""}.ri-dice-6-fill:before{content:""}.ri-dice-6-line:before{content:""}.ri-dice-fill:before{content:""}.ri-dice-line:before{content:""}.ri-drinks-fill:before{content:""}.ri-drinks-line:before{content:""}.ri-equalizer-2-fill:before{content:""}.ri-equalizer-2-line:before{content:""}.ri-equalizer-3-fill:before{content:""}.ri-equalizer-3-line:before{content:""}.ri-eth-fill:before{content:""}.ri-eth-line:before{content:""}.ri-flower-fill:before{content:""}.ri-flower-line:before{content:""}.ri-glasses-2-fill:before{content:""}.ri-glasses-2-line:before{content:""}.ri-glasses-fill:before{content:""}.ri-glasses-line:before{content:""}.ri-goggles-fill:before{content:""}.ri-goggles-line:before{content:""}.ri-image-circle-fill:before{content:""}.ri-image-circle-line:before{content:""}.ri-info-i:before{content:""}.ri-money-rupee-circle-fill:before{content:""}.ri-money-rupee-circle-line:before{content:""}.ri-news-fill:before{content:""}.ri-news-line:before{content:""}.ri-robot-3-fill:before{content:""}.ri-robot-3-line:before{content:""}.ri-share-2-fill:before{content:""}.ri-share-2-line:before{content:""}.ri-sofa-fill:before{content:""}.ri-sofa-line:before{content:""}.ri-svelte-fill:before{content:""}.ri-svelte-line:before{content:""}.ri-vk-fill:before{content:""}.ri-vk-line:before{content:""}.ri-xrp-fill:before{content:""}.ri-xrp-line:before{content:""}.ri-xtz-fill:before{content:""}.ri-xtz-line:before{content:""}.ri-archive-stack-fill:before{content:""}.ri-archive-stack-line:before{content:""}.ri-bowl-fill:before{content:""}.ri-bowl-line:before{content:""}.ri-calendar-view:before{content:""}.ri-carousel-view:before{content:""}.ri-code-block:before{content:""}.ri-color-filter-fill:before{content:""}.ri-color-filter-line:before{content:""}.ri-contacts-book-3-fill:before{content:""}.ri-contacts-book-3-line:before{content:""}.ri-contract-fill:before{content:""}.ri-contract-line:before{content:""}.ri-drinks-2-fill:before{content:""}.ri-drinks-2-line:before{content:""}.ri-export-fill:before{content:""}.ri-export-line:before{content:""}.ri-file-check-fill:before{content:""}.ri-file-check-line:before{content:""}.ri-focus-mode:before{content:""}.ri-folder-6-fill:before{content:""}.ri-folder-6-line:before{content:""}.ri-folder-check-fill:before{content:""}.ri-folder-check-line:before{content:""}.ri-folder-close-fill:before{content:""}.ri-folder-close-line:before{content:""}.ri-folder-cloud-fill:before{content:""}.ri-folder-cloud-line:before{content:""}.ri-gallery-view-2:before{content:""}.ri-gallery-view:before{content:""}.ri-hand:before{content:""}.ri-import-fill:before{content:""}.ri-import-line:before{content:""}.ri-information-2-fill:before{content:""}.ri-information-2-line:before{content:""}.ri-kanban-view-2:before{content:""}.ri-kanban-view:before{content:""}.ri-list-view:before{content:""}.ri-lock-star-fill:before{content:""}.ri-lock-star-line:before{content:""}.ri-puzzle-2-fill:before{content:""}.ri-puzzle-2-line:before{content:""}.ri-puzzle-fill:before{content:""}.ri-puzzle-line:before{content:""}.ri-ram-2-fill:before{content:""}.ri-ram-2-line:before{content:""}.ri-ram-fill:before{content:""}.ri-ram-line:before{content:""}.ri-receipt-fill:before{content:""}.ri-receipt-line:before{content:""}.ri-shadow-fill:before{content:""}.ri-shadow-line:before{content:""}.ri-sidebar-fold-fill:before{content:""}.ri-sidebar-fold-line:before{content:""}.ri-sidebar-unfold-fill:before{content:""}.ri-sidebar-unfold-line:before{content:""}.ri-slideshow-view:before{content:""}.ri-sort-alphabet-asc:before{content:""}.ri-sort-alphabet-desc:before{content:""}.ri-sort-number-asc:before{content:""}.ri-sort-number-desc:before{content:""}.ri-stacked-view:before{content:""}.ri-sticky-note-add-fill:before{content:""}.ri-sticky-note-add-line:before{content:""}.ri-swap-2-fill:before{content:""}.ri-swap-2-line:before{content:""}.ri-swap-3-fill:before{content:""}.ri-swap-3-line:before{content:""}.ri-table-3:before{content:""}.ri-table-view:before{content:""}.ri-text-block:before{content:""}.ri-text-snippet:before{content:""}.ri-timeline-view:before{content:""}.ri-blogger-fill:before{content:""}.ri-blogger-line:before{content:""}.ri-chat-thread-fill:before{content:""}.ri-chat-thread-line:before{content:""}.ri-discount-percent-fill:before{content:""}.ri-discount-percent-line:before{content:""}.ri-exchange-2-fill:before{content:""}.ri-exchange-2-line:before{content:""}.ri-git-fork-fill:before{content:""}.ri-git-fork-line:before{content:""}.ri-input-field:before{content:""}.ri-progress-1-fill:before{content:""}.ri-progress-1-line:before{content:""}.ri-progress-2-fill:before{content:""}.ri-progress-2-line:before{content:""}.ri-progress-3-fill:before{content:""}.ri-progress-3-line:before{content:""}.ri-progress-4-fill:before{content:""}.ri-progress-4-line:before{content:""}.ri-progress-5-fill:before{content:""}.ri-progress-5-line:before{content:""}.ri-progress-6-fill:before{content:""}.ri-progress-6-line:before{content:""}.ri-progress-7-fill:before{content:""}.ri-progress-7-line:before{content:""}.ri-progress-8-fill:before{content:""}.ri-progress-8-line:before{content:""}.ri-remix-run-fill:before{content:""}.ri-remix-run-line:before{content:""}.ri-signpost-fill:before{content:""}.ri-signpost-line:before{content:""}.ri-time-zone-fill:before{content:""}.ri-time-zone-line:before{content:""}.ri-arrow-down-wide-fill:before{content:""}.ri-arrow-down-wide-line:before{content:""}.ri-arrow-left-wide-fill:before{content:""}.ri-arrow-left-wide-line:before{content:""}.ri-arrow-right-wide-fill:before{content:""}.ri-arrow-right-wide-line:before{content:""}.ri-arrow-up-wide-fill:before{content:""}.ri-arrow-up-wide-line:before{content:""}.ri-bluesky-fill:before{content:""}.ri-bluesky-line:before{content:""}.ri-expand-height-fill:before{content:""}.ri-expand-height-line:before{content:""}.ri-expand-width-fill:before{content:""}.ri-expand-width-line:before{content:""}.ri-forward-end-fill:before{content:""}.ri-forward-end-line:before{content:""}.ri-forward-end-mini-fill:before{content:""}.ri-forward-end-mini-line:before{content:""}.ri-friendica-fill:before{content:""}.ri-friendica-line:before{content:""}.ri-git-pr-draft-fill:before{content:""}.ri-git-pr-draft-line:before{content:""}.ri-play-reverse-fill:before{content:""}.ri-play-reverse-line:before{content:""}.ri-play-reverse-mini-fill:before{content:""}.ri-play-reverse-mini-line:before{content:""}.ri-rewind-start-fill:before{content:""}.ri-rewind-start-line:before{content:""}.ri-rewind-start-mini-fill:before{content:""}.ri-rewind-start-mini-line:before{content:""}.ri-scroll-to-bottom-fill:before{content:""}.ri-scroll-to-bottom-line:before{content:""}.ri-add-large-fill:before{content:""}.ri-add-large-line:before{content:""}.ri-aed-electrodes-fill:before{content:""}.ri-aed-electrodes-line:before{content:""}.ri-aed-fill:before{content:""}.ri-aed-line:before{content:""}.ri-alibaba-cloud-fill:before{content:""}.ri-alibaba-cloud-line:before{content:""}.ri-align-item-bottom-fill:before{content:""}.ri-align-item-bottom-line:before{content:""}.ri-align-item-horizontal-center-fill:before{content:""}.ri-align-item-horizontal-center-line:before{content:""}.ri-align-item-left-fill:before{content:""}.ri-align-item-left-line:before{content:""}.ri-align-item-right-fill:before{content:""}.ri-align-item-right-line:before{content:""}.ri-align-item-top-fill:before{content:""}.ri-align-item-top-line:before{content:""}.ri-align-item-vertical-center-fill:before{content:""}.ri-align-item-vertical-center-line:before{content:""}.ri-apps-2-add-fill:before{content:""}.ri-apps-2-add-line:before{content:""}.ri-close-large-fill:before{content:""}.ri-close-large-line:before{content:""}.ri-collapse-diagonal-2-fill:before{content:""}.ri-collapse-diagonal-2-line:before{content:""}.ri-collapse-diagonal-fill:before{content:""}.ri-collapse-diagonal-line:before{content:""}.ri-dashboard-horizontal-fill:before{content:""}.ri-dashboard-horizontal-line:before{content:""}.ri-expand-diagonal-2-fill:before{content:""}.ri-expand-diagonal-2-line:before{content:""}.ri-expand-diagonal-fill:before{content:""}.ri-expand-diagonal-line:before{content:""}.ri-firebase-fill:before{content:""}.ri-firebase-line:before{content:""}.ri-flip-horizontal-2-fill:before{content:""}.ri-flip-horizontal-2-line:before{content:""}.ri-flip-horizontal-fill:before{content:""}.ri-flip-horizontal-line:before{content:""}.ri-flip-vertical-2-fill:before{content:""}.ri-flip-vertical-2-line:before{content:""}.ri-flip-vertical-fill:before{content:""}.ri-flip-vertical-line:before{content:""}.ri-formula:before{content:""}.ri-function-add-fill:before{content:""}.ri-function-add-line:before{content:""}.ri-goblet-2-fill:before{content:""}.ri-goblet-2-line:before{content:""}.ri-golf-ball-fill:before{content:""}.ri-golf-ball-line:before{content:""}.ri-group-3-fill:before{content:""}.ri-group-3-line:before{content:""}.ri-heart-add-2-fill:before{content:""}.ri-heart-add-2-line:before{content:""}.ri-id-card-fill:before{content:""}.ri-id-card-line:before{content:""}.ri-information-off-fill:before{content:""}.ri-information-off-line:before{content:""}.ri-java-fill:before{content:""}.ri-java-line:before{content:""}.ri-layout-grid-2-fill:before{content:""}.ri-layout-grid-2-line:before{content:""}.ri-layout-horizontal-fill:before{content:""}.ri-layout-horizontal-line:before{content:""}.ri-layout-vertical-fill:before{content:""}.ri-layout-vertical-line:before{content:""}.ri-menu-fold-2-fill:before{content:""}.ri-menu-fold-2-line:before{content:""}.ri-menu-fold-3-fill:before{content:""}.ri-menu-fold-3-line:before{content:""}.ri-menu-fold-4-fill:before{content:""}.ri-menu-fold-4-line:before{content:""}.ri-menu-unfold-2-fill:before{content:""}.ri-menu-unfold-2-line:before{content:""}.ri-menu-unfold-3-fill:before{content:""}.ri-menu-unfold-3-line:before{content:""}.ri-menu-unfold-4-fill:before{content:""}.ri-menu-unfold-4-line:before{content:""}.ri-mobile-download-fill:before{content:""}.ri-mobile-download-line:before{content:""}.ri-nextjs-fill:before{content:""}.ri-nextjs-line:before{content:""}.ri-nodejs-fill:before{content:""}.ri-nodejs-line:before{content:""}.ri-pause-large-fill:before{content:""}.ri-pause-large-line:before{content:""}.ri-play-large-fill:before{content:""}.ri-play-large-line:before{content:""}.ri-play-reverse-large-fill:before{content:""}.ri-play-reverse-large-line:before{content:""}.ri-police-badge-fill:before{content:""}.ri-police-badge-line:before{content:""}.ri-prohibited-2-fill:before{content:""}.ri-prohibited-2-line:before{content:""}.ri-shopping-bag-4-fill:before{content:""}.ri-shopping-bag-4-line:before{content:""}.ri-snowflake-fill:before{content:""}.ri-snowflake-line:before{content:""}.ri-square-root:before{content:""}.ri-stop-large-fill:before{content:""}.ri-stop-large-line:before{content:""}.ri-tailwind-css-fill:before{content:""}.ri-tailwind-css-line:before{content:""}.ri-tooth-fill:before{content:""}.ri-tooth-line:before{content:""}.ri-video-off-fill:before{content:""}.ri-video-off-line:before{content:""}.ri-video-on-fill:before{content:""}.ri-video-on-line:before{content:""}.ri-webhook-fill:before{content:""}.ri-webhook-line:before{content:""}.ri-weight-fill:before{content:""}.ri-weight-line:before{content:""}.ri-book-shelf-fill:before{content:""}.ri-book-shelf-line:before{content:""}.ri-brain-2-fill:before{content:""}.ri-brain-2-line:before{content:""}.ri-chat-search-fill:before{content:""}.ri-chat-search-line:before{content:""}.ri-chat-unread-fill:before{content:""}.ri-chat-unread-line:before{content:""}.ri-collapse-horizontal-fill:before{content:""}.ri-collapse-horizontal-line:before{content:""}.ri-collapse-vertical-fill:before{content:""}.ri-collapse-vertical-line:before{content:""}.ri-dna-fill:before{content:""}.ri-dna-line:before{content:""}.ri-dropper-fill:before{content:""}.ri-dropper-line:before{content:""}.ri-expand-diagonal-s-2-fill:before{content:""}.ri-expand-diagonal-s-2-line:before{content:""}.ri-expand-diagonal-s-fill:before{content:""}.ri-expand-diagonal-s-line:before{content:""}.ri-expand-horizontal-fill:before{content:""}.ri-expand-horizontal-line:before{content:""}.ri-expand-horizontal-s-fill:before{content:""}.ri-expand-horizontal-s-line:before{content:""}.ri-expand-vertical-fill:before{content:""}.ri-expand-vertical-line:before{content:""}.ri-expand-vertical-s-fill:before{content:""}.ri-expand-vertical-s-line:before{content:""}.ri-gemini-fill:before{content:""}.ri-gemini-line:before{content:""}.ri-reset-left-fill:before{content:""}.ri-reset-left-line:before{content:""}.ri-reset-right-fill:before{content:""}.ri-reset-right-line:before{content:""}.ri-stairs-fill:before{content:""}.ri-stairs-line:before{content:""}.ri-telegram-2-fill:before{content:""}.ri-telegram-2-line:before{content:""}.ri-triangular-flag-fill:before{content:""}.ri-triangular-flag-line:before{content:""}.ri-user-minus-fill:before{content:""}.ri-user-minus-line:before{content:""}.ri-account-box-2-fill:before{content:""}.ri-account-box-2-line:before{content:""}.ri-account-circle-2-fill:before{content:""}.ri-account-circle-2-line:before{content:""}.ri-alarm-snooze-fill:before{content:""}.ri-alarm-snooze-line:before{content:""}.ri-arrow-down-box-fill:before{content:""}.ri-arrow-down-box-line:before{content:""}.ri-arrow-left-box-fill:before{content:""}.ri-arrow-left-box-line:before{content:""}.ri-arrow-left-down-box-fill:before{content:""}.ri-arrow-left-down-box-line:before{content:""}.ri-arrow-left-up-box-fill:before{content:""}.ri-arrow-left-up-box-line:before{content:""}.ri-arrow-right-box-fill:before{content:""}.ri-arrow-right-box-line:before{content:""}.ri-arrow-right-down-box-fill:before{content:""}.ri-arrow-right-down-box-line:before{content:""}.ri-arrow-right-up-box-fill:before{content:""}.ri-arrow-right-up-box-line:before{content:""}.ri-arrow-up-box-fill:before{content:""}.ri-arrow-up-box-line:before{content:""}.ri-bar-chart-box-ai-fill:before{content:""}.ri-bar-chart-box-ai-line:before{content:""}.ri-brush-ai-fill:before{content:""}.ri-brush-ai-line:before{content:""}.ri-camera-ai-fill:before{content:""}.ri-camera-ai-line:before{content:""}.ri-chat-ai-fill:before{content:""}.ri-chat-ai-line:before{content:""}.ri-chat-smile-ai-fill:before{content:""}.ri-chat-smile-ai-line:before{content:""}.ri-chat-voice-ai-fill:before{content:""}.ri-chat-voice-ai-line:before{content:""}.ri-code-ai-fill:before{content:""}.ri-code-ai-line:before{content:""}.ri-color-filter-ai-fill:before{content:""}.ri-color-filter-ai-line:before{content:""}.ri-custom-size:before{content:""}.ri-fediverse-fill:before{content:""}.ri-fediverse-line:before{content:""}.ri-flag-off-fill:before{content:""}.ri-flag-off-line:before{content:""}.ri-home-9-fill:before{content:""}.ri-home-9-line:before{content:""}.ri-image-ai-fill:before{content:""}.ri-image-ai-line:before{content:""}.ri-image-circle-ai-fill:before{content:""}.ri-image-circle-ai-line:before{content:""}.ri-info-card-fill:before{content:""}.ri-info-card-line:before{content:""}.ri-landscape-ai-fill:before{content:""}.ri-landscape-ai-line:before{content:""}.ri-letter-spacing-2:before{content:""}.ri-line-height-2:before{content:""}.ri-mail-ai-fill:before{content:""}.ri-mail-ai-line:before{content:""}.ri-mic-2-ai-fill:before{content:""}.ri-mic-2-ai-line:before{content:""}.ri-mic-ai-fill:before{content:""}.ri-mic-ai-line:before{content:""}.ri-movie-ai-fill:before{content:""}.ri-movie-ai-line:before{content:""}.ri-music-ai-fill:before{content:""}.ri-music-ai-line:before{content:""}.ri-notification-snooze-fill:before{content:""}.ri-notification-snooze-line:before{content:""}.ri-php-fill:before{content:""}.ri-php-line:before{content:""}.ri-pix-fill:before{content:""}.ri-pix-line:before{content:""}.ri-pulse-ai-fill:before{content:""}.ri-pulse-ai-line:before{content:""}.ri-quill-pen-ai-fill:before{content:""}.ri-quill-pen-ai-line:before{content:""}.ri-speak-ai-fill:before{content:""}.ri-speak-ai-line:before{content:""}.ri-star-off-fill:before{content:""}.ri-star-off-line:before{content:""}.ri-translate-ai-2:before{content:""}.ri-translate-ai:before{content:""}.ri-user-community-fill:before{content:""}.ri-user-community-line:before{content:""}.ri-vercel-fill:before{content:""}.ri-vercel-line:before{content:""}.ri-video-ai-fill:before{content:""}.ri-video-ai-line:before{content:""}.ri-video-on-ai-fill:before{content:""}.ri-video-on-ai-line:before{content:""}.ri-voice-ai-fill:before{content:""}.ri-voice-ai-line:before{content:""}.ri-ai-generate-2:before{content:""}.ri-ai-generate-text:before{content:""}.ri-anthropic-fill:before{content:""}.ri-anthropic-line:before{content:""}.ri-apps-2-ai-fill:before{content:""}.ri-apps-2-ai-line:before{content:""}.ri-camera-lens-ai-fill:before{content:""}.ri-camera-lens-ai-line:before{content:""}.ri-clapperboard-ai-fill:before{content:""}.ri-clapperboard-ai-line:before{content:""}.ri-claude-fill:before{content:""}.ri-claude-line:before{content:""}.ri-closed-captioning-ai-fill:before{content:""}.ri-closed-captioning-ai-line:before{content:""}.ri-dvd-ai-fill:before{content:""}.ri-dvd-ai-line:before{content:""}.ri-film-ai-fill:before{content:""}.ri-film-ai-line:before{content:""}.ri-font-size-ai:before{content:""}.ri-mixtral-fill:before{content:""}.ri-mixtral-line:before{content:""}.ri-movie-2-ai-fill:before{content:""}.ri-movie-2-ai-line:before{content:""}.ri-mv-ai-fill:before{content:""}.ri-mv-ai-line:before{content:""}.ri-perplexity-fill:before{content:""}.ri-perplexity-line:before{content:""}.ri-poker-clubs-fill:before{content:""}.ri-poker-clubs-line:before{content:""}.ri-poker-diamonds-fill:before{content:""}.ri-poker-diamonds-line:before{content:""}.ri-poker-hearts-fill:before{content:""}.ri-poker-hearts-line:before{content:""}.ri-poker-spades-fill:before{content:""}.ri-poker-spades-line:before{content:""}.ri-safe-3-fill:before{content:""}.ri-safe-3-line:before{content:""}.ri-accessibility-fill:before{content:""}.ri-accessibility-line:before{content:""}.ri-alarm-add-fill:before{content:""}.ri-alarm-add-line:before{content:""}.ri-arrow-down-long-fill:before{content:""}.ri-arrow-down-long-line:before{content:""}.ri-arrow-left-down-long-fill:before{content:""}.ri-arrow-left-down-long-line:before{content:""}.ri-arrow-left-long-fill:before{content:""}.ri-arrow-left-long-line:before{content:""}.ri-arrow-left-up-long-fill:before{content:""}.ri-arrow-left-up-long-line:before{content:""}.ri-arrow-right-down-long-fill:before{content:""}.ri-arrow-right-down-long-line:before{content:""}.ri-arrow-right-long-fill:before{content:""}.ri-arrow-right-long-line:before{content:""}.ri-arrow-right-up-long-fill:before{content:""}.ri-arrow-right-up-long-line:before{content:""}.ri-arrow-up-long-fill:before{content:""}.ri-arrow-up-long-line:before{content:""}.ri-chess-fill:before{content:""}.ri-chess-line:before{content:""}.ri-diamond-fill:before{content:""}.ri-diamond-line:before{content:""}.ri-diamond-ring-fill:before{content:""}.ri-diamond-ring-line:before{content:""}.ri-figma-fill:before{content:""}.ri-figma-line:before{content:""}.ri-firefox-browser-fill:before{content:""}.ri-firefox-browser-line:before{content:""}.ri-jewelry-fill:before{content:""}.ri-jewelry-line:before{content:""}.ri-multi-image-fill:before{content:""}.ri-multi-image-line:before{content:""}.ri-no-credit-card-fill:before{content:""}.ri-no-credit-card-line:before{content:""}.ri-service-bell-fill:before{content:""}.ri-service-bell-line:before{content:""}:root,.dropdown,.base-surface{--baseFontFamily:"IBM Plex Sans", system-ui, sans-serif, emoji;--monospaceFontFamily:"IBM Plex Mono", ui-monospace, monospace, emoji;--iconFontFamily:"remixicon";--primaryColor:#25272d;--primaryAlt1Color:color-mix(in srgb, var(--primaryColor), white 8%);--primaryAlt2Color:color-mix(in srgb, var(--primaryColor), white 13%);--primaryTxtColor:#fff;--primaryTxtHintColor:color-mix(in srgb, var(--primaryTxtColor), transparent 35%);--primaryTxtDisabledColor:color-mix(in srgb, var(--primaryTxtColor), transparent 50%);--secondaryColor:#e4e8ec;--secondaryAlt1Color:#dce0e5;--secondaryAlt2Color:#d3d9df;--secondaryTxtColor:var(--primaryColor);--secondaryTxtHintColor:color-mix(in srgb, var(--secondaryTxtColor), transparent 35%);--secondaryTxtDisabledColor:color-mix(in srgb, var(--secondaryTxtColor), transparent 50%);--infoColor:#3376e5;--infoAlt1Color:color-mix(in srgb, var(--infoColor), white 10%);--infoAlt2Color:color-mix(in srgb, var(--infoColor), white 15%);--infoTxtColor:var(--primaryTxtColor);--infoTxtHintColor:var(--primaryTxtHintColor);--infoTxtDisabledColor:var(--primaryTxtDisabledColor);--successColor:#22a96d;--successAlt1Color:color-mix(in srgb, var(--successColor), white 10%);--successAlt2Color:color-mix(in srgb, var(--successColor), white 15%);--successTxtColor:var(--primaryTxtColor);--successTxtHintColor:var(--primaryTxtHintColor);--successTxtDisabledColor:var(--primaryTxtDisabledColor);--warningColor:#e57534;--warningAlt1Color:color-mix(in srgb, var(--warningColor), white 10%);--warningAlt2Color:color-mix(in srgb, var(--warningColor), white 15%);--warningTxtColor:var(--primaryTxtColor);--warningTxtHintColor:var(--primaryTxtHintColor);--warningTxtDisabledColor:var(--primaryTxtDisabledColor);--dangerColor:#c33751;--dangerAlt1Color:color-mix(in srgb, var(--dangerColor), white 10%);--dangerAlt2Color:color-mix(in srgb, var(--dangerColor), white 15%);--dangerTxtColor:var(--primaryTxtColor);--dangerTxtHintColor:var(--primaryTxtHintColor);--dangerTxtDisabledColor:var(--primaryTxtDisabledColor);--accentColor:#1055c9;--accentAlt1Color:color-mix(in srgb, var(--accentColor), white 10%);--accentAlt2Color:color-mix(in srgb, var(--accentColor), white 15%);--accentTxtColor:#fff;--accentTxtHintColor:color-mix(in srgb, var(--accentTxtColor), transparent 40%);--accentTxtDisabledColor:color-mix(in srgb, var(--accentTxtColor), transparent 50%);--surfaceColor:#fff;--surfaceAlt1Color:#f8f9fa;--surfaceAlt2Color:#e4e8ec;--surfaceAlt3Color:#dce0e5;--surfaceAlt4Color:#d3d9df;--surfaceAlt5Color:#ccd4db;--surfaceTxtColor:#25272d;--surfaceTxtHintColor:#687278;--surfaceTxtDisabledColor:#a2a9ae;--surfaceAccentColor:color-mix(in srgb, var(--accentColor), white 80%);--surfaceInfoColor:color-mix(in srgb, var(--infoColor), white 80%);--surfaceSuccessColor:color-mix(in srgb, var(--successColor), white 80%);--surfaceWarningColor:color-mix(in srgb, var(--warningColor), white 80%);--surfaceDangerColor:color-mix(in srgb, var(--dangerColor), white 80%);--selectionColor:#465a7340;--inputColor:var(--surfaceAlt2Color);--inputFocusColor:var(--surfaceAlt3Color);--inputBorderColor:var(--surfaceAlt4Color);scrollbar-color:var(--surfaceAlt4Color) transparent;--prismFunctionColor:#7c00aa;--prismStringColor:#116b00;--prismNumberColor:#246f86;--prismPropertyColor:#246f86;--prismKeywordColor:#a04900;--prismCommentColor:var(--surfaceTxtHintColor);--prismPunctuationColor:var(--surfaceTxtColor);--modalAnimationSpeed:.2s;--modalOverlayColor:#465a7340;--tooltipTxtColor:#fff;--tooltipSurfaceColor:#25272de6;--boxShadow:0px 8px 5px -5px #2224241a;--leftBoxShadow:-1px 0px 5px 0 #2224241a;--rightBoxShadow:1px 0px 5px 0 #2224241a;--topScrollShadow:0px 2px 8px 1px #22242426;--bottomScrollShadow:0px -2px 8px 1px #22242426;--leftScrollShadow:3px 0px 5px 0px #22242433;--rightScrollShadow:-3px 0px 5px 0px #22242433;--fontSize:14px;--smFontSize:13px;--lgFontSize:15px;--lineHeight:22px;--smLineHeight:16px;--lgLineHeight:24px;--btnHeight:45px;--smBtnHeight:35px;--lgBtnHeight:52px;--spacing:30px;--smSpacing:20px;--inputPadding:13px;--inputBorderRadius:var(--borderRadius);--borderRadius:5px;--lgBorderRadius:15px;--pageSidebarWidth:240px;--wrapperWidth:840px;--smWrapperWidth:430px;--lgWrapperWidth:1150px;--loaderIcon:"";--loaderAnimationSpeed:1.1s;--animationSpeed:.15s;--activeAnimationSpeed:70ms;--slideAnimationSpeed:.2s;accent-color:var(--primaryColor)}[data-color-scheme=dark],[data-color-scheme=dark] .dropdown{--surfaceColor:#1c1c1c;--surfaceAlt1Color:color-mix(in srgb, var(--surfaceColor), white 2%);--surfaceAlt2Color:color-mix(in srgb, var(--surfaceColor), white 7%);--surfaceAlt3Color:color-mix(in srgb, var(--surfaceColor), white 12%);--surfaceAlt4Color:color-mix(in srgb, var(--surfaceColor), white 14%);--surfaceAlt5Color:color-mix(in srgb, var(--surfaceColor), white 16%);--surfaceTxtColor:#ebebeb;--tooltipTxtColor:var(--surfaceTxtColor);--surfaceTxtHintColor:color-mix(in srgb, var(--surfaceTxtColor), transparent 45%);--surfaceTxtDisabledColor:color-mix(in srgb, var(--surfaceTxtColor), transparent 65%);--secondaryColor:var(--surfaceAlt2Color);--secondaryTxtColor:var(--surfaceTxtColor);--secondaryAlt1Color:var(--surfaceAlt3Color);--secondaryAlt2Color:var(--surfaceAlt4Color);--primaryColor:#121212;--primaryTxtColor:var(--surfaceTxtColor);--primaryAlt1Color:color-mix(in srgb, var(--primaryColor), black 12%);--primaryAlt2Color:color-mix(in srgb, var(--primaryColor), black 25%);--primaryTxtHintColor:color-mix(in srgb, var(--primaryTxtColor), transparent 35%);--primaryTxtDisabledColor:color-mix(in srgb, var(--primaryTxtColor), transparent 50%);--infoColor:#4273bd;--infoTxtColor:var(--surfaceTxtColor);--infoAlt1Color:color-mix(in srgb, var(--infoColor), black 10%);--infoAlt2Color:color-mix(in srgb, var(--infoColor), black 15%);--surfaceInfoColor:color-mix(in srgb, var(--infoColor), var(--surfaceColor) 45%);--successColor:#27865d;--successTxtColor:var(--surfaceTxtColor);--successAlt1Color:color-mix(in srgb, var(--successColor), black 10%);--successAlt2Color:color-mix(in srgb, var(--successColor), black 15%);--surfaceSuccessColor:color-mix(in srgb, var(--successColor), var(--surfaceColor) 45%);--warningColor:#cf4e17;--warningTxtColor:var(--surfaceTxtColor);--warningAlt1Color:color-mix(in srgb, var(--warningColor), black 10%);--warningAlt2Color:color-mix(in srgb, var(--warningColor), black 15%);--surfaceWarningColor:color-mix(in srgb, var(--warningColor), var(--surfaceColor) 45%);--dangerColor:#bb303e;--dangerTxtColor:var(--surfaceTxtColor);--dangerAlt1Color:color-mix(in srgb, var(--dangerColor), black 10%);--dangerAlt2Color:color-mix(in srgb, var(--dangerColor), black 15%);--surfaceDangerColor:color-mix(in srgb, var(--dangerColor), var(--surfaceColor) 45%);--selectionColor:#ffffff38;--inputColor:var(--surfaceAlt2Color);--inputFocusColor:var(--surfaceAlt3Color);--inputBorderColor:var(--surfaceAlt4Color);scrollbar-color:var(--surfaceAlt5Color) transparent;--modalOverlayColor:#12121280;--tooltipSurfaceColor:#161616e6;--boxShadow:0px 8px 5px -5px #0000004d;--leftBoxShadow:-1px 0px 5px 0 #0000004d;--rightBoxShadow:1px 0px 5px 0 #0000004d;--topScrollShadow:0px 2px 8px 1px #00000073;--bottomScrollShadow:0px -2px 8px 1px #00000073;--leftScrollShadow:3px 0px 5px 0px #0006;--rightScrollShadow:-3px 0px 5px 0px #0006;--prismFunctionColor:#ab7abd;--prismStringColor:#87b47e;--prismNumberColor:#86b9bb;--prismPropertyColor:#90c2d1;--prismKeywordColor:#b3703d;--prismCommentColor:var(--surfaceTxtHintColor);--prismPunctuationColor:var(--surfaceTxtColor)}html .accent-surface{--surfaceColor:var(--accentColor);--surfaceAlt1Color:color-mix(in srgb, var(--surfaceColor), white 5%);--surfaceAlt2Color:color-mix(in srgb, var(--surfaceColor), white 10%);--surfaceAlt3Color:color-mix(in srgb, var(--surfaceColor), white 20%);--surfaceAlt4Color:color-mix(in srgb, var(--surfaceColor), white 30%);--surfaceAlt5Color:color-mix(in srgb, var(--surfaceColor), white 40%);--surfaceTxtColor:#fff;--surfaceTxtHintColor:color-mix(in srgb, var(--surfaceTxtColor), transparent 35%);--surfaceTxtDisabledColor:color-mix(in srgb, var(--surfaceTxtColor), transparent 60%);--surfaceAccentColor:color-mix(in srgb, var(--surfaceColor), white 20%);--surfaceInfoColor:color-mix(in srgb, var(--infoColor), transparent 40%);--surfaceSuccessColor:color-mix(in srgb, var(--successColor), transparent 40%);--surfaceWarningColor:color-mix(in srgb, var(--warningColor), transparent 40%);--surfaceDangerColor:color-mix(in srgb, var(--dangerColor), transparent 40%);--inputColor:var(--surfaceAlt3Color);--inputFocusColor:var(--surfaceAlt4Color);--inputBorderColor:var(--surfaceAlt5Color);--selectionColor:var(--surfaceAccentColor);scrollbar-color:var(--surfaceAlt4Color) transparent}@media (width<=900px){:root,.dropdown,.base-surface{--spacing:20px;--smSpacing:15px;--btnHeight:40px;--smBtnHeight:30px;--lgBtnHeight:47px}}@keyframes rotate{0%{pointer-events:none}to{pointer-events:none;transform:rotate(360deg)}}@keyframes halfRotate{0%{pointer-events:none}to{pointer-events:none;transform:rotate(180deg)}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideTop{0%{opacity:0;transform:translateY(-3px)}to{opacity:1;transform:translateY(0)}}@keyframes scaleIn{0%{opacity:0;transform:scale(.85)}to{opacity:1;transform:scale(1)}}code[class*=language-],pre[class*=language-]{color:var(--surfaceTxtHintColor);font-family:var(--monospaceFontFamily);text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;tab-size:4;-webkit-hyphens:none;hyphens:none;font-size:1em;line-height:1.5}pre[class*=language-]{margin:.5em 0;padding:1em;overflow:auto}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:var(--prismCommentColor)}.token.punctuation{color:var(--prismPunctuationColor)}.token.namespace{opacity:.7}.token.constant,.token.boolean,.token.number{color:var(--prismNumberColor)}.token.deleted,.token.property,.token.symbol,.token.tag,.token.tag .token.punctuation{color:var(--prismPropertyColor)}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string,.token.url{color:var(--prismStringColor)}.token.atrule,.token.attr-value,.token.keyword{color:var(--prismKeywordColor)}.token.class-name,.token.function,.token.important,.token.regex,.token.variable{color:var(--prismFunctionColor)}.token.bold{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{font:inherit;vertical-align:baseline;border:0;margin:0;padding:0}*,:before,:after{box-sizing:border-box}[class^=ri-],[class*=\ ri-]{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:1.15em;font-style:normal;font-weight:400;font-family:var(--iconFontFamily)!important}:is([class^=ri-],[class*=\ ri-]):before{vertical-align:top}:focus-visible{outline:2px dotted var(--selectionColor)}::selection{background:var(--selectionColor)}:root{interpolate-size:allow-keywords}[data-dragover=true]{opacity:.5}html,body{font-optical-sizing:auto;font-size:var(--fontSize);font-family:var(--baseFontFamily);line-height:var(--lineHeight);color:var(--surfaceTxtColor);background:var(--surfaceColor);letter-spacing:.004em;height:100%}h1,h2,h3,h4,h5,h6{font-weight:400;display:block}h1{font-size:26px;line-height:32px}h2{font-size:24px;line-height:30px}h3{font-size:22px;line-height:28px}h4{font-size:20px;line-height:26px}h5{font-size:18px;line-height:24px}h6{font-size:16px;line-height:24px}em{font-style:italic}strong{font-weight:700}small{font-size:var(--smFontSize);line-height:var(--smLineHeight)}sub,sup{font-size:.8em;line-height:1;position:relative}sup{vertical-align:top}sub{vertical-align:bottom}p{margin:10px 0;display:block}p:first-child{margin-top:0}p:last-child{margin-bottom:0}a{color:inherit}a:hover{text-decoration:none}ol,ul{padding-left:var(--spacing);margin:10px 0}:is(ol,ul) li{margin-top:5px;margin-bottom:5px}:is(ol,ul) li:first-child{margin-top:0}:is(ol,ul) li:last-child{margin-bottom:0}ol{list-style:decimal}ul{list-style:outside}cite{font-style:italic}blockquote{quotes:none;color:var(--surfaceTxtHintColor);border-left:3px solid var(--surfaceAlt2Color);margin:10px 0;padding-left:10px;font-style:italic;display:block;position:relative}blockquote:before,blockquote:after{content:none;display:none}blockquote>:first-child{margin-top:0}blockquote>:last-child{margin-bottom:0}pre{white-space:pre-wrap;border-radius:var(--borderRadius)}pre[class*=language-]{background:0 0;margin:0;padding:0;overflow:visible}code,code[class*=language-]{letter-spacing:0;font-size:.93em;line-height:1.5;font-family:var(--monospaceFontFamily);background:var(--surfaceAlt2Color);border-radius:var(--borderRadius);tab-size:4;padding:1px 3px;display:inline-block}pre :is(code,code[class*=language-]),:is(code,code[class*=language-]).block{width:100%;padding:max(10px, calc(var(--inputPadding) - 5px)) max(10px, var(--inputPadding));white-space:pre-wrap;display:block}.code-wrapper{outline:0}.code-wrapper code{scrollbar-width:thin;overflow:auto}.code-wrapper .footnote{color:var(--surfaceTxtHintColor);font-size:var(--smFontSize);line-height:var(--smLineHeight);margin:5px 0 0}.code-wrapper .footnote:empty{display:none}hr{width:100%;height:1px;color:inherit;margin:var(--spacing) 0;background:var(--surfaceAlt2Color);border:0;flex-shrink:0;display:block}hr.sm{margin:var(--smSpacing) 0}.block,.full-width{width:100%}.flex{align-items:center;gap:var(--spacing);display:flex!important}.inline-flex{align-items:center;gap:var(--smSpacing);display:inline-flex!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-fill{flex:auto!important}.wrapper{width:var(--wrapperWidth);max-width:100%;margin:0 auto}.wrapper.sm{width:var(--smWrapperWidth)}.wrapper.lg{width:var(--lgWrapperWidth)}.app>.wrapper{max-width:calc(100% - var(--spacing))}[hidden],.hidden{display:none!important}.slide,[data-slide]{transition:margin var(--slideAnimationSpeed), padding var(--slideAnimationSpeed), height var(--slideAnimationSpeed), opacity var(--slideAnimationSpeed), display var(--slideAnimationSpeed), overflow var(--slideAnimationSpeed) step-end;transition-behavior:allow-discrete}@starting-style{.slide,[data-slide]{opacity:0!important;height:0!important;margin-top:0!important;margin-bottom:0!important;padding-top:0!important;padding-bottom:0!important;overflow:hidden!important}}:is(.slide,[data-slide]).hidden{opacity:0!important;height:0!important;transition:margin var(--slideAnimationSpeed), padding var(--slideAnimationSpeed), height var(--slideAnimationSpeed), opacity var(--slideAnimationSpeed), display var(--slideAnimationSpeed), overflow var(--slideAnimationSpeed) step-start!important;transition-behavior:allow-discrete!important;margin-top:0!important;margin-bottom:0!important;padding-top:0!important;padding-bottom:0!important;overflow:hidden!important}.txt-base{line-height:var(--lineHeight)!important;font-size:var(--fontSize)!important}.txt-sm{line-height:var(--smLineHeight)!important;font-size:var(--smFontSize)!important}.txt-lg{line-height:var(--lgLineHeight)!important;font-size:var(--lgFontSize)!important}.txt-center{text-align:center!important}.txt-left{text-align:left!important}.txt-right{text-align:right!important}.txt-warning{color:var(--warningColor)!important}.txt-success{color:var(--successColor)!important}.txt-danger{color:var(--dangerColor)!important}.txt-info{color:var(--infoColor)!important}.txt-accent{color:var(--accentColor)!important}.txt-primary{color:var(--surfaceTxtColor)!important}.txt-hint{color:var(--surfaceTxtHintColor)!important}.txt-disabled{color:var(--surfaceTxtDisabledColor)!important}.txt-bold{font-weight:700!important}.txt-normal{font-weight:400!important}.txt-strikethrough{text-decoration:line-through!important}.txt-code{letter-spacing:0;font-size:.93em!important;font-family:var(--monospaceFontFamily)!important;white-space:pre-wrap!important;text-align:left!important}.txt-nowrap{white-space:nowrap!important}.txt-ellipsis{vertical-align:top;flex-shrink:1;min-width:10px;max-width:100%;display:inline-block;overflow:hidden;white-space:nowrap!important;text-overflow:ellipsis!important}.faded{opacity:.6;transition:opacity var(--animationSpeed)}.link-faded{opacity:.6;cursor:pointer;transition:all var(--animationSpeed);text-decoration:none}.link-faded:hover,.link-faded:focus-visible,.link-faded[data-popover-state=true],.link-faded:active{opacity:1}.link-primary,.link-hint{--linkColor:var(--surfaceTxtHintColor);--linkFocusColor:var(--surfaceTxtColor);vertical-align:top;cursor:pointer;border-radius:var(--borderRadius);color:var(--linkColor);transition:color var(--animationSpeed), opacity var(--animationSpeed);-webkit-user-select:none;user-select:none;align-items:center;gap:5px;text-decoration:none;display:inline-flex}:is(.link-primary,.link-hint):hover,:is(.link-primary,.link-hint):focus-visible{color:var(--linkFocusColor)}:is(.link-primary,.link-hint)[data-popover-state=true],:is(.link-primary,.link-hint):active{color:var(--linkFocusColor);transition-duration:var(--activeAnimationSpeed)}.link-primary{--linkColor:var(--surfaceTxtColor);--linkFocusColor:var(--surfaceTxtColor)}.link-primary:hover,.link-primary:focus-visible,.link-primary[data-popover-state=true],.link-primary:active{opacity:.9}.gap-base{gap:var(--spacing)!important}.gap-sm{gap:var(--smSpacing)!important}.gap-auto{gap:auto!important}.gap-0{gap:0!important}.gap-5{gap:5px!important}.gap-10{gap:10px!important}.gap-15{gap:15px!important}.gap-20{gap:20px!important}.gap-25{gap:25px!important}.gap-30{gap:30px!important}.m-base{margin:var(--spacing)!important}.m-t-base{margin-top:var(--spacing)!important}.m-r-base{margin-right:var(--spacing)!important}.m-b-base{margin-bottom:var(--spacing)!important}.m-l-base{margin-left:var(--spacing)!important}.m-sm{margin:var(--smSpacing)!important}.m-t-sm{margin-top:var(--smSpacing)!important}.m-r-sm{margin-right:var(--smSpacing)!important}.m-b-sm{margin-bottom:var(--smSpacing)!important}.m-l-sm{margin-left:var(--smSpacing)!important}.m-auto{margin:auto!important}.m-t-auto{margin-top:auto!important}.m-r-auto{margin-right:auto!important}.m-b-auto{margin-bottom:auto!important}.m-l-auto{margin-left:auto!important}.m-0{margin:0!important}.m-t-0{margin-top:0!important}.m-r-0{margin-right:0!important}.m-b-0{margin-bottom:0!important}.m-l-0{margin-left:0!important}.m-5{margin:5px!important}.m-t-5{margin-top:5px!important}.m-r-5{margin-right:5px!important}.m-b-5{margin-bottom:5px!important}.m-l-5{margin-left:5px!important}.m-10{margin:10px!important}.m-t-10{margin-top:10px!important}.m-r-10{margin-right:10px!important}.m-b-10{margin-bottom:10px!important}.m-l-10{margin-left:10px!important}.m-15{margin:15px!important}.m-t-15{margin-top:15px!important}.m-r-15{margin-right:15px!important}.m-b-15{margin-bottom:15px!important}.m-l-15{margin-left:15px!important}.m-20{margin:20px!important}.m-t-20{margin-top:20px!important}.m-r-20{margin-right:20px!important}.m-b-20{margin-bottom:20px!important}.m-l-20{margin-left:20px!important}.m-t-25{margin-top:25px!important}.m-r-25{margin-right:25px!important}.m-b-25{margin-bottom:25px!important}.m-l-25{margin-left:25px!important}.m-t-30{margin-top:30px!important}.m-r-30{margin-right:30px!important}.m-b-30{margin-bottom:30px!important}.m-l-30{margin-left:30px!important}.p-base{padding:var(--spacing)!important}.p-t-base{padding-top:var(--spacing)!important}.p-r-base{padding-right:var(--spacing)!important}.p-b-base{padding-bottom:var(--spacing)!important}.p-l-base{padding-left:var(--spacing)!important}.p-sm{padding:var(--smSpacing)!important}.p-t-sm{padding-top:var(--smSpacing)!important}.p-r-sm{padding-right:var(--smSpacing)!important}.p-b-sm{padding-bottom:var(--smSpacing)!important}.p-l-sm{padding-left:var(--smSpacing)!important}.p-0{padding:0!important}.p-t-0{padding-top:0!important}.p-r-0{padding-right:0!important}.p-b-0{padding-bottom:0!important}.p-l-0{padding-left:0!important}.p-5{padding:5px!important}.p-t-5{padding-top:5px!important}.p-r-5{padding-right:5px!important}.p-b-5{padding-bottom:5px!important}.p-l-5{padding-left:5px!important}.p-10{padding:10px!important}.p-t-10{padding-top:10px!important}.p-r-10{padding-right:10px!important}.p-b-10{padding-bottom:10px!important}.p-l-10{padding-left:10px!important}.p-15{padding:15px!important}.p-t-15{padding-top:15px!important}.p-r-15{padding-right:15px!important}.p-b-15{padding-bottom:15px!important}.p-l-15{padding-left:15px!important}.p-20{padding:20px!important}.p-t-20{padding-top:20px!important}.p-r-20{padding-right:20px!important}.p-b-20{padding-bottom:20px!important}.p-l-20{padding-left:20px!important}.p-t-25{padding-top:25px!important}.p-r-25{padding-right:25px!important}.p-b-25{padding-bottom:25px!important}.p-l-25{padding-left:25px!important}.p-t-30{padding-top:30px!important}.p-r-30{padding-right:30px!important}.p-b-30{padding-bottom:30px!important}.p-l-30{padding-left:30px!important}.loader{--loaderSize:24px;vertical-align:top;text-align:center;color:var(--surfaceAlt5Color);opacity:0;animation:scaleIn var(--animationSpeed) .1s forwards;align-items:center;gap:5px;line-height:1;display:inline-flex}.loader:before{content:var(--loaderIcon);-webkit-user-select:none;user-select:none;text-align:left;color:currentColor;font-weight:400;line-height:var(--loaderSize);font-size:var(--loaderSize);font-family:var(--iconFontFamily);animation:rotate var(--loaderAnimationSpeed) infinite linear;align-content:center;display:block}.loader.sm{--loaderSize:20px;font-size:var(--smFontSize)}.loader.lg{--loaderSize:33px;font-size:var(--lgFontSize)}@keyframes shine{to{background-position-x:-200%}}.skeleton-loader{border-radius:var(--borderRadius);background:var(--surfaceAlt1Color);background:linear-gradient(90deg, var(--surfaceAlt1Color) 10%, var(--surfaceAlt2Color) 25%, var(--surfaceAlt1Color) 60%);width:100%;height:12px;animation:fadeIn var(--animationSpeed), shine 1s linear infinite;background-size:200% 100%;margin:5px 0;display:block;position:relative}.skeleton-loader.sm{height:8px}.skeleton-loader.lg{height:18px}.alert{width:100%;min-height:var(--lgBtnHeight);padding:max(5px, calc(var(--inputPadding) - 5px)) max(10px, var(--inputPadding));border-radius:var(--borderRadius);color:var(--alertTxtColor);background:var(--surfaceAlt2Color);border:2px solid var(--surfaceAlt4Color);flex-shrink:0;align-content:center;display:block}.alert code,.alert .label,.alert hr{background:color-mix(in srgb, currentColor, transparent 90%)}.alert p{margin:5px 0}.alert p:first-child{margin-top:0}.alert p:last-child{margin-bottom:0}.alert.info{border-color:var(--infoColor);background:var(--surfaceInfoColor)}.alert.success{border-color:var(--successColor);background:var(--surfaceSuccessColor)}.alert.warning{border-color:var(--warningColor);background:var(--surfaceWarningColor)}.alert.danger{border-color:var(--dangerColor);background:var(--surfaceDangerColor)}.label{text-align:center;vertical-align:middle;word-break:break-word;width:auto;min-width:0;max-width:100%;min-height:25px;font-weight:400;font-size:var(--smFontSize);line-height:calc(var(--smFontSize) + 2px);border-radius:var(--borderRadius);color:var(--surfaceTxtColor);background:var(--surfaceAlt3Color);border:0px solid var(--surfaceAlt5Color);flex-shrink:0;justify-content:center;align-items:center;gap:5px;padding:5px 7px;text-decoration:none;display:inline-flex}.label .label{border-width:1px;border-color:var(--surfaceAlt5Color)}.label.sm{min-height:20px;font-size:calc(var(--smFontSize) - 2px);padding:3px 5px}.label.info{background:var(--surfaceInfoColor)}.label.info .label{border-color:var(--infoColor)}.label.success{background:var(--surfaceSuccessColor)}.label.success .label{border-color:var(--successColor)}.label.warning{background:var(--surfaceWarningColor)}.label.warning .label{border-color:var(--warningColor)}.label.danger{background:var(--surfaceDangerColor)}.label.danger .label{border-color:var(--dangerColor)}.label.handle{cursor:pointer;-webkit-user-select:none;user-select:none;transition:opacity var(--animationSpeed);outline:0}.label.handle:hover,.label.handle:focus-visible{opacity:.9}.label.handle:active{opacity:.8;transition-duration:var(--activeAnimationSpeed)}.breadcrumbs{min-width:0;max-width:calc(100% - 50px);color:var(--surfaceTxtHintColor);align-items:center;gap:30px;font-size:1.286rem;font-weight:400;display:inline-flex}.breadcrumbs>div,.breadcrumbs>span,.breadcrumbs>a,.breadcrumbs>button{position:relative}:is(.breadcrumbs>div,.breadcrumbs>span,.breadcrumbs>a,.breadcrumbs>button):after{content:"/";vertical-align:top;cursor:default;-webkit-user-select:none;user-select:none;pointer-events:none;height:100%;color:var(--surfaceTxtDisabledColor);align-content:center;font-size:.85em;line-height:1;display:inline-block;position:absolute;top:0;right:-18px}:is(.breadcrumbs>div,.breadcrumbs>span,.breadcrumbs>a,.breadcrumbs>button):last-child{color:var(--surfaceTxtColor);white-space:nowrap;text-overflow:ellipsis;flex-shrink:1;min-width:0;max-width:400px;position:relative;overflow:hidden}:is(.breadcrumbs>div,.breadcrumbs>span,.breadcrumbs>a,.breadcrumbs>button):last-child:after{content:none;display:none}@media (width<=800px){.breadcrumbs>div,.breadcrumbs>span,.breadcrumbs>a,.breadcrumbs>button{display:none}:is(.breadcrumbs>div,.breadcrumbs>span,.breadcrumbs>a,.breadcrumbs>button):last-child{display:block}}.breadcrumbs a{cursor:pointer;color:var(--surfaceTxtHintColor);transition:color var(--animationSpeed);outline:0;text-decoration:none}.breadcrumbs a:hover,.breadcrumbs a:focus-visible{color:var(--surfaceTxtColor)}.copy-to-clipboard{cursor:pointer;-webkit-user-select:none;user-select:none;vertical-align:middle;color:var(--surfaceTxtHintColor);transition:color var(--animationSpeed);outline:0;align-items:center;gap:5px;line-height:1;text-decoration:none;display:inline-flex}.copy-to-clipboard .copy-icon{font-size:var(--smFontSize)}.copy-to-clipboard:hover,.copy-to-clipboard:active{color:var(--surfaceTxtColor)}.copy-to-clipboard.active{color:var(--successColor)}.label .copy-to-clipboard{align-self:stretch;margin:-5px;padding:5px}.thumb{--thumbSize:var(--btnHeight);width:var(--thumbSize);aspect-ratio:1;background:var(--surfaceAlt1Color);border-radius:var(--borderRadius);text-align:center;color:var(--surfaceTxtHintColor);font-size:var(--fontSize);line-height:var(--lineHeight);transition:border var(--animationSpeed), opacity var(--animationSpeed);border:1px solid var(--surfaceAlt3Color);outline:0;flex-shrink:0;justify-content:center;align-items:center;text-decoration:none;display:inline-flex;overflow:hidden}.thumb img{width:100%;max-width:100%;height:auto;transition:opacity var(--animationSpeed)}.thumb.loading{background:linear-gradient(90deg, var(--surfaceAlt1Color) 0%, var(--surfaceColor) 25%, var(--surfaceAlt1Color) 50%);background-size:200% 100%;animation:.85s linear .2s infinite shine}.thumb.loading img{opacity:0}.thumb.lg{--thumbSize:80px;font-size:var(--lgFontSize)}.thumb.sm{--thumbSize:var(--smBtnHeight);font-size:var(--smFontSize);line-height:var(--smLineHeight)}.thumb.info{border:1px solid var(--infoColor)}.thumb.success{border:1px solid var(--successColor)}.thumb.warning{border:1px solid var(--warningColor)}.thumb.danger{border:1px solid var(--dangerColor)}.hanlde.thumb,button.thumb,a.thumb{cursor:pointer}:is(.hanlde.thumb,button.thumb,a.thumb):hover,:is(.hanlde.thumb,button.thumb,a.thumb):active,:is(.hanlde.thumb,button.thumb,a.thumb):focus-visible{opacity:.8}:is(.hanlde.thumb,button.thumb,a.thumb):active{opacity:.6;transition-duration:var(--activeAnimationSpeed)}.animate-fadeIn{animation:fadeIn var(--animationSpeed)}.animate-delayed-fadeIn{opacity:0;animation:fadeIn var(--animationSpeed) var(--animationSpeed) forwards}.formatted-date .missing-value,.formatted-date .primary-date,.formatted-date .secondary-date{width:100%;display:block}.formatted-date .secondary-date{color:var(--surfaceTxtHintColor);font-size:var(--smFontSize);line-height:var(--smLineHeight);margin-top:3px}.formatted-date .missing-value{text-align:left}.formatted-date.short{text-align:center;white-space:nowrap}.formatted-date.short .secondary-date{margin-top:0;font-size:.87em}.section-heading{color:var(--surfaceTxtHintColor);margin:0 0 var(--smSpacing);align-items:center;gap:10px;display:flex}.section-heading .field{width:auto}.main-logo{max-height:40px}.dragline{z-index:9;cursor:ew-resize;box-sizing:content-box;-webkit-user-select:none;user-select:none;width:2px;height:100%;transition:background var(--animationSpeed);background:0 0;flex-shrink:0;margin:0;padding:0;position:relative}.dragline:hover,.dragline:active,.dragline.dragging{z-index:101;background:var(--surfaceAlt3Color)}.pb-tooltip{z-index:99999;text-align:center;white-space:pre-line;word-break:break-word;background:var(--tooltipSurfaceColor);border-radius:var(--borderRadius);min-width:30px;max-width:300px;max-height:90%;color:var(--tooltipTxtColor);font-weight:400;font-size:var(--smFontSize);line-height:var(--smLineHeight);font-family:var(--baseFontFamily);scrollbar-width:thin;pointer-events:none;opacity:0;transition:opacity var(--animationSpeed), display var(--animationSpeed) allow-discrete;padding:3px 5px;position:fixed}.pb-tooltip:popover-open{opacity:1;display:block}@starting-style{.pb-tooltip:popover-open{opacity:0}}.pb-tooltip[data-style=code]{text-align:left;white-space:pre-wrap;max-width:350px;font-family:var(--monospaceFontFamily)}@keyframes toastEntrance{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes toastContentEntrance{0%{overflow:hidden}}.toast{--toastWidth:420px;--toastSurfaceColor:var(--surfaceInfoColor);--toastSurfaceTxtColor:var(--surfaceTxtColor);--toastAccentColor:var(--infoColor);width:var(--toastWidth);max-width:95%;margin:0 0 var(--smSpacing);animation:toastEntrance var(--animationSpeed);grid-template-rows:1fr;display:grid;position:sticky;top:0}.toast .toast-container{border-radius:var(--borderRadius);width:100%;line-height:var(--lineHeight);color:var(--toastSurfaceTxtColor);background:var(--toastSurfaceColor);box-shadow:var(--boxShadow);animation:toastContentEntrance var(--animationSpeed);align-items:stretch;display:flex}.toast .toast-content{text-align:left;word-break:break-word;width:100%;min-height:var(--lgBtnHeight);padding:max(5px, calc(var(--inputPadding) - 5px)) var(--inputPadding);align-items:center;gap:10px;display:flex}.toast .toast-icon{min-height:0;color:var(--toastAccentColor);border-top-left-radius:var(--borderRadius);border-bottom-left-radius:var(--borderRadius);border-right:1px solid color-mix(in srgb, var(--toastAccentColor), transparent 90%);align-content:center;margin-left:-1px;padding:5px 10px;font-size:1.2em}[data-color-scheme=dark] :is(.toast .toast-icon){border-color:color-mix(in srgb, var(--toastAccentColor), transparent 75%)}.toast .toast-icon:before{content:"";font-family:var(--iconFontFamily)}.toast .toast-remove{margin:-5px -10px -5px 0}.toast.success{--toastSurfaceColor:var(--surfaceSuccessColor);--toastAccentColor:var(--successColor)}.toast.success .toast-icon:before{content:""}.toast.error{--toastSurfaceColor:var(--surfaceDangerColor);--toastAccentColor:var(--dangerColor)}.toast.error .toast-icon:before{content:""}.toast.removing{transition:opacity var(--animationSpeed), margin var(--animationSpeed), grid-template-rows var(--animationSpeed);opacity:0;grid-template-rows:0fr;margin:0}.toast.removing .toast-container{overflow:hidden}.toasts-container{z-index:9999;bottom:var(--spacing);width:100%;display:block;position:fixed;left:0;pointer-events:none!important}.toasts-container .toast{pointer-events:auto;margin-left:auto;margin-right:auto}.list{--borderColor:var(--surfaceAlt3Color);width:100%;color:var(--surfaceTxtColor);background:var(--surfaceColor);border:1px solid var(--borderColor);border-radius:var(--borderRadius);scrollbar-width:thin;display:block;position:relative;overflow:auto}.list:empty{display:none}.list .list-content{scrollbar-width:thin;width:100%;max-height:425px;display:block;overflow:auto}.list .list-item{word-break:break-word;width:100%;padding:10px var(--inputPadding);min-height:54px;box-shadow:0px -1px 0 0 var(--borderColor);transition:background var(--animationSpeed);outline:0;align-items:center;gap:10px;display:flex;position:relative}.list .list-item .content{-webkit-user-select:text;user-select:text;align-items:center;gap:5px;width:100%;min-width:0;max-width:100%;line-height:1.5;display:flex}.list .list-item .actions{flex-shrink:0;align-items:center;gap:10px;margin:-1px -5px -1px 0;display:inline-flex}.list .list-item .actions.autohide{opacity:0;transition:transform var(--animationSpeed), opacity var(--animationSpeed), visibility var(--animationSpeed);transform:translate(5px)}@media only screen and (hover:none){.list .list-item .actions.autohide{opacity:1;transform:translate(0)}}.list .list-item>.btn.block{border-radius:0;width:100%}.list .list-item>.btn.block.sm{border-radius:var(--borderRadius)}.list .list-item:has(>.btn.block){min-height:0;padding:0}.list .list-item:has(>.btn.sm.block){padding:5px}:is(.list .list-item:hover,.list .list-item:focus-visible,.list .list-item:focus-within,.list .list-item:active) .actions.autohide{opacity:1;transform:translate(0)}.list .list-item[data-dragstart=true],.list .list-item.active{background:var(--surfaceAlt1Color)}.list .list-item[data-dragstart=true] .actions.autohide{opacity:0}:is(.list .list-item:not(.disabled).highlight,.list .list-item:not(.disabled).handle):hover,:is(.list .list-item:not(.disabled).highlight,.list .list-item:not(.disabled).handle):focus-visible{background:var(--surfaceAlt1Color)}:is(.list .list-item:not(.disabled).highlight,.list .list-item:not(.disabled).handle):active{background:var(--surfaceAlt2Color);transition-duration:var(--activeAnimationSpeed)}.list .list-item.handle{cursor:pointer;-webkit-user-select:none;user-select:none}.list .list-item.deleted{cursor:default}.list .list-item.deleted .content{opacity:.6}.list .list-item.deleted .content .txt{text-decoration:line-through}.list .list-item.disabled:not(.active){cursor:default;opacity:.6}.list.sm .list-item{min-height:var(--btnHeight);padding:5px 10px}.grid{--gridGap:var(--spacing);row-gap:var(--gridGap);margin:0 calc(-.5 * var(--gridGap));flex-wrap:wrap;flex-grow:1;display:flex;position:relative;container-type:inline-size}.grid.center{align-items:center}.grid.sm{--gridGap:var(--smSpacing)}.grid>[class^=col-]{width:100%;min-width:0;min-height:1px;margin:0 calc(.5 * var(--gridGap));position:relative}.grid>[class^=col-]>hr:first-child{margin-top:0}.grid>[class^=col-]>hr:last-child{margin-bottom:0}.grid .col-12{width:calc(100% - var(--gridGap))}.grid .col-11{width:calc(91.6667% - var(--gridGap))}.grid .col-10{width:calc(83.3333% - var(--gridGap))}.grid .col-9{width:calc(75% - var(--gridGap))}.grid .col-8{width:calc(66.6667% - var(--gridGap))}.grid .col-7{width:calc(58.3333% - var(--gridGap))}.grid .col-6{width:calc(50% - var(--gridGap))}.grid .col-5{width:calc(41.6667% - var(--gridGap))}.grid .col-4{width:calc(33.3333% - var(--gridGap))}.grid .col-3{width:calc(25% - var(--gridGap))}.grid .col-2{width:calc(16.6667% - var(--gridGap))}.grid .col-1{width:calc(8.33333% - var(--gridGap))}@container (width>=380px){.grid .col-sm-12{width:calc(100% - var(--gridGap))}.grid .col-sm-11{width:calc(91.6667% - var(--gridGap))}.grid .col-sm-10{width:calc(83.3333% - var(--gridGap))}.grid .col-sm-9{width:calc(75% - var(--gridGap))}.grid .col-sm-8{width:calc(66.6667% - var(--gridGap))}.grid .col-sm-7{width:calc(58.3333% - var(--gridGap))}.grid .col-sm-6{width:calc(50% - var(--gridGap))}.grid .col-sm-5{width:calc(41.6667% - var(--gridGap))}.grid .col-sm-4{width:calc(33.3333% - var(--gridGap))}.grid .col-sm-3{width:calc(25% - var(--gridGap))}.grid .col-sm-2{width:calc(16.6667% - var(--gridGap))}.grid .col-sm-1{width:calc(8.33333% - var(--gridGap))}}@container (width>=550px){.grid .col-md-12{width:calc(100% - var(--gridGap))}.grid .col-md-11{width:calc(91.6667% - var(--gridGap))}.grid .col-md-10{width:calc(83.3333% - var(--gridGap))}.grid .col-md-9{width:calc(75% - var(--gridGap))}.grid .col-md-8{width:calc(66.6667% - var(--gridGap))}.grid .col-md-7{width:calc(58.3333% - var(--gridGap))}.grid .col-md-6{width:calc(50% - var(--gridGap))}.grid .col-md-5{width:calc(41.6667% - var(--gridGap))}.grid .col-md-4{width:calc(33.3333% - var(--gridGap))}.grid .col-md-3{width:calc(25% - var(--gridGap))}.grid .col-md-2{width:calc(16.6667% - var(--gridGap))}.grid .col-md-1{width:calc(8.33333% - var(--gridGap))}}@container (width>=650px){.grid .col-lg-12{width:calc(100% - var(--gridGap))}.grid .col-lg-11{width:calc(91.6667% - var(--gridGap))}.grid .col-lg-10{width:calc(83.3333% - var(--gridGap))}.grid .col-lg-9{width:calc(75% - var(--gridGap))}.grid .col-lg-8{width:calc(66.6667% - var(--gridGap))}.grid .col-lg-7{width:calc(58.3333% - var(--gridGap))}.grid .col-lg-6{width:calc(50% - var(--gridGap))}.grid .col-lg-5{width:calc(41.6667% - var(--gridGap))}.grid .col-lg-4{width:calc(33.3333% - var(--gridGap))}.grid .col-lg-3{width:calc(25% - var(--gridGap))}.grid .col-lg-2{width:calc(16.6667% - var(--gridGap))}.grid .col-lg-1{width:calc(8.33333% - var(--gridGap))}}table{--tableSpacing:var(--inputPadding);border-collapse:separate;border-spacing:0;width:100%}table td,table th{padding:10px max(var(--tableSpacing), 10px);vertical-align:middle;text-align:left;height:var(--btnHeight);background:var(--surfaceColor);border:1px solid var(--surfaceAlt2Color);border-bottom-width:0}:is(table td,table th):not(:first-child){border-left:0}:is(table td,table th):not(:last-child){border-right:0}@media (width<=600px){table td,table th{padding:5px}}table>:first-child>tr:first-child>:first-child{border-top-left-radius:var(--borderRadius)}table>:first-child>tr:first-child>:last-child{border-top-right-radius:var(--borderRadius)}table>:last-child>tr:last-child>:first-child{border-bottom-left-radius:var(--borderRadius)}table>:last-child>tr:last-child>:last-child{border-bottom-right-radius:var(--borderRadius)}table>:last-child>tr:last-child>td,table>:last-child>tr:last-child>th{border-width:1px}table th{color:var(--surfaceTxtHintColor);font-size:.98em;font-weight:700;line-height:1.4}table th.sort-handle{cursor:pointer;-webkit-user-select:none;user-select:none;outline:0;padding-right:40px;position:relative}:is(table th.sort-handle.asc,table th.sort-handle.desc):before{content:"";right:var(--tableSpacing);color:inherit;opacity:.5;font-weight:400;font-family:var(--iconFontFamily);transition:opacity var(--animationSpeed);display:block;position:absolute;top:50%;transform:translateY(-50%)}table th.sort-handle.desc:before{content:""}table th.sort-handle:hover,table th.sort-handle:focus-visible{background:var(--surfaceAlt1Color)}:is(table th.sort-handle:hover,table th.sort-handle:focus-visible):before{opacity:1}table th.sort-handle:active{background:var(--surfaceAlt2Color)}:is(table td,table th).min-width{white-space:nowrap;width:1%!important;min-width:0!important}:is(table td,table th).col-bulk-select,:is(table td,table th).col-meta{z-index:2;word-break:normal;white-space:nowrap;position:sticky}:is(table td,table th).col-bulk-select{width:1%;min-width:62px;padding-right:5px;left:0}:is(table td,table th).col-bulk-select .field{width:auto}:is(table td,table th).col-bulk-select .loader{margin-left:-2px;position:absolute;top:10px}:is(table td,table th).col-bulk-select:after{content:"";opacity:0;pointer-events:none;width:1px;height:100%;box-shadow:var(--leftScrollShadow);display:block;position:absolute;top:0;right:0}@container scroll-state(scrollable:left){:is(table td,table th).col-bulk-select:after{opacity:1;transition:opacity var(--animationSpeed)}}@media (width<=600px){:is(table td,table th).col-bulk-select{min-width:50px;padding-right:0}}:is(table td,table th).col-meta{text-align:right;width:1%;padding-top:4px;padding-bottom:5px;padding-left:10px;right:0}:is(table td,table th).col-meta:before{content:"";opacity:0;pointer-events:none;width:1px;height:100%;box-shadow:var(--rightScrollShadow);display:block;position:absolute;top:0;left:0}@container scroll-state(scrollable:right){:is(table td,table th).col-meta:before{opacity:1;transition:opacity var(--animationSpeed)}}:is(table td,table th).col-meta>i{vertical-align:top;color:var(--surfaceTxtDisabledColor);transition:color var(--animationSpeed), transform var(--animationSpeed);will-change:transform, color;display:inline-block}@media (width<=600px){:is(table td,table th).col-meta{padding-left:5px}}:is(table td,table th).col-field-type-date,:is(table td,table th).col-field-type-autodate,:is(table td,table th).col-field-type-geopoint{white-space:nowrap;width:1%}:is(table td,table th).col-field-type-relation{min-width:190px;max-width:500px}:is(table td,table th).col-field-type-text{max-width:300px}:is(table td,table th).col-field-type-editor{min-width:400px}:is(table td,table th).col-field-type-select{min-width:180px}:is(table td,table th).col-field-type-url{max-width:300px}:is(table td,table th).col-field-type-email{white-space:nowrap;min-width:120px}:is(table td,table th).col-field-type-number{white-space:nowrap}:is(table td,table th).col-field-type-file{min-width:120px}:is(table td,table th).col-field-type-json{max-width:300px}:is(table td,table th).col-field-name-id{white-space:nowrap;width:190px}table .col-copy{padding-left:0}table .col-copy .copy-to-clipboard{opacity:0;transition:color var(--animationSpeed), opacity var(--animationSpeed), transform var(--animationSpeed);transform:translate(3px)}table tr:hover .col-copy .copy-to-clipboard{opacity:1;transform:translate(0)}table thead th{background:var(--surfaceAlt1Color)}table thead.sticky{z-index:3;position:sticky;top:0}table thead.sticky:after{content:"";z-index:-1;opacity:0;pointer-events:none;width:100%;height:1px;box-shadow:var(--topScrollShadow);display:block;position:absolute;bottom:0;left:0}@container scroll-state(scrollable:top){table thead.sticky:after{opacity:1;transition:opacity var(--animationSpeed)}}table tr.handle{cursor:pointer;outline:0}table tr.handle td,table tr.handle th{transition:background var(--animationSpeed);will-change:background}:is(table tr.handle:hover,table tr.handle:focus-within) td,:is(table tr.handle:hover,table tr.handle:focus-within) th{background:var(--surfaceAlt1Color)}:is(table tr.handle:hover,table tr.handle:focus-within) .col-meta>i{color:var(--surfaceTxtColor);transform:translate(3px)}table tr.handle.active td,table tr.handle.active th{background:var(--surfaceAlt2Color)}table.optimize td,table.optimize th,table.optimize .col-bulk-select label:before,table.optimize .col-bulk-select label:after,table.optimize .col-meta i{transition:none!important}table.optimize .col-meta i{transform:none!important}.page-table-wrapper{width:auto;min-height:130px;margin-left:calc(-1 * var(--spacing));margin-right:calc(-1 * var(--spacing));container-type:inline-size scroll-state;display:block;overflow:auto}.page-table-wrapper .label{word-break:normal}.page-table-wrapper .load-more-btn,.page-table-wrapper .sticky-content{z-index:3;width:100%;left:var(--spacing);right:var(--spacing);max-width:calc(100cqw - (2 * var(--spacing)));position:sticky}.page-table-wrapper table{border-radius:0;min-width:900px}.page-table-wrapper table>:first-child>tr:first-child>:first-child{border-top-left-radius:0}.page-table-wrapper table>:first-child>tr:first-child>:last-child{border-top-right-radius:0}.page-table-wrapper table>:last-child>tr:last-child>:first-child{border-bottom-left-radius:0}.page-table-wrapper table>:last-child>tr:last-child>:last-child{border-bottom-right-radius:0}.page-table-wrapper td,.page-table-wrapper th{border:0;border-bottom:1px solid var(--surfaceAlt2Color);border-radius:0}:is(.page-table-wrapper td,.page-table-wrapper th):first-child{padding-left:var(--spacing)}:is(.page-table-wrapper td,.page-table-wrapper th):last-child{padding-right:var(--spacing)}.page-table-wrapper th{background:var(--surfaceColor)}.page-table-wrapper th.sort-handle{border-radius:var(--borderRadius) var(--borderRadius) 0 0}.page-table-wrapper tbody td,.page-table-wrapper tbody th{border-radius:0;height:59px}.page-table-wrapper:before,.page-table-wrapper:after{content:"";z-index:9;opacity:0;pointer-events:none;width:100%;height:1px;display:block;position:sticky;left:0}.page-table-wrapper:before{box-shadow:var(--topScrollShadow);top:0}@container scroll-state(scrollable:top){.page-table-wrapper:before{opacity:1;transition:opacity var(--animationSpeed)}}.page-table-wrapper:after{box-shadow:var(--bottomScrollShadow);margin-top:-1px;bottom:0}@container scroll-state(scrollable:bottom){.page-table-wrapper:after{opacity:1;transition:opacity var(--animationSpeed)}}.page-table-wrapper:has(thead.sticky):before{content:none;display:none}@media (width<=600px){table.responsive-table{border-collapse:collapse;table-layout:fixed;min-width:0}table.responsive-table tr{border:1px solid var(--surfaceAlt2Color);flex-flow:wrap;gap:5px;width:100%;padding:10px;display:flex}table.responsive-table tr~tr{border-top:0}table.responsive-table .col-copy{display:none}table.responsive-table td,table.responsive-table th{word-break:break-word;margin:0;display:block;white-space:normal!important;background:0 0!important;border:0!important;width:100%!important;min-width:0!important;max-width:none!important;height:auto!important;min-height:0!important;padding:0!important}:is(table.responsive-table td,table.responsive-table th):before{content:attr(data-name);width:100%;color:var(--surfaceTxtHintColor);font-weight:700;font-size:var(--smFontSize);line-height:var(--lineHeight);display:block}:is(table.responsive-table td,table.responsive-table th).col-bulk-select{align-content:center;margin-top:0;padding:0}:is(table.responsive-table td,table.responsive-table th).col-meta{display:none}:is(:is(table.responsive-table td,table.responsive-table th).col-bulk-select,:is(table.responsive-table td,table.responsive-table th).col-meta):before,:is(:is(table.responsive-table td,table.responsive-table th).col-bulk-select,:is(table.responsive-table td,table.responsive-table th).col-meta):after{display:none}:is(table.responsive-table td,table.responsive-table th) .formatted-date.short{align-items:center;gap:5px;display:inline-flex}:is(table.responsive-table td,table.responsive-table th) .formatted-date.short .secondary-date,:is(table.responsive-table td,table.responsive-table th) .formatted-date.short .primary-date{width:auto;margin:0}:is(table.responsive-table td,table.responsive-table th) .record-field-view{text-align:left}table.responsive-table td.col-bulk-select{width:auto!important}table.responsive-table td.col-field-name-id{flex-grow:1;width:auto!important}table.responsive-table td.col-field-name-id:before{display:none}table.responsive-table td.col-field-name-id .label{width:100%;font-weight:700}table.responsive-table thead tr{background:var(--surfaceColor);border:0;flex-direction:row;padding-top:0}table.responsive-table thead th{display:none}table.responsive-table thead th.col-meta,table.responsive-table thead th.col-bulk-select{margin:0;display:inline-block;width:auto!important}table.responsive-table thead th.col-meta{margin-left:auto;padding:0}table.responsive-table .label{word-break:break-word}.page-table-wrapper .responsive-table{border:0}.page-table-wrapper .responsive-table tr{padding-left:var(--spacing);padding-right:var(--spacing);border-left:0;border-right:0}}button{color:inherit;text-align:left;font-family:inherit;font-size:inherit;font-weight:inherit;line-height:inherit;letter-spacing:inherit;background:0 0;border:0;outline:0;padding:0}.btn{--btnGap:8px;cursor:pointer;justify-content:center;align-items:center;gap:var(--btnGap);-webkit-user-select:none;user-select:none;min-height:var(--btnHeight);text-align:center;min-width:0;max-width:100%;color:var(--primaryTxtColor);font-weight:700;line-height:1;font-size:var(--fontSize);font-family:var(--baseFontFamily);border-radius:var(--borderRadius);background:var(--primaryColor);transition:color var(--animationSpeed), border-color var(--animationSpeed), background var(--animationSpeed);border:0;outline:0;flex-shrink:0;margin:0;padding:5px 25px;text-decoration:none;display:inline-flex;position:relative}.btn:hover,.btn:focus-visible{background:var(--primaryAlt1Color)}.btn[data-popover-state=true],.btn:active{background:var(--primaryAlt2Color);transition-duration:var(--activeAnimationSpeed)}.btn i{font-size:1.25em}.btn.secondary{color:var(--secondaryTxtColor);background:var(--secondaryColor)}.btn.secondary:hover,.btn.secondary:focus-visible{background:var(--secondaryAlt1Color)}.btn.secondary[data-popover-state=true],.btn.secondary:active{background:var(--secondaryAlt2Color)}.btn.info{color:var(--infoTxtColor);background:var(--infoColor)}.btn.info:hover,.btn.info:focus-visible{background:var(--infoAlt1Color)}.btn.info[data-popover-state=true],.btn.info:active{background:var(--infoAlt2Color)}.btn.success{color:var(--successTxtColor);background:var(--successColor)}.btn.success:hover,.btn.success:focus-visible{background:var(--successAlt1Color)}.btn.success[data-popover-state=true],.btn.success:active{background:var(--successAlt2Color)}.btn.warning{color:var(--warningTxtColor);background:var(--warningColor)}.btn.warning:hover,.btn.warning:focus-visible{background:var(--warningAlt1Color)}.btn.warning[data-popover-state=true],.btn.warning:active{background:var(--warningAlt2Color)}.btn.danger{color:var(--dangerTxtColor);background:var(--dangerColor)}.btn.danger:hover,.btn.danger:focus-visible{background:var(--dangerAlt1Color)}.btn.danger[data-popover-state=true],.btn.danger:active{background:var(--dangerAlt2Color)}.btn.outline{border:2px solid}.btn.outline,.btn.transparent{color:var(--surfaceTxtColor);background:var(--surfaceColor)}[data-color-scheme=dark] :is(.btn.outline,.btn.transparent){border-color:var(--surfaceAlt3Color)}[data-color-scheme=dark] :is(.btn.outline,.btn.transparent):hover,[data-color-scheme=dark] :is(.btn.outline,.btn.transparent):focus-visible{background:var(--surfaceAlt4Color)}[data-color-scheme=dark] :is(.btn.outline,.btn.transparent)[data-popover-state=true],[data-color-scheme=dark] :is(.btn.outline,.btn.transparent):active{background:var(--surfaceAlt5Color)}:is(.btn.outline,.btn.transparent):hover,:is(.btn.outline,.btn.transparent):focus-visible{background:var(--surfaceAlt1Color)}:is(.btn.outline,.btn.transparent)[data-popover-state=true],:is(.btn.outline,.btn.transparent):active{background:var(--surfaceAlt2Color)}:is(.btn.outline,.btn.transparent).secondary{color:var(--surfaceTxtHintColor)}:is(.btn.outline,.btn.transparent).info{color:var(--infoColor)}:is(.btn.outline,.btn.transparent).success{color:var(--successColor)}:is(.btn.outline,.btn.transparent).warning{color:var(--warningColor)}:is(.btn.outline,.btn.transparent).danger{color:var(--dangerColor)}:is(:is(.btn.outline,.btn.transparent).secondary,:is(.btn.outline,.btn.transparent).info,:is(.btn.outline,.btn.transparent).success,:is(.btn.outline,.btn.transparent).warning,:is(.btn.outline,.btn.transparent).danger):hover,:is(:is(.btn.outline,.btn.transparent).secondary,:is(.btn.outline,.btn.transparent).info,:is(.btn.outline,.btn.transparent).success,:is(.btn.outline,.btn.transparent).warning,:is(.btn.outline,.btn.transparent).danger):focus-visible{background:color-mix(in srgb, currentColor, transparent 92%)}:is(:is(.btn.outline,.btn.transparent).secondary,:is(.btn.outline,.btn.transparent).info,:is(.btn.outline,.btn.transparent).success,:is(.btn.outline,.btn.transparent).warning,:is(.btn.outline,.btn.transparent).danger)[data-popover-state=true],:is(:is(.btn.outline,.btn.transparent).secondary,:is(.btn.outline,.btn.transparent).info,:is(.btn.outline,.btn.transparent).success,:is(.btn.outline,.btn.transparent).warning,:is(.btn.outline,.btn.transparent).danger):active{background:color-mix(in srgb, currentColor, transparent 85%)}.btn.transparent{background:0 0}.btn.transparent:hover,.btn.transparent:focus-visible{background:var(--surfaceAlt2Color)}.btn.transparent[data-popover-state=true],.btn.transparent:active{background:var(--surfaceAlt4Color)}.btn.pill{border-radius:30px}.btn.expanded{min-width:130px}.btn.expanded-sm{min-width:100px}.btn.expanded-lg{min-width:160px}.btn.sm{--btnGap:5px;min-height:var(--smBtnHeight);font-size:var(--smFontSize);line-height:var(--smLineHeight);padding-left:12px;padding-right:12px}.btn.sm i{font-size:1.15em}.btn.sm.expanded{min-width:110px}.btn.sm.expanded-sm{min-width:85px}.btn.sm.expanded-lg{min-width:130px}.btn.lg{min-height:var(--lgBtnHeight);font-size:var(--lgFontSize)}.btn.lg i{font-size:1.4em}.btn.lg.expanded{min-width:150px}.btn.lg.expanded-sm{min-width:120px}.btn.lg.expanded-lg{min-width:190px}.btn.circle{--circleSize:var(--btnHeight);min-height:0;width:var(--circleSize);height:var(--circleSize);text-align:center;border-radius:50%;flex-shrink:0;align-content:center;padding:0!important}.btn.circle i{vertical-align:top;display:inline-block}.btn.circle i:before{vertical-align:top;line-height:26px;display:inline-block}.btn.circle.sm{--circleSize:var(--smBtnHeight)}.btn.circle.lg{--circleSize:var(--lgBtnHeight)}.btn.next i{will-change:transform;transition:transform var(--animationSpeed)}:is(.btn.next:hover,.btn.next:active,.btn.next:focus-visible) i{transform:translate(3px)}:is(.btn[data-rotate=true],.btn.rotate) i{animation:.3s halfRotate}.btn[data-loading=true],.btn.loading{cursor:default}:is(.btn[data-loading=true],.btn.loading):after{--size:24px;content:var(--loaderIcon);width:var(--size);height:var(--size);line-height:var(--size);margin-top:calc(var(--size) / -2);margin-left:calc(var(--size) / -2);color:inherit;text-align:center;font-size:1.5em;font-weight:400;font-family:var(--iconFontFamily);will-change:transform;animation:fadeIn var(--animationSpeed), rotate var(--loaderAnimationSpeed) infinite linear;flex-shrink:0;padding:0;display:block;position:absolute;top:50%;left:50%}:is(.btn[data-loading=true],.btn.loading)>*{opacity:0}.btn.disabled,.btn[disabled]{cursor:default;color:var(--surfaceTxtDisabledColor)!important;background:var(--surfaceAlt2Color)!important}:is(.btn.disabled,.btn[disabled]).outline,:is(.btn.disabled,.btn[disabled]).transparent{color:var(--surfaceTxtDisabledColor);background:0 0!important}:is(.btn.disabled,.btn[disabled]).outline{border-color:var(--surfaceAlt2Color)}.btns{align-items:stretch;min-width:0;display:inline-flex}.btns>.btn~.btn{border-left:1px solid var(--primaryAlt1Color);border-top-left-radius:0;border-bottom-left-radius:0}.btns>.btn~.btn.outline{border-left:0}.btns>.btn~.btn.secondary{border-left-color:var(--secondaryAlt1Color)}.btns>.btn~.btn.info{border-left-color:var(--infoAlt1Color)}.btns>.btn~.btn.success{border-left-color:var(--successAlt1Color)}.btns>.btn~.btn.warning{border-left-color:var(--warningAlt1Color)}.btns>.btn~.btn.danger{border-left-color:var(--dangerAlt1Color)}.btns>.btn~.btn.disabled,.btns>.btn~.btn[disabled]{border-left-color:var(--surfaceAlt3Color)}.btns>.btn:has(~.btn){border-top-right-radius:0;border-bottom-right-radius:0}.btns.full-width{width:100%}.btns.full-width>.btn{flex:1 1 0;min-width:0}.field:after{content:"";clear:both;display:table}.field input,.field textarea,.field select,.field .input{vertical-align:top;width:100%;letter-spacing:inherit;padding:10px var(--inputPadding);color:var(--surfaceTxtColor);font-weight:400;line-height:1;font-size:var(--fontSize);font-family:var(--baseFontFamily);scrollbar-width:thin;scrollbar-color:var(--surfaceAlt5Color) transparent;background:0 0;border:0;outline:0;align-self:stretch;margin:0;display:inline-block}[data-color-scheme=dark] :is(.field input,.field textarea,.field select,.field .input){--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark}:is(.field input,.field textarea,.field select,.field .input)::placeholder{-webkit-user-select:none;user-select:none;color:var(--surfaceTxtDisabledColor);font-weight:inherit;font-family:inherit}:is(.field input,.field textarea,.field select,.field .input):autofill{-webkit-text-fill-color:var(--surfaceTxtColor);box-shadow:0 0 0 50px var(--inputColor) inset;transition:box-shadow var(--animationSpeed);background:0 0}:is(.field input,.field textarea,.field select,.field .input):focus,:is(.field input,.field textarea,.field select,.field .input):focus-visible,:is(.field input,.field textarea,.field select,.field .input):focus-within{outline:0}:is(:is(.field input,.field textarea,.field select,.field .input):focus,:is(.field input,.field textarea,.field select,.field .input):focus-visible,:is(.field input,.field textarea,.field select,.field .input):focus-within):autofill{box-shadow:0 0 0 50px var(--inputFocusColor) inset}:is(.field input,.field textarea,.field select,.field .input).readonly,:is(.field input,.field textarea,.field select,.field .input)[readonly]{cursor:default;color:var(--surfaceTxtHintColor)}:is(.field input,.field textarea,.field select,.field .input).disabled,:is(.field input,.field textarea,.field select,.field .input)[disabled]{cursor:default;color:var(--surfaceTxtDisabledColor)}:is(.field input,.field textarea,.field select,.field .input):only-child{height:100%}.field input[type=range]{-webkit-appearance:none;left:var(--inputPadding);width:calc(100% - 2 * var(--inputPadding));background:var(--surfaceAlt5Color);height:6px;min-height:0;accent-color:var(--surfaceTxtHintColor);margin-top:16px;margin-bottom:16px;padding:0;position:relative;border-radius:var(--borderRadius)!important}.field input[type=color]{-webkit-appearance:none;border:0;height:36px;min-height:0;margin:1px 0}.field input[type=color]::-webkit-color-swatch-wrapper{border-radius:var(--borderRadius);padding:0}.field input[type=color]::-webkit-color-swatch{border-radius:var(--borderRadius);border:none}.field input[type=color]::-moz-color-swatch{border-radius:var(--borderRadius);border:none}.field .autoexpand-wrapper>.input,.field textarea{resize:vertical;min-height:38px;max-height:300px;padding-top:8px;padding-bottom:9px;line-height:1.5}@supports (field-sizing:content){:is(.field .autoexpand-wrapper>.input,.field textarea).autoexpand{field-sizing:content;resize:none}}.field .autoexpand-wrapper{display:grid}.field .autoexpand-wrapper>textarea{resize:none}.field .autoexpand-wrapper>.input{white-space:pre-wrap;visibility:hidden;overflow:auto}.field .autoexpand-wrapper>.input,.field .autoexpand-wrapper>textarea{grid-area:1/1/2/2}.field.addon{width:auto;color:var(--surfaceTxtHintColor);flex-shrink:0;align-items:center;display:inline-flex}.field.addon:after{content:none;display:none}.field:focus-within:not(.addon){background:var(--inputFocusColor)}.field:focus-within:not(.addon) label{color:var(--surfaceTxtColor)}.field-list,.field{border-radius:var(--inputBorderRadius);background:var(--inputColor);width:100%;min-width:0;transition:background var(--animationSpeed);outline:0;display:block;position:relative}:is(.field-list,.field):not(.addon)>:first-child:not(.btn){border-top-left-radius:inherit;border-top-right-radius:inherit}:is(.field-list,.field):not(.addon)>:last-child:not(.btn){border-bottom-left-radius:inherit;border-bottom-right-radius:inherit}:is(.field-list,.field) label{width:100%;min-height:24px;padding:9px var(--inputPadding) 1px;white-space:normal;color:var(--surfaceTxtHintColor);font-weight:700;line-height:1;font-size:var(--smFontSize);transition:color var(--animationSpeed);align-self:center;align-items:center;gap:5px;display:flex}:is(.field-list,.field) label i{padding:0;font-size:1em}:is(.field-list,.field) label:has(~.autoexpand-wrapper textarea[required]):after{vertical-align:top;content:"*";color:var(--dangerColor);margin:-5px 0 0 -2px;font-size:.75em;line-height:1}:is(.field-list,.field) label:has(~[required]):after{vertical-align:top;content:"*";color:var(--dangerColor);margin:-5px 0 0 -2px;font-size:.75em;line-height:1}:is(.field-list,.field) label:has(~.input.required):after{vertical-align:top;content:"*";color:var(--dangerColor);margin:-5px 0 0 -2px;font-size:.75em;line-height:1}:is(:is(.field-list,.field).required label,:is(.field-list,.field) label.required,:is(.field-list,.field) .required>label):after{vertical-align:top;content:"*";color:var(--dangerColor);margin:-5px 0 0 -2px;font-size:.75em;line-height:1}:is(.field-list,.field).disabled label,:is(.field-list,.field) label.disabled,:is(.field-list,.field) .disabled>label{color:var(--surfaceTxtDisabledColor)}:is(.field-list,.field) label:has(~.autoexpand-wrapper textarea[disabled]){color:var(--surfaceTxtDisabledColor)}:is(.field-list,.field) label:has(~.autoexpand-wrapper textarea[disabled]):after{color:inherit}:is(.field-list,.field) label:has(~[disabled]){color:var(--surfaceTxtDisabledColor)}:is(.field-list,.field) label:has(~[disabled]):after{color:inherit}:is(.field-list,.field) label:has(~.input.disabled){color:var(--surfaceTxtDisabledColor)}:is(.field-list,.field) label:has(~.input.disabled):after{color:inherit}:is(:is(.field-list,.field).disabled label,:is(.field-list,.field) label.disabled,:is(.field-list,.field) .disabled>label):after{color:inherit}:is(.field-list,.field).addon label{padding:0}:is(.field-list,.field) hr{background:var(--inputBorderColor);height:1px}:is(.field-list,.field).error,.error :is(.field-list,.field){color:var(--dangerColor)}:is(:is(.field-list,.field).error,.error :is(.field-list,.field)) label,:is(:is(.field-list,.field).error,.error :is(.field-list,.field)) input,:is(:is(.field-list,.field).error,.error :is(.field-list,.field)) textarea,:is(:is(.field-list,.field).error,.error :is(.field-list,.field)) select,:is(:is(.field-list,.field).error,.error :is(.field-list,.field)) .input{color:var(--dangerColor)!important}:is(.field-list,.field).error,.error :is(.field-list,.field){--inputColor:color-mix(in srgb, var(--dangerColor), var(--surfaceColor) 80%);--inputFocusColor:color-mix(in srgb, var(--dangerColor), var(--surfaceColor) 75%);--inputBorderColor:color-mix(in srgb, var(--dangerColor), var(--surfaceColor) 70%)}.field-content{flex-direction:column;gap:3px;margin-top:4px;padding:3px;display:flex;position:relative}.field-content .list{border:1px solid var(--inputBorderColor);background:0 0;border-left:0;border-right:0;border-radius:0;gap:0;width:auto;max-height:300px;margin:0 -3px}.field-content .list .list-item{box-shadow:none;border-top:1px solid var(--inputBorderColor);margin:0}.field-content .list .list-item:first-child{border-top:0}.field-content .list .list-item:not(.disabled)[data-dragstart=true],.field-content .list .list-item:not(.disabled).active,.field-content .list .list-item:not(.disabled).handle:hover,.field-content .list .list-item:not(.disabled).handle:active,.field-content .list .list-item:not(.disabled).highlight:hover,.field-content .list .list-item:not(.disabled).highlight:active{background:var(--inputFocusColor)}.field-list .field-list-content{scrollbar-width:thin;max-height:500px;color:var(--surfaceTxtColor);overflow:auto}.field-list label+.field-list-content{margin-top:8px}.field-list .field-list-item{width:100%;padding:var(--inputPadding);min-height:var(--btnHeight);border-top:1px solid var(--inputBorderColor);align-items:center;gap:10px;display:flex}.field-list .field-list-item.p-0:first-child>.field,.field-list .field-list-item.p-0:first-child>.fields .field{border-radius:0}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])){--checkboxSize:20px;--checkboxActiveColor:var(--successColor);--checkboxBorderColor:var(--surfaceAlt3Color);--checkboxBorderFocusColor:var(--surfaceAlt5Color);text-align:left;background:0 0;align-items:center;gap:10px;padding:0;display:flex}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])):focus-visible,:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])):focus-within{background:0 0}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])):after{content:none;display:none}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input{opacity:0;width:1px;height:1px;position:absolute}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) label{padding:0 0 0 calc(var(--checkboxSize) + 7px);-webkit-user-select:none;user-select:none;cursor:pointer;width:auto;color:var(--surfaceTxtColor);font-weight:400;font-size:var(--fontSize);line-height:var(--smLineHeight);min-height:var(--checkboxSize);background:0 0;margin:0}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) label:before{content:"";width:var(--checkboxSize);height:var(--checkboxSize);border-radius:var(--borderRadius);background:var(--surfaceColor);border:2px solid var(--checkboxBorderColor);transition:border-color var(--animationSpeed), box-shadow var(--animationSpeed), background var(--animationSpeed);display:block;position:absolute;top:0;left:0}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) label:after{content:"";z-index:1;width:var(--checkboxSize);height:var(--checkboxSize);text-align:center;font-size:1.15rem;font-weight:400;font-family:var(--iconFontFamily);color:var(--checkboxActiveColor);opacity:0;transition:transform var(--activeAnimationSpeed), opacity var(--activeAnimationSpeed);justify-content:center;align-items:center;display:flex;position:absolute;top:0;left:0;transform:translateY(2px)}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input:focus-visible~label,:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) label:hover,:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) label:focus-within{--checkboxBorderColor:var(--checkboxBorderFocusColor);background:0 0}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input[type=radio]~label:before{border-radius:50%}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input[type=radio]~label:after{content:"";font-size:.7em}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input:checked~label{--checkboxBorderColor:var(--checkboxActiveColor)}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input:checked~label:after{opacity:1;transform:scale(1)}:is(:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input:checked:focus-visible~label,:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input:checked~label:hover,:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input:checked~label:focus-within):before{box-shadow:0px 0px 0px 3px color-mix(in srgb, var(--checkboxActiveColor), transparent 85%)}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input.sm~label{--checkboxSize:18px;font-size:var(--smFontSize);padding-left:calc(var(--checkboxSize) + 5px);gap:3px}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input.sm~label:after{font-size:1.12em}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])){--switchH:24px;--switchW:41px;--switchTranslateX:0}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input.switch~label{--switchTranslateX:0;min-height:var(--switchH);padding-left:calc(var(--switchW) + 8px)}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input.switch~label:before{width:var(--switchW);height:var(--switchH);background:var(--checkboxBorderColor);border:0;border-radius:7px}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input.switch~label:after{content:"";height:calc(var(--switchH) - 8px);width:calc(var(--switchH) - 5px);opacity:1;transform:translateX(var(--switchTranslateX));background:#fff;border-radius:5px;top:4px;left:4px;box-shadow:1px 0 2px #0003}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input.switch~label:active:after{transform:scale(.92)}@supports (corner-shape:squircle){:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input.switch~label:before{corner-shape:squircle;border-radius:11px}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input.switch~label:after{corner-shape:squircle;border-radius:7px}}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input.switch:checked~label{--switchTranslateX:calc(var(--switchW) - var(--switchH) - 3px)}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input.switch:checked~label:before{background:var(--checkboxActiveColor)}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input.switch:checked~label:after{left:4px;box-shadow:-1px 0 2px #0003}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input.switch:checked~label:active:after{transform:scale(.92) translateX(var(--switchTranslateX))}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input.switch.sm~label{--switchH:21px;--switchW:35px}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input[disabled]~label{cursor:default;color:var(--surfaceTxtHintColor)}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input[disabled]~label:before{opacity:.6}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])) input[disabled]~label:after{box-shadow:none!important}:is(.field:has(input[type=checkbox]),.field:has(input[type=radio])).error label{--checkboxActiveColor:var(--dangerColor);color:var(--dangerColor)}.flex>.field,.inline-flex>.field{width:auto}.input.select{align-items:center;gap:10px;min-height:38px;padding:5px 0;display:flex}.input.select .selected-container{width:100%;padding:1px var(--inputPadding);color:var(--surfaceTxtHintColor);cursor:pointer;outline:0;flex-wrap:wrap;align-self:stretch;align-items:center;gap:5px;margin:0;display:flex}.input.select .selected-container:after{content:"";text-align:right;font-size:1.2rem;font-family:var(--iconFontFamily);transition:color var(--animationSpeed);align-content:center;margin-left:auto;margin-right:-2px;display:block}.input.select .selected-item{color:var(--surfaceTxtColor);border-radius:var(--borderRadius);background:0 0;align-items:center;gap:5px;padding:0;display:inline-flex}.input.select .selected-item .link-hint{font-size:var(--smFontSize);padding:1px}.input.select .dropdown{border-width:2px;border-color:var(--inputFocusColor);min-width:100px;margin:-2px 0}.input.select.single .selected-item{flex-grow:1}.input.select.single .selected-item .btn-option-unset{margin-left:auto}.input.select.single .selected-container{flex-wrap:nowrap}.input.select.multiple .selected-item{color:var(--surfaceTxtColor);background:var(--surfaceColor);padding:3px 4px}.input.select:has(.dropdown:popover-open) .selected-container:after{content:"";color:var(--surfaceTxtColor)}.input.select.disabled .selected-container{cursor:default}.input.select.disabled .selected-container:after{color:var(--surfaceTxtDisabledColor)}.input.select.disabled .selected-item{color:var(--surfaceTxtHintColor)}.fields{align-items:stretch;width:100%;display:flex}.fields .field:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.fields .field:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.fields .delimiter{background:var(--inputFocusColor);flex-shrink:0;width:1px;min-height:0}.fields .addon{padding:0 var(--inputPadding);align-items:center;gap:5px;display:inline-flex}.fields .addon:has(+.field){padding-right:0}.fields .field+.addon{padding-left:0}.fields .field:focus-within+.addon{background:var(--inputFocusColor)}.fields .addon:has(+.field:focus-within){background:var(--inputFocusColor)}.fields.error .delimiter{background:color-mix(in srgb, var(--dangerColor), var(--surfaceColor) 70%)}.field-help{width:100%;font-size:var(--smFontSize);line-height:var(--smLineHeight);color:var(--surfaceTxtHintColor);margin:7px 0 0;display:block}.field-help.error{color:var(--dangerColor)}.field-help code{font-size:.9em;line-height:1.4}.field-help p{margin:5px 0}.searchbar{min-height:var(--btnHeight);max-width:100%}.searchbar input,.searchbar .input{height:100%}.searchbar .field{--inputBorderRadius:30px}.searchbar .field:not(.addon){flex-grow:1;width:0}.pb-tinymce{width:100%;display:block}.field .pb-tinymce .tox-tinymce{border-width:2px;border-color:#0000}.field label~.pb-tinymce{margin-top:7px}.input.code-editor{cursor:text;scrollbar-width:thin;flex-shrink:0;align-items:stretch;width:100%;min-height:150px;max-height:350px;display:flex;position:relative;overflow:auto}.input.code-editor .code-editor-container{width:100%;position:relative}.input.code-editor .editor-content,.input.code-editor .highlight-overlay{tab-size:4;-webkit-hyphens:none;hyphens:none;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;text-align:left;letter-spacing:normal;width:100%;min-height:100%;font-size:.96rem;font-weight:400;line-height:1.5;font-family:var(--monospaceFontFamily);border:0;outline:0;margin:0;padding:0;display:block}.input.code-editor .highlight-overlay{pointer-events:none;position:absolute;top:0;left:0}.input.code-editor .editor-content{color:#0000;resize:none;caret-color:var(--surfaceTxtHintColor)}.input.code-editor .editor-content:empty:before{content:attr(data-placeholder);color:var(--surfaceTxtDisabledColor);white-space:normal}.input.code-editor.single-line{align-items:center;min-height:0;padding-top:9px;padding-bottom:9px}.input.code-editor.pre-wrap .editor-content,.input.code-editor.pre-wrap .highlight-overlay{white-space:pre-wrap}.dropdown{width:anchor-size(width);text-align:left;min-width:150px;max-height:330px;font-weight:400;font-size:var(--fontSize);line-height:var(--smLineHeight);color:var(--surfaceTxtColor);background:var(--surfaceColor);box-shadow:var(--boxShadow);scrollbar-width:thin;border-radius:var(--borderRadius);border:1px solid var(--surfaceAlt3Color);outline:0;flex-direction:column;gap:5px;margin:5px 0;padding:5px;display:inline-flex;overflow:auto}.dropdown[popover]{position-area:bottom span-left;position-try-fallbacks:flip-block;opacity:0;transition:opacity var(--animationSpeed), transform var(--animationSpeed), display var(--animationSpeed) allow-discrete, overlay var(--animationSpeed) allow-discrete;display:none;transform:translateY(3px)}.dropdown[popover]:popover-open{opacity:1;display:inline-flex;transform:translateY(0)}@starting-style{.dropdown[popover]:popover-open{opacity:0;transform:translateY(3px)}}@supports not (fill:context-stroke){.dropdown[popover]{position-try-fallbacks:none!important;transition:none!important}}.dropdown[popover].left{position-area:bottom span-right}.dropdown hr{margin:0}.dropdown .dropdown-item{cursor:pointer;-webkit-user-select:none;user-select:none;word-break:break-word;width:100%;color:inherit;transition:background var(--animationSpeed);border-radius:var(--borderRadius);outline:0;align-items:center;gap:8px;padding:10px 12px;text-decoration:none;display:flex}.dropdown .dropdown-item:hover{background:var(--surfaceAlt1Color)}.dropdown .dropdown-item:focus-visible{outline:2px dotted var(--surfaceAlt3Color)}.dropdown .dropdown-item:active{background:var(--surfaceAlt2Color);transition-duration:var(--activeAnimationSpeed)}.dropdown .dropdown-item.active{background:var(--surfaceAlt2Color);transition-duration:var(--activeAnimationSpeed)}.dropdown .dropdown-item.active code{background:var(--surfaceAlt1Color)}.dropdown .dropdown-item.active:hover{background:var(--surfaceAlt3Color);transition-duration:var(--animationSpeed)}.dropdown .dropdown-item[disabled],.dropdown .dropdown-item.disabled{cursor:default;color:var(--surfaceTxtDisabledColor);background:0 0}:is(.dropdown .dropdown-item input[type=checkbox],.dropdown .dropdown-item input[type=radio])~label{width:100%}.dropdown>.field,.dropdown>.fields-group{margin:0}:is(.dropdown .field:has(.search),.dropdown .fields-group:has(.search)){border-bottom:1px solid var(--surfaceAlt1Color);background:0 0;margin:0}:is(.dropdown .field:has(.search),.dropdown .fields-group:has(.search)) .field,:is(.dropdown .field:has(.search),.dropdown .fields-group:has(.search)) input.search{background:0 0;border-bottom:0}.dropdown .dropdown-search{border-bottom:1px solid var(--surfaceAlt2Color)}.dropdown .dropdown-search .field{background:0 0!important}.dropdown.nowrap,.dropdown.txt-nowrap{white-space:nowrap;width:auto}.dropdown.sm{min-width:100px;font-size:var(--smFontSize)}.dropdown.sm .dropdown-item{gap:5px;padding:7px}.dropdown.autocomplete{z-index:99999;word-break:break-word;max-width:350px;max-height:200px;font-size:var(--smFontSize);gap:3px;padding:3px;position:fixed}.dropdown.autocomplete .dropdown-item{padding:2px 4px;line-height:1.2}.dropdown.history-searchbar-dropdown[popover]{min-width:300px;max-width:450px}.accordion{--siblingSpacing:var(--smSpacing);--contentPadding:var(--smSpacing);width:100%;color:var(--surfaceTxtColor);border-radius:var(--borderRadius);background:var(--surfaceAlt1Color);border:1px solid var(--surfaceAlt3Color);transition:border var(--animationSpeed), border-radius var(--animationSpeed), box-shadow var(--animationSpeed), margin var(--animationSpeed);display:block;position:relative}.accordion summary{width:100%;min-height:var(--lgBtnHeight);cursor:pointer;padding:10px var(--smSpacing);padding-right:calc(var(--smSpacing) + 30px);background:var(--surfaceColor);border-radius:var(--borderRadius);-webkit-user-select:none;user-select:none;transition:background var(--animationSpeed), border var(--animationSpeed), border-radius var(--animationSpeed);align-items:center;gap:10px;display:flex;position:relative}.accordion summary::marker{content:"";display:none}.accordion summary:before{right:calc(var(--smSpacing) - 3px);content:"";width:20px;height:20px;font-size:1.3rem;font-weight:400;line-height:20px;font-family:var(--iconFontFamily);color:var(--surfaceTxtHintColor);transition:color var(--animationSpeed);flex-shrink:0;align-content:center;margin-top:-10px;display:block;position:absolute;top:50%}.accordion summary:not([tabindex="-1"]):hover,.accordion summary:not([tabindex="-1"]):focus-visible{background:var(--surfaceAlt1Color);outline:0}:is(.accordion summary:not([tabindex="-1"]):hover,.accordion summary:not([tabindex="-1"]):focus-visible):before{color:var(--surfaceTxtColor)}.accordion summary[tabindex="-1"]{cursor:default;-webkit-user-select:auto;user-select:auto;padding-right:var(--smSpacing);outline:0}.accordion summary[tabindex="-1"]:before{content:none;display:none}.accordion::details-content{height:0;padding:0 var(--contentPadding);background:var(--surfaceColor);border-bottom-left-radius:var(--borderRadius);border-bottom-right-radius:var(--borderRadius);transition:border var(--slideAnimationSpeed) step-end, height var(--slideAnimationSpeed), padding var(--slideAnimationSpeed), content-visibility var(--slideAnimationSpeed), overflow var(--slideAnimationSpeed) step-start;transition-behavior:allow-discrete;overflow:clip}.accordion:has(+.accordion){border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion:has(+.accordion) summary{border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion:not([open]):has(+.accordion[open]){border-bottom-left-radius:var(--borderRadius);border-bottom-right-radius:var(--borderRadius);border-bottom-width:1px}.accordion:not([open]):has(+.accordion[open]) summary{border-bottom-left-radius:var(--borderRadius);border-bottom-right-radius:var(--borderRadius)}.accordion+.accordion{border-top-width:0;border-top-left-radius:0;border-top-right-radius:0}.accordion+.accordion summary{border-top-left-radius:0;border-top-right-radius:0}.accordion+.accordion[open]{margin-top:var(--siblingSpacing)}.accordion[open]{border-radius:var(--borderRadius);box-shadow:var(--boxShadow);border-width:1px}.accordion[open] summary{background:var(--surfaceAlt1Color);border-radius:var(--borderRadius) var(--borderRadius) 0 0}.accordion[open] summary:before{content:""}.accordion[open]::details-content{border-top:1px solid var(--surfaceAlt3Color);padding-top:var(--contentPadding);padding-bottom:var(--contentPadding);height:auto;transition:height var(--slideAnimationSpeed), padding var(--slideAnimationSpeed), content-visibility var(--slideAnimationSpeed), overflow var(--slideAnimationSpeed) step-end;transition-behavior:allow-discrete;overflow:visible}.accordion[open]+.accordion{margin-top:var(--siblingSpacing);border-top-left-radius:var(--borderRadius);border-top-right-radius:var(--borderRadius);border-top-width:1px}.accordion[open]+.accordion summary{border-top-left-radius:var(--borderRadius);border-top-right-radius:var(--borderRadius)}.accordion.noanimation::details-content{transition:none!important}.bulkbar{z-index:11;bottom:var(--spacing);opacity:1;width:450px;max-width:95%;padding:5px var(--smSpacing);min-height:var(--lgBtnHeight);background:var(--surfaceColor);box-shadow:var(--boxShadow);border:1px solid var(--surfaceAlt3Color);transition-behavior:allow-discrete;transition-property:opacity,transform,display;transition-duration:var(--animationSpeed);border-radius:50px;flex-wrap:wrap;align-items:center;gap:10px;display:flex;position:fixed;left:50%;transform:translate(-50%,10px)}@starting-style{.bulkbar{opacity:0;transform:translate(-50%,10px)}}.bulkbar[hidden],.bulkbar.hidden{opacity:0;transform:translate(-50%,10px)}.bulkbar>.btn:first-child{margin-left:-5px}.bulkbar>.btn:last-child{margin-right:-5px}@media (width<=480px){.bulkbar{border-radius:var(--borderRadius);padding:min(10px, var(--smSpacing)) var(--smSpacing)}.bulkbar>.txt,.bulkbar>.content{width:100%}}.bulkbar-wrapper{z-index:11;width:100%;left:0;bottom:var(--smSpacing);pointer-events:none;position:sticky;right:0}.bulkbar-wrapper .bulkbar{margin:var(--smSpacing) auto;pointer-events:auto;position:relative;bottom:0;left:auto;right:auto;transform:translateY(0)}@starting-style{.bulkbar-wrapper .bulkbar{transform:translateY(10px)}}.bulkbar-wrapper .bulkbar[hidden],.bulkbar-wrapper .bulkbar.hidden{transform:translateY(10px)}.tabs-header{z-index:0;border-bottom:2px solid var(--surfaceAlt2Color);align-items:center;gap:10px;width:100%;display:flex;position:relative}.tabs-header .tab-item{cursor:pointer;text-align:center;-webkit-user-select:none;user-select:none;min-width:0;min-height:var(--btnHeight);padding:5px var(--smSpacing);border-top-left-radius:var(--borderRadius);border-top-right-radius:var(--borderRadius);color:var(--surfaceTxtHintColor);transition:color var(--animationSpeed), background var(--animationSpeed);outline:0;justify-content:center;align-items:center;gap:5px;display:inline-flex}.tabs-header .tab-item:hover,.tabs-header .tab-item:focus-visible{color:var(--surfaceTxtColor);background:var(--surfaceAlt1Color)}.tabs-header .tab-item.active,.tabs-header .tab-item:active{color:var(--surfaceTxtColor);background:var(--surfaceAlt2Color);transition-duration:var(--activeAnimationSpeed)}.tabs-header.equal-width .tab-item{flex:1 0 0;padding:5px}.code-block-tabs-content{z-index:1;margin-top:calc(-1 * (var(--borderRadius)));position:relative}.code-block-tabs-content code.block{padding:max(10px, calc(var(--smSpacing) - 5px)) max(10px, var(--smSpacing))}.modal{z-index:1000;opacity:0;word-break:break-word;width:620px;max-width:100%;height:100%;color:var(--surfaceTxtColor);background:var(--surfaceColor);backface-visibility:hidden;transition-property:opacity,transform,width,display;transition-duration:var(--modalAnimationSpeed);transition-behavior:allow-discrete;box-shadow:var(--leftBoxShadow);overscroll-behavior:none;border:0;outline:0;flex-direction:column;margin:0;display:none;position:fixed;top:0;right:0;transform:translate(30px)}.modal[data-modal-state=open]{opacity:1;display:flex;transform:translate(0)}@starting-style{.modal[data-modal-state=open]{opacity:0;transform:translate(30px)}}.modal:before{content:"";z-index:-2;background:var(--modalOverlayColor);width:200vw;height:200vh;display:block;position:fixed;top:-100vh;left:-100vw}.modal:after{content:"";z-index:-1;border-radius:inherit;background:inherit;width:100%;height:100%;display:block;position:absolute;top:0;left:0}.modal .modal-header,.modal .modal-content,.modal .modal-footer{padding:var(--spacing);outline:0}.modal .modal-header,.modal .modal-footer{align-items:center;gap:var(--smSpacing);width:100%;padding-top:calc(var(--spacing) - 10px);padding-bottom:calc(var(--spacing) - 10px);display:flex}.modal .modal-footer{border-top:1px solid var(--surfaceAlt2Color);margin-top:auto}.modal .modal-content{scrollbar-width:thin;flex-grow:1;position:relative;overflow:auto}.modal .modal-content>:first-child{margin-top:0}.modal .modal-content>:last-child{margin-bottom:0}.modal .modal-header .modal-close-btn.transparent{margin-right:-10px}.modal .modal-header:not(.isolated)~.modal-content{padding-top:5px}.modal .modal-header.isolated{background:var(--surfaceAlt1Color);border-bottom:1px solid var(--surfaceAlt2Color);border-top-left-radius:inherit;border-top-right-radius:inherit}.modal .modal-title{align-content:center}.modal.sm{width:480px}.modal.lg{width:880px}.modal.full{width:100%}.modal.preview,.modal.popup{max-width:95%;height:min-content;max-height:95%;box-shadow:var(--boxShadow);border-radius:var(--lgBorderRadius);margin:auto;inset:0;transform:scale(.98)}:is(.modal.preview,.modal.popup).full{width:95%}:is(.modal.preview,.modal.popup) .modal-header,:is(.modal.preview,.modal.popup) .modal-content,:is(.modal.preview,.modal.popup) .modal-footer{border-radius:inherit}:is(.modal.preview,.modal.popup) .modal-header,:is(.modal.preview,.modal.popup) .modal-footer{padding-top:calc(var(--spacing) - 5px);padding-bottom:calc(var(--spacing) - 5px)}:is(:is(.modal.preview,.modal.popup) .modal-header:has(~.modal-content),:is(.modal.preview,.modal.popup) .modal-header:has(~.modal-footer),:is(.modal.preview,.modal.popup) .modal-content:has(~.modal-footer)){border-bottom-right-radius:0;border-bottom-left-radius:0}:is(.modal.preview,.modal.popup) .modal-header~.modal-content,:is(.modal.preview,.modal.popup) .modal-content~.modal-footer,:is(.modal.preview,.modal.popup) .modal-header~.modal-footer{border-top-left-radius:0;border-top-right-radius:0}:is(.modal.preview,.modal.popup) .modal-footer{background:var(--surfaceAlt1Color)}:is(.modal.preview,.modal.popup)[data-modal-state=open]{transform:scale(1)}@starting-style{:is(.modal.preview,.modal.popup)[data-modal-state=open]{transform:scale(.98)}}.modal.preview{width:min-content;min-width:400px;min-height:300px}.modal.preview .modal-footer{padding:var(--smSpacing)}.modal.preview .modal-content{text-align:center;justify-content:center;align-items:flex-start;width:100%;max-width:100%;margin:auto;padding:0;display:flex}.modal.preview .modal-content:has(img){width:max-content}.modal.preview .modal-content:before,.modal.preview .modal-content:after{content:none}.modal.preview .modal-content img{width:100%;margin:auto}.modal.preview .modal-content object{width:100%;height:100%;margin:auto}.modal.preview:has(object){width:75%;height:85%}@media (width<=900px){.modal.preview:has(object){width:90%;height:90%}}.modal.preview.preview-audio{width:500px;height:400px}.tox-fullscreen .modal{transition:none;width:100%!important}.modal-content{--topShadowOffset:calc(var(--spacing) + 1px);--bottomShadowOffset:calc(var(--spacing) + 1px);min-height:92px;container-type:scroll-state}.modal-content:before,.modal-content:after{content:"";z-index:9;width:auto;height:1px;margin-left:calc(-1 * var(--spacing));margin-right:calc(-1 * var(--spacing));pointer-events:none;opacity:0;display:block;position:sticky;left:0}.modal-content:before{top:calc(100% + var(--bottomShadowOffset));margin-bottom:calc(-1 * var(--bottomShadowOffset));margin-top:var(--bottomShadowOffset);box-shadow:var(--bottomScrollShadow)}@container scroll-state(scrollable:bottom){.modal-content:before{opacity:1;transition:opacity var(--animationSpeed)}}.modal-content:after{top:auto;bottom:calc(100% + var(--topShadowOffset));margin-top:calc(-1 * var(--topShadowOffset));margin-bottom:var(--topShadowOffset);box-shadow:var(--topScrollShadow)}@container scroll-state(scrollable:top){.modal-content:after{opacity:1;transition:opacity var(--animationSpeed)}}.modal-header:not(.isolated)~.modal-content:after{--topShadowOffset:6px}.modal-header .tabs-header{flex-grow:1;width:auto}.modal-header .tabs-header .tab-item{font-size:var(--lgFontSize)}.modal-header.isolated :is(.modal-header .tabs-header):last-child{padding:0 var(--spacing);margin-left:calc(-1 * var(--spacing));margin-right:calc(-1 * var(--spacing));margin-bottom:calc(-1 * var(--spacing) + 9px);border-bottom:0}.modal-header.isolated :is(.modal-header .tabs-header):last-child .tab-item{border:1px solid #0000;border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.modal-header.isolated :is(.modal-header .tabs-header):last-child .tab-item:hover,.modal-header.isolated :is(.modal-header .tabs-header):last-child .tab-item:focus-visible{background:var(--surfaceAlt2Color)}.modal-header.isolated :is(.modal-header .tabs-header):last-child .tab-item:active{background:var(--surfaceAlt3Color)}.modal-header.isolated :is(.modal-header .tabs-header):last-child .tab-item.active{background:var(--surfaceColor);border-color:var(--surfaceAlt2Color)}.popup .modal-header.isolated :is(.modal-header .tabs-header):last-child{margin-bottom:calc(-1 * var(--spacing) + 4px)}.app{flex-direction:column;width:100%;height:100%;padding:0;display:flex}.app:has(.accent-surface){background:var(--accentColor);color:var(--accentTxtColor)}.app-header{--headerItemsGap:var(--inputPadding);align-items:center;gap:var(--headerItemsGap);width:100%;min-height:38px;font-size:var(--smFontSize);line-height:var(--smLineHeight);flex-shrink:0;padding:2px 10px;display:flex}@media (display-mode:minimal-ui) or (display-mode:standalone){.app-header{border-top:1px solid var(--accentAlt1Color);border-bottom:1px solid #0000}}.app-header .logo{vertical-align:top;border-radius:var(--borderRadius);justify-content:center;align-items:center;gap:5px;text-decoration:none;display:inline-flex}.app-header .logo img{vertical-align:top;max-height:26px}@media (width<=400px){.app-header{gap:7px;padding-left:5px;padding-right:5px}}.app-main-nav{align-items:center;gap:max(var(--headerItemsGap), 5px);scrollbar-width:thin;overflow:auto;overflow:overlay;margin:0 -3px;padding:3px;display:inline-flex;position:relative;container-type:scroll-state}.app-main-nav:before,.app-main-nav:after{content:"";z-index:9;opacity:0;pointer-events:none;flex-shrink:0;align-self:stretch;width:1px;height:auto;margin:0;display:block;position:sticky}.app-main-nav:before{margin-right:calc(-1 * (var(--headerItemsGap) + 1px));left:-5px;box-shadow:2px 0 4px 1px #0006}@container scroll-state(scrollable:left){.app-main-nav:before{opacity:1;transition:opacity var(--animationSpeed)}}.app-main-nav:after{margin-left:calc(-1 * (var(--headerItemsGap) + 1px));right:-5px;box-shadow:-2px 0 4px 1px #0006}@container scroll-state(scrollable:right){.app-main-nav:after{opacity:1;transition:opacity var(--animationSpeed)}}@media (width<=500px){.app-main-nav{--headerItemsGap:5px}}.app-header .header-link{-webkit-user-select:none;user-select:none;cursor:pointer;color:var(--accentTxtHintColor);border-radius:var(--borderRadius);transition:color var(--animationSpeed), background var(--animationSpeed);align-items:center;gap:5px;padding:4px 5px;font-weight:700;text-decoration:none;display:inline-flex}.app-header .header-link[data-popover-state=true],.app-header .header-link.active,.app-header .header-link:hover,.app-header .header-link:focus-visible{color:var(--accentTxtColor);background:var(--surfaceAlt2Color)}.app-header .header-link:active{background:var(--surfaceAlt3Color);transition-duration:var(--activeAnimationSpeed)}.app-header .logged-user{max-width:300px}@media (width<=600px){.app-header .logged-user .superuser-name{display:none}}.page{height:100%;color:var(--surfaceTxtColor);background:var(--surfaceColor);border-radius:var(--lgBorderRadius);display:flex;position:relative;overflow:auto}.page:first-child{border-top-left-radius:0;border-top-right-radius:0}.page:last-child{border-bottom-right-radius:0;border-bottom-left-radius:0}.page-content{z-index:0;width:100%;min-width:0;padding:var(--spacing);flex-grow:1;overflow:auto}.page-header{column-gap:var(--smSpacing);row-gap:calc(var(--smSpacing) - 5px);width:100%;min-height:var(--btnHeight);margin:-10px 0 calc(var(--spacing) - 10px);flex-wrap:wrap;flex-shrink:0;align-items:center;display:flex}.page-header .searchbar{flex-grow:1;width:auto}.page-header .page-header-secondary-btns,.page-header .page-header-primary-btns{flex-shrink:0;justify-content:flex-end;display:inline-flex}.page-header-secondary-btns{gap:10px}@media (width<=550px){.page-header-secondary-btns{gap:5px}}.page-header-primary-btns{gap:var(--smSpacing);margin-left:auto}.page-header-primary-btns .btn{white-space:nowrap;flex-wrap:nowrap}@media (width<=950px){.page-header-primary-btns{gap:5px}.page-header-primary-btns .btn{flex-grow:1;flex-basis:0;padding-left:10px;padding-right:10px}}@media (width<=550px){.page-header-primary-btns{gap:5px}.page-header-primary-btns .api-preview-btn{display:none}.page-header-primary-btns .btn:not(.circle){aspect-ratio:1;border-radius:50%;width:auto;min-width:0;padding:0}.page-header-primary-btns .btn:not(.circle) i+.txt{display:none}}.page-footer{z-index:10;align-items:center;gap:var(--smSpacing);width:auto;color:var(--surfaceTxtHintColor);font-size:var(--smFontSize);line-height:var(--smLineHeight);box-shadow:0px -1px 0px 0px var(--surfaceAlt2Color);padding:10px var(--spacing);margin:auto calc(-1 * var(--spacing)) calc(-1 * var(--spacing));flex-wrap:wrap;display:flex}.page-footer a{transition:color var(--animationSpeed);border-radius:var(--borderRadius);text-decoration:none}.page-footer a:hover,.page-footer a:focus-visible{color:var(--surfaceTxtColor)}.page-footer .credits{--creditsGap:20px;align-items:center;gap:var(--creditsGap);margin:0 0 0 auto;display:inline-flex}.page-footer .credits .credit-item{color:var(--surfaceTxtDisabledColor);align-items:center;gap:5px;display:inline-flex;position:relative}.page-footer .credits .credit-item:before{content:"";pointer-events:none;-webkit-user-select:none;user-select:none;top:50%;left:calc(var(--creditsGap) / -2);opacity:.5;background:var(--surfaceTxtDisabledColor);width:1px;height:10px;margin-top:-5px;position:absolute}.page-footer .credits .credit-item:first-child:before{content:none;display:none}.page-footer .credits .credit-item:hover,.page-footer .credits .credit-item:active,.page-footer .credits .credit-item:focus-within{color:var(--surfaceTxtColor)}.page-sidebar{--sidebarSpacing:calc(var(--spacing) / 2);width:var(--pageSidebarWidth);min-width:var(--pageSidebarWidth);background:var(--surfaceAlt1Color);border-right:1px solid var(--surfaceAlt2Color);backface-visibility:hidden;flex-direction:column;flex-shrink:0;max-width:min(400px,80%);display:flex;position:relative;overflow:auto}.page-sidebar .sidebar-content{padding:var(--sidebarSpacing);position:relative}.page-sidebar .sidebar-content.scrollable{scrollbar-width:thin;--topShadowOffset:calc(var(--sidebarSpacing) + 1px);--bottomShadowOffset:calc(var(--sidebarSpacing) + 1px);overflow:auto;container-type:scroll-state}.page-sidebar .sidebar-content.scrollable:before,.page-sidebar .sidebar-content.scrollable:after{content:"";z-index:9;width:auto;height:1px;margin-left:calc(-1 * var(--sidebarSpacing));margin-right:calc(-1 * var(--sidebarSpacing));pointer-events:none;opacity:0;display:block;position:sticky;left:0}.page-sidebar .sidebar-content.scrollable:before{top:calc(100% + var(--bottomShadowOffset));margin-bottom:calc(-1 * var(--bottomShadowOffset));margin-top:var(--bottomShadowOffset);box-shadow:var(--bottomScrollShadow)}@container scroll-state(scrollable:bottom){.page-sidebar .sidebar-content.scrollable:before{opacity:1;transition:opacity var(--animationSpeed)}}.page-sidebar .sidebar-content.scrollable:after{top:auto;bottom:calc(100% + var(--topShadowOffset));margin-top:calc(-1 * var(--topShadowOffset));margin-bottom:var(--topShadowOffset);box-shadow:var(--topScrollShadow)}@container scroll-state(scrollable:top){.page-sidebar .sidebar-content.scrollable:after{opacity:1;transition:opacity var(--animationSpeed)}}.page-sidebar .sidebar-content:has(+.sidebar-content){--bottomShadowOffset:1px;padding-bottom:0}.page-sidebar .sidebar-search{--inputPadding:var(--sidebarSpacing);border-bottom:1px solid var(--surfaceAlt2Color);--inputColor:var(--surfaceAlt1Color);--inputFocusColor:var(--surfaceAlt2Color);--inputBorderColor:var(--surfaceAlt3Color);align-items:center;gap:5px;min-height:50px;display:flex}.page-sidebar .sidebar-search .fields{height:100%}.page-sidebar .sidebar-search .field{border-radius:0;height:100%}.page-sidebar .sidebar-search .field input{height:100%}.page-sidebar hr{margin:var(--sidebarSpacing) 0}.page-sidebar .nav-group{box-shadow:none;margin:0 0 var(--sidebarSpacing);background:0 0;border:0;border-radius:0;padding:0;transition:none}.page-sidebar .nav-group:last-child{margin:0}.page-sidebar .nav-group summary{-webkit-user-select:none;user-select:none;min-height:30px;font-weight:700;font-size:var(--smFontSize);color:var(--surfaceTxtHintColor);transition:color var(--animationSpeed);background:0 0;border:0;border-radius:0;align-items:center;gap:5px;margin:0;padding:0;display:flex}.page-sidebar .nav-group summary::marker{content:"";display:none}.page-sidebar .nav-group summary:before{content:"";width:20px;height:20px;font-size:1em;font-weight:400;line-height:20px;font-family:var(--iconFontFamily);flex-shrink:0;order:1;align-content:center;margin:0;padding:0;display:block;position:relative;inset:auto}.page-sidebar .nav-group summary .actions{opacity:0;transition:transform var(--animationSpeed), opacity var(--animationSpeed);order:100;align-items:center;gap:5px;margin:0 0 0 auto;display:inline-flex;transform:translate(3px)}.page-sidebar .nav-group summary .actions:focus-within{opacity:1;transform:translate(0)}.page-sidebar .nav-group summary:hover,.page-sidebar .nav-group summary:active,.page-sidebar .nav-group summary:focus-visible{cursor:pointer;color:var(--surfaceTxtColor)}:is(.page-sidebar .nav-group summary:hover,.page-sidebar .nav-group summary:active,.page-sidebar .nav-group summary:focus-visible) .actions{opacity:1;transform:translate(0)}.page-sidebar .nav-group summary[tabindex="-1"]{cursor:default;color:var(--surfaceTxtHintColor)}.page-sidebar .nav-group summary[tabindex="-1"]:before{content:none;display:none}.page-sidebar .nav-group summary:empty{display:none}.page-sidebar .nav-group::details-content{background:0 0;border:0;flex-direction:column;gap:5px;margin:0;padding:0;display:flex}.page-sidebar .nav-group[open] summary:before{content:""}.compact :is(.page-sidebar .nav-group)::details-content{gap:2px}.page-sidebar .nav-group.compact::details-content{gap:2px}.page-sidebar .nav-group .nav-item{cursor:pointer;width:100%;font-size:var(--lgFontSize);color:var(--surfaceTxtHintColor);min-height:var(--btnHeight);border-radius:var(--borderRadius);transition:color var(--animationSpeed), background var(--animationSpeed);outline:0;align-items:center;gap:10px;padding:5px 10px;text-decoration:none;display:flex}.page-sidebar .nav-group .nav-item .txt{text-overflow:ellipsis;overflow:hidden}.page-sidebar .nav-group .nav-item .pin{color:var(--surfaceTxtDisabledColor);border-radius:var(--borderRadius);opacity:0;transition:color var(--animationSpeed), opacity var(--animationSpeed), transform var(--animationSpeed);margin-left:auto;margin-right:-5px;padding:2px;font-size:.8em;transform:translate(3px)}.page-sidebar .nav-group .nav-item .pin:hover,.page-sidebar .nav-group .nav-item .pin:focus-visible{color:var(--surfaceTxtColor)}.page-sidebar .nav-group .nav-item:hover .pin,.page-sidebar .nav-group .nav-item:focus-visible .pin,.page-sidebar .nav-group .nav-item:active .pin,.page-sidebar .nav-group .nav-item .pin:hover,.page-sidebar .nav-group .nav-item .pin:focus-visible,.page-sidebar .nav-group .nav-item .pin:active,.page-sidebar .nav-group .nav-item .pin.active{opacity:1;transform:translate(0)}.page-sidebar .nav-group .nav-item:hover,.page-sidebar .nav-group .nav-item:focus-visible,.page-sidebar .nav-group .nav-item:active,.page-sidebar .nav-group .nav-item.active{background:var(--surfaceAlt2Color)}.page-sidebar .nav-group .nav-item.active{color:var(--surfaceTxtColor)}.page-sidebar .nav-group .nav-item:active{background:var(--surfaceAlt3Color);transition-duration:var(--activeAnimationSpeed)}.page-sidebar .dragline{position:absolute;top:0;right:0}.page-sidebar[data-responsive=true]{z-index:9;opacity:0;visibility:hidden;height:100%;transition:opacity var(--animationSpeed), visibility var(--animationSpeed), transform var(--animationSpeed);position:absolute;top:0;left:0;transform:translate(-30px)}.page-sidebar[data-responsive=true] .dragline{display:none}.page-sidebar[data-responsive=true].active{opacity:1;visibility:visible;box-shadow:100px 0px 0px 1000px var(--modalOverlayColor);transform:translate(0)}.btn.responsive-sidebar-btn{min-height:var(--smBtnHeight);align-self:stretch;height:auto;margin:0 -5px;padding:0 10px}.btn.responsive-sidebar-btn i{margin-top:2px}.collections-sidebar .sidebar-content.collections-list{--topShadowOffset:6px;--bottomShadowOffset:6px;padding-top:5px;padding-bottom:5px}.page-content.full-height{flex-direction:column;align-items:normal;gap:0;display:flex}@supports not (fill:context-stroke){.page-content.full-height{overflow-x:hidden}}.rule-field{min-height:67px}.rule-field .code-editor{z-index:0;min-height:41px}.rule-field .code-editor .editor-content:empty:before{font-family:var(--baseFontFamily)}.rule-field .code-editor .highlight-overlay{color:var(--surfaceTxtColor)}.rule-field .code-editor .editor-content,.rule-field .code-editor .highlight-overlay{white-space:pre-wrap}.rule-field .superuser-toggle,.rule-field .superuser-toggle:last-child:not(.btn){border-radius:0;border-bottom-left-radius:var(--borderRadius);border-top-right-radius:var(--borderRadius)}.rule-field .superuser-toggle{z-index:3;cursor:pointer;-webkit-user-select:none;user-select:none;font-weight:700;line-height:1;font-size:var(--smFontSize);color:var(--surfaceTxtHintColor);background:var(--inputFocusColor);border:1px solid var(--surfaceAlt5Color);transition:color var(--animationSpeed), background var(--animationSpeed);border-top:0;border-right:0;outline:0;align-items:center;gap:5px;padding:8px 10px;display:inline-flex;position:absolute;top:0;right:0}.rule-field .superuser-toggle:hover,.rule-field .superuser-toggle:active,.rule-field .superuser-toggle:focus-visible{color:var(--successColor);background:var(--inputBorderColor)}.rule-field .superuser-toggle[disabled]{cursor:not-allowed;color:var(--surfaceTxtDisabledColor);background:var(--surfaceAlt3Color)}.rule-field .input:focus-within~.superuser-toggle{background:var(--inputBorderColor)}.rule-field label{z-index:2;position:relative}.rule-field label .superusers-label{opacity:1;visibility:visible;transition:opacity var(--animationSpeed), visibility var(--animationSpeed), transform var(--animationSpeed);transform:translate(0)}.rule-field label .superusers-label.hidden,.rule-field label .superusers-label[hidden]{opacity:0;visibility:hidden;transform:translate(3px);display:inline!important}.rule-field .unlock-overlay{z-index:1;cursor:pointer;-webkit-user-select:none;user-select:none;width:100%;height:100%;font-weight:700;font-size:var(--smFontSize);color:var(--successColor);padding:5px var(--smSpacing);border-radius:var(--borderRadius);background:var(--surfaceAlt1Color);border:2px solid var(--surfaceAlt2Color);transition:border-color var(--animationSpeed);justify-content:flex-end;align-items:center;gap:10px;display:flex;position:absolute;top:0;left:0}.rule-field .unlock-overlay .txt{opacity:0;transition:opacity var(--animationSpeed), transform var(--animationSpeed);transform:translate(3px)}.rule-field .unlock-overlay i{font-size:1.4em}.rule-field .unlock-overlay:hover,.rule-field .unlock-overlay:active,.rule-field .unlock-overlay:focus-visible{border-color:var(--surfaceAlt4Color)}:is(.rule-field .unlock-overlay:hover,.rule-field .unlock-overlay:active,.rule-field .unlock-overlay:focus-visible) .txt{opacity:1;transform:translate(0)}.rule-field .unlock-overlay:active{border-color:var(--surfaceAlt5Color);transition-duration:var(--activeAnimationSpeed)}.rule-field .unlock-overlay[disabled]{cursor:not-allowed}.rule-field .unlock-overlay[disabled] .txt{display:none}.rule-field.locked label{pointer-events:none}.rate-limit-table{background:0 0}.rate-limit-table tr,.rate-limit-table td,.rate-limit-table th{background:0 0;border:0;height:auto;min-height:0;padding:0}.rate-limit-table th{font-size:var(--smFontSize);line-height:var(--smLineHeight);padding:0 0 10px}.rate-limit-table .rate-limit-row .fields,.rate-limit-table .rate-limit-row .field,.rate-limit-table .rate-limit-row input,.rate-limit-table .rate-limit-row select,.rate-limit-table .rate-limit-row .input,.rate-limit-table .rate-limit-row .select{background:0 0;border-radius:0;height:100%}.rate-limit-table .rate-limit-row td{background:var(--inputColor);border-left:1px solid var(--inputBorderColor);border-top:1px solid var(--inputBorderColor);transition:background var(--animationSpeed)}.rate-limit-table .rate-limit-row td:first-child{border-left:0}.rate-limit-table .rate-limit-row td:focus-within{background:var(--inputFocusColor)}.rate-limit-table .rate-limit-row td:has(.error:not(.hidden)){background:var(--surfaceDangerColor)}.rate-limit-table .rate-limit-row:first-child td{border-top:0}.rate-limit-table .rate-limit-row:first-child td:first-child{border-top-left-radius:var(--borderRadius)}.rate-limit-table .rate-limit-row:first-child td:last-child{border-top-right-radius:var(--borderRadius)}.rate-limit-table .rate-limit-row:last-child td:first-child{border-bottom-left-radius:var(--borderRadius)}.rate-limit-table .rate-limit-row:last-child td:last-child{border-bottom-right-radius:var(--borderRadius)}.rate-limit-table td.col-new-btn{padding:3px}.rate-limit-table td.col-new-btn:focus-within{background:var(--inputColor)}.rate-limit-table .col-label{width:60%}.rate-limit-table .col-requests,.rate-limit-table .col-duration{width:15%}.rate-limit-table .col-audience{white-space:nowrap;width:1px;min-width:130px}.rate-limit-table .col-audience .selected-container{flex-wrap:nowrap}.rate-limit-table .col-action{width:1px;min-width:0;padding:0 3px}.rate-limit-table-wrapper{overflow:auto}.rate-limit-table-wrapper .rate-limit-table{min-width:550px}.export-panel{background:var(--surfaceAlt1Color);border-radius:var(--borderRadius);align-items:stretch;width:100%;height:550px;display:flex}.export-panel .export-list{gap:var(--smSpacing);scrollbar-width:thin;width:230px;min-height:0;padding:var(--smSpacing);word-break:break-word;flex-direction:column;flex-shrink:0;display:flex;overflow:auto}.export-panel .export-list .list-item{width:100%;margin:0}.export-panel .export-preview{flex-grow:1;position:relative;overflow:hidden}.export-panel .export-preview .ctrls{right:var(--smSpacing);top:calc(var(--smSpacing) - 5px);align-items:center;gap:10px;display:flex;position:absolute}.export-panel .export-preview .code-wrapper{width:100%;height:100%}.export-panel .export-preview .code-wrapper code{white-space:pre;background:0 0;border-radius:0;height:100%}.export-panel>*{border-left:1px solid var(--surfaceAlt2Color)}.export-panel>:first-child{border-top-left-radius:var(--borderRadius);border-bottom-left-radius:var(--borderRadius);border-left:0}.export-panel>:last-child{border-top-right-radius:var(--borderRadius);border-bottom-right-radius:var(--borderRadius)}@media (width<=700px){.export-panel{flex-flow:wrap;height:auto}.export-panel>*{border:0;border-top:1px solid var(--surfaceAlt2Color);border-radius:0}.export-panel>:first-child{border-top-left-radius:var(--borderRadius);border-top-right-radius:var(--borderRadius);border-top:0}.export-panel>:last-child{border-bottom-left-radius:var(--borderRadius);border-bottom-right-radius:var(--borderRadius)}.export-panel .export-list{width:100%;max-height:200px}.export-panel .export-preview{max-height:300px}}.import-change-label{min-width:65px}.collections-diff-table-title{width:100%;margin:0 0 var(--smSpacing);flex-wrap:wrap;align-items:center;gap:10px;display:flex}.collections-diff-table-title .import-change-label{font-weight:700}.collections-diff-table{color:var(--surfaceTxtHintColor);border-radius:var(--borderRadius)}.collections-diff-table tr{background:0 0}.collections-diff-table th,.collections-diff-table td{height:auto;padding:2px 10px}.collections-diff-table th{color:var(--surfaceTxtColor);padding:4px 10px}.collections-diff-table thead tr{background:var(--surfaceAlt2Color)}.collections-diff-table thead tr th{background:0 0}.collections-diff-table .changed-none-col{color:var(--surfaceTxtDisabledColor);background:var(--surfaceAlt1Color)}.collections-diff-table .changed-old-col{color:var(--surfaceTxtColor);background:var(--surfaceDangerColor)}.collections-diff-table .changed-new-col{color:var(--surfaceTxtColor);background:var(--surfaceSuccessColor)}.collections-diff-table .field-key-col{padding-left:var(--spacing);white-space:nowrap}.collections-diff-table .diff-value{white-space:break-spaces}.collections-diff-table tbody th{background:var(--surfaceAlt1Color)}.collections-diff-table-wrapper+.collections-diff-table-wrapper{margin-top:var(--spacing)}.logs-chart{text-align:center;touch-action:none;width:100%;height:0;max-height:0;transition:opacity var(--animationSpeed), max-height var(--slideAnimationSpeed), height var(--slideAnimationSpeed);flex-shrink:0;align-content:center;margin:0;display:block;position:relative;overflow:hidden;transform:translateZ(0)}.logs-chart .chart-tooltip{width:;z-index:3;white-space:nowrap;text-align:center;font-size:var(--smFontSize);border-radius:var(--borderRadius);color:var(--tooltipTxtColor);background:var(--tooltipSurfaceColor);pointer-events:none;box-shadow:var(--boxShadow);padding:5px;line-height:1;position:absolute}.logs-chart .chart-tooltip .content-primary{font-weight:700}.logs-chart .chart-tooltip .content-secondary{opacity:.6;margin:3px 0 1px;font-size:.85em}.logs-chart:has(.uplot){height:auto;max-height:180px}.logs-chart .uplot{padding-bottom:var(--smSpacing)}.logs-chart.loading{opacity:.7}.logs-chart.pending,.logs-chart.empty-list:not(.zoomed),.logs-chart.nodata:not(.nonempty-list){height:0;max-height:0}.logs-chart.zoomed .u-over+.u-axis{cursor:ew-resize}.logs-reset-zoom-ctrl{z-index:2;vertical-align:top;text-align:center;cursor:pointer;opacity:.7;font-weight:700;font-size:var(--smFontSize);border-radius:var(--borderRadius);color:var(--surfaceTxtColor);background:var(--surfaceAlt3Color);transition:opacity var(--animationSpeed);outline:0;gap:5px;padding:5px 8px;line-height:1;display:inline-block;position:absolute;top:0;left:50%;transform:translate(-50%)}.logs-reset-zoom-ctrl .content-secondary{margin-top:5px;font-size:.85em;font-weight:400}.logs-reset-zoom-ctrl:hover,.logs-reset-zoom-ctrl:active,.logs-reset-zoom-ctrl:focus-visible{opacity:1}.logs-chart-loader{z-index:1;position:absolute;top:50%;left:50%;transform:translate(-50%,-80%)}.logs-chart-container{width:100%;display:block}.logs-table .col-field-name-level{white-space:nowrap;width:1px}.logs-table .col-field-name-message{word-break:break-word}.logs-table .col-field-name-message .content-primary{-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.logs-table .col-field-name-message .content-secondary{flex-wrap:wrap;gap:10px;margin-top:7px;display:flex}.logs-table .log-request .col-field-name-message .content-primary{word-break:break-all}.logs-include-superuser-requests{width:150px}.logs-include-superuser-requests .txt{margin-top:-3px;line-height:1}.log-level-label{justify-content:center;min-width:80px;font-size:.8em;font-weight:700}.log-level-label:before{content:"";background:var(--surfaceAlt5Color);border-radius:6px;width:6px;height:6px}.log-level-label.level-0:before{background:var(--successColor)}.log-level-label.level-4:before{background:var(--warningColor)}.log-level-label.level-8:before{background:var(--dangerColor)}.page-logs .page-content{padding-top:0}.page-logs .page-header{margin:10px 0}@media (width<=750px){.page-header .logs-searchbar{order:99;width:100%}}@media (width<=600px){.page-table-wrapper .logs-table{table-layout:fixed;width:100%;min-width:0}.page-table-wrapper .logs-table thead{display:none}.page-table-wrapper .logs-table tbody tr{border-top:1px solid var(--surfaceAlt2Color);flex-wrap:wrap;width:100%;padding:10px 0;display:flex}.page-table-wrapper .logs-table tbody td{height:auto;padding:5px var(--spacing);white-space:normal;border:0;width:100%;min-height:0;display:block;background:0 0!important}.page-table-wrapper .logs-table tbody td.col-bulk-select{width:auto;padding:0 0 0 var(--spacing);align-content:center}.page-table-wrapper .logs-table tbody td.col-field-name-level{flex-grow:1;width:auto;padding-left:0}.page-table-wrapper .logs-table .log-level-label{width:100%}.page-table-wrapper .logs-table .col-field-name-message .content-secondary{gap:5px}.page-table-wrapper .logs-table .col-field-name-message .content-secondary .label{word-break:break-word}.page-table-wrapper .logs-table .col-meta{display:none}.page-table-wrapper .logs-table~.bulkbar{margin-left:auto;margin-right:auto;position:sticky;left:0;transform:none!important}}.map-container{flex-direction:column;width:100%;height:100%;min-height:200px;display:flex;position:relative}.map-box{z-index:1;flex-grow:1;width:100%;height:100%;min-height:0}.map-search{--searchWidth:400px;z-index:2;top:10px;left:calc((100% - var(--searchWidth)) / 2);height:auto;width:var(--searchWidth);opacity:.8;max-width:90%;transition:opacity var(--animationSpeed);position:absolute}.map-search input{background:inherit}.map-search .field{box-shadow:var(--boxShadow);background:var(--surfaceColor)!important}.map-search .dropdown{border:0;max-height:180px}.map-search:focus-within{opacity:1}.record-summary{flex-shrink:1;justify-content:flex-start;padding:3px 5px}.record-summary .thumb{--thumbSize:28px;border-width:1px;font-size:75%}.record-summary i{font-size:1em}.record-summary .record-preview-icon{align-content:center;height:100%;margin:0 -5px;padding:0 5px}.record-summary .record-summary .thumb{--thumbSize:24px}.record-summary .record-summary .record-summary .thumb{--thumbSize:20px}.field-content .record-summary{border-width:1px}.record-summary .record-field-view{vertical-align:top;display:inline-block}td .record-summary .field-type-text,td .record-summary .field-type-editor,td .record-summary .field-type-json{max-width:250px}.record-summary-dropdown{font-family:var(--monospaceFontFamily);font-size:var(--smFontSize);line-height:var(--smLineHeight);width:100%;max-width:350px;max-height:305px;min-width:anchor-size(width);-webkit-user-select:text;user-select:text;cursor:default}.record-summary-dropdown[popover]{position-area:bottom span-right;position-try-fallbacks:flip-block}.record-summary-dropdown .record-header{width:100%;font-family:var(--baseFontFamily);align-items:center;gap:10px;padding:5px;display:flex}.record-summary-dropdown .record-json{scrollbar-width:thin;overflow:auto}.record-file-picker-collection-select-btn{padding-left:var(--smSpacing);padding-right:calc(var(--smSpacing) - 5px);white-space:nowrap;width:27%}.record-file-picker-collection-select-btn .collection-name{white-space:nowrap;text-overflow:ellipsis;max-width:100%;overflow:hidden}.record-file-picker-thumb-select{min-width:170px}.record-file-picker-list{grid-gap:var(--smSpacing);grid-template-columns:1fr 1fr 1fr 1fr 1fr 1fr 1fr;display:grid}.record-file-picker-list .list-item{--thumbSize:100%;border-width:2px}@media only screen and (width<=700px){.record-file-picker-list{grid-template-columns:1fr 1fr 1fr 1fr 1fr}}@media only screen and (width<=450px){.record-file-picker-list{grid-template-columns:1fr 1fr 1fr}}.record-file-picker-modal{width:var(--wrapperWidth)}@media only screen and (width<=550px){.record-file-picker-modal .modal-header{flex-wrap:wrap}.record-file-picker-modal .record-file-picker-collection-select-btn{flex-grow:1}.record-file-picker-modal .records-searchbar-wrapper{flex-grow:1;order:99}.record-file-picker-modal .record-file-picker-thumb-select{min-width:100px}.record-file-picker-modal .modal-footer .btn.expanded,.record-file-picker-modal .modal-footer .btn.expanded-sm,.record-file-picker-modal .modal-footer .btn.expanded-lg{min-width:50px}}.records-picker-list{max-height:400px}.records-picker-selected-list{flex-wrap:wrap;align-items:stretch;gap:10px;max-width:100%;display:flex}.records-picker-modal .modal-header .collection-name{text-overflow:ellipsis;white-space:nowrap;flex-shrink:0;min-width:0;max-width:250px;overflow:hidden}@media only screen and (width<=550px){.records-picker-modal .modal-header{flex-wrap:wrap}.records-picker-modal .modal-header .collection-name{flex-grow:1;flex-shrink:1;max-width:80%;margin-right:auto}.records-picker-modal .searchbar{flex-grow:1;order:99}}.accordion.record-field-settings{--fieldsGap:10px;border-color:var(--surfaceAlt4Color)}.accordion.record-field-settings summary{align-items:center;gap:var(--fieldsGap);background:var(--inputColor);min-height:0;padding:4px;display:flex;container-type:inline-size}.accordion.record-field-settings summary .header-fields{gap:var(--fieldsGap);align-content:center;align-items:stretch;width:100%;display:flex}.accordion.record-field-settings summary .header-fields .header-select{max-width:150px}.accordion.record-field-settings summary .header-fields>*{position:relative}.accordion.record-field-settings summary .header-fields>*:before{content:"";background:var(--surfaceAlt4Color);flex-shrink:0;width:1px;height:auto;min-height:0;position:absolute;top:-4px;bottom:-4px;right:-5px}.accordion.record-field-settings summary .btn i.ri-settings-3-line{transition:color var(--animationSpeed), transform var(--animationSpeed)}.accordion.record-field-settings summary .sort-handle{z-index:2;text-align:left;cursor:pointer;width:30px;height:100%;color:var(--surfaceTxtHintColor);opacity:0;transition:color var(--animationSpeed), opacity var(--animationSpeed), transform var(--animationSpeed);flex-shrink:0;align-content:center;padding-left:7px;position:absolute;top:0;left:-30px;transform:translate(3px)}.accordion.record-field-settings summary .sort-handle:hover,.accordion.record-field-settings summary .sort-handle:active{opacity:1;color:var(--surfaceTxtColor);transform:translate(0)}@container (width<=480px){.accordion.record-field-settings summary .header-fields{border-radius:var(--borderRadius);background:var(--surfaceColor);flex-direction:column;gap:5px;padding:5px}.accordion.record-field-settings summary .header-fields>*{flex-grow:1;max-width:none!important}.accordion.record-field-settings summary .header-fields>*:before{content:none;display:none}}.accordion.record-field-settings:hover summary .sort-handle{opacity:1;transform:translate(0)}.accordion.record-field-settings .record-field-settings-footer{align-items:center;gap:var(--smSpacing);margin-top:var(--smSpacing);flex-wrap:wrap;display:flex}.accordion.record-field-settings .record-field-settings-footer>.field,.accordion.record-field-settings .record-field-settings-footer>.fields{width:auto}.accordion.record-field-settings summary+.record-field-settings-footer{margin-top:0}.accordion.record-field-settings .field-labels{z-index:2;pointer-events:none;-webkit-user-select:none;user-select:none;align-items:center;gap:2px;display:flex;position:absolute;top:2px;right:2px}.accordion.record-field-settings .field-labels .label{min-height:0;padding:2px 3px;font-size:.7em;line-height:1.2}.accordion.record-field-settings[open]{box-shadow:0px 0px 0px 1px var(--surfaceAlt3Color)}.accordion.record-field-settings[open] summary{outline:0}.accordion.record-field-settings[open] summary .btn i.ri-settings-3-line{color:var(--surfaceTxtColor);transform:rotate(-30deg)}.accordion.record-field-settings.deleted summary{background:var(--surfaceAlt1Color)}.accordion.record-field-settings.deleted summary .field,.accordion.record-field-settings.deleted summary .fields{background:0 0!important}.accordion.record-field-settings.deleted .header-fields{opacity:.7}.accordion.record-field-settings.deleted .header-fields>:after{background:var(--surfaceAlt2Color)}.header-select.field-select-choices-input,.header-select.collections-select{min-width:200px}.record-field-view{vertical-align:top;text-align:left;align-content:center;min-width:0;max-width:100%;display:block}.record-field-view:empty{display:none!important}.record-field-view .missing-value{vertical-align:top;color:var(--surfaceTxtDisabledColor);font-size:var(--smFontSize);align-content:center;display:inline-block}.record-field-view .missing-value:before{content:"N/A"}.record-field-view .delimiter{line-height:1;font-size:var(--smFontSize);color:var(--surfaceTxtDisabledColor)}.record-field-view .marker{line-height:1;font-size:var(--smFontSize);color:var(--surfaceTxtHintColor);align-content:center;padding-right:5px}.field-type-bool.record-field-view{min-width:auto}.field-type-bool.record-field-view .label{min-width:48px}.field-type-json.record-field-view{white-space:pre-wrap;scrollbar-width:thin;max-height:400px;overflow:auto}.field-type-json .input.code-editor{min-height:38px}.field-type-json .json-state{position:absolute;top:10px;right:10px}.field-type-geoPoint.record-field-view{white-space:nowrap}.field-type-geoPoint.record-field-input .field-list-item label:after{content:none;display:none}.more-marker{color:var(--surfaceTxtHintColor);align-self:flex-end}.field-type-select .field-select-choices-input>input{font-size:var(--smFontSize)}.field-type-select .field-select-choices-dropdown{max-height:400px}.field-type-select .field-select-choices-dropdown textarea{font-size:var(--smFontSize);max-height:300px}:is(.field-type-select,.field-type-file).record-field-view{flex-wrap:wrap;align-items:center;gap:5px;min-width:auto;display:inline-flex}.field-type-editor.record-field-view{width:100%}.record-summary .field-type-editor.record-field-view{width:auto}.field-type-editor.record-field-input .field{min-height:296px}.field-type-editor.record-field-input .loading-textarea{resize:none}.field-type-editor.record-field-input .pb-tinymce{animation:fadeIn var(--animationSpeed)}.field-type-relation.record-field-view{flex-wrap:wrap;align-items:stretch;gap:10px;display:inline-flex}.record-summary .field-type-relation.record-field-view{gap:5px}:is(.field-type-autodate,.field-type-date).record-field-view{flex-shrink:0}.hidden-field-blur{filter:blur(2.5px);transition:filter var(--animationSpeed)}.hidden-field-blur:hover,.hidden-field-blur:active,.hidden-field-blur:focus-within{filter:none;transition-delay:0s}.records-list-columns-dropdown{max-height:230px}.record-upsert-modal{width:720px}.record-upsert-modal .modal-title{min-height:var(--smBtnHeight);align-content:center}.record-upsert-modal .modal-content{scrollbar-gutter:stable}:is(.record-upsert-modal,.record-preview-modal):has(.large-modal){width:832px}.collection-upsert-modal{width:720px}.collection-upsert-modal .modal-content{scrollbar-gutter:stable both-edges}.collection-upsert-modal .modal-title{min-height:var(--smBtnHeight)}.collection-upsert-modal .modal-title .collection-name{max-width:220px}.new-collection-field-btn-wrapper{margin:var(--smSpacing) 0}.field-types-dropdown{border:2px solid var(--primaryColor);flex-flow:wrap;gap:0;margin:-5px 0}.field-types-dropdown .dropdown-item{width:25%;margin:2px 0;padding:10px}@media (width<=600px){.field-types-dropdown .dropdown-item{width:50%}}.indexes-list{flex-wrap:wrap;gap:10px;display:flex}.code-editor.collection-index-input{min-height:101px}.query-caveats-dropdown{width:300px;padding:10px}.query-caveats-dropdown ul{margin:0;padding-left:20px}.query-state{position:absolute;top:10px;right:10px}.collection-changes-list{margin:10px 0}.collection-changes-list li{line-height:var(--smLineHeight);align-content:center;margin:10px 0}.collection-changes-list li i{display:inline-block}.collection-changes-list li .label{vertical-align:baseline}.collection-changes-list .rule-content{font-family:var(--monospaceFontFamily);font-size:var(--smFontSize);line-height:var(--smLineHeight);white-space:pre-wrap;text-align:left;margin:5px 0}.collection-changes-list .rule-content.old-rule{color:var(--surfaceTxtHintColor)}.collection-changes-list .rule-content.new-rule{color:var(--successColor)}.oidc-userinfo-options{border:2px solid var(--inputFocusColor);border-radius:var(--borderRadius);padding:var(--smSpacing)}.view-query-sample-wrapper{position:relative}.view-query-sample-wrapper .loader{z-index:1;position:absolute;top:10px;right:10px}.view-query-sample code{z-index:0;border:1px solid var(--surfaceAlt2Color);background:0 0;max-height:300px}.provider-logo{--size:40px;text-align:center;width:var(--size);height:var(--size);line-height:1;font-size:var(--fontSize);color:var(--surfaceTxtDisabledColor);background:var(--surfaceAlt2Color);border-radius:var(--borderRadius);transition:background var(--animationSpeed);flex-shrink:0;justify-content:center;align-items:center;padding:8px;display:flex}.provider-logo:empty:before{content:"";font-family:var(--iconFontFamily)}.provider-logo img{width:100%;height:auto}.handle:hover .provider-logo,.handle:focus-visible .provider-logo{background:var(--surfaceAlt3Color)}.handle.active .provider-logo,.handle:active .provider-logo{transition-duration:var(--activeAnimationSpeed);background:var(--surfaceAlt4Color)}.provider-card{width:100%;min-height:var(--lgBtnHeight);border-radius:var(--borderRadius);border:1px solid var(--surfaceAlt2Color);align-items:center;gap:10px;padding:5px;display:flex}.provider-card .content{word-break:break-word;font-size:var(--fontSize);flex-grow:1;line-height:1.1}.provider-card .content p{margin:5px 0}.provider-card .content p:first-child{margin-top:0}.provider-card .content p:last-child{margin-bottom:0}.provider-card .content .primary-txt,.provider-card .content .secondary-txt{display:block}.provider-card .content .secondary-txt{color:var(--surfaceTxtHintColor);font-size:var(--smFontSize);margin:2px 0}.provider-card.handle{cursor:pointer;-webkit-user-select:none;user-select:none;transition:background var(--animationSpeed);outline:0;text-decoration:none}.provider-card.handle:hover,.provider-card.handle:focus-visible{background:var(--surfaceAlt1Color)}.provider-card.error{border-color:var(--dangerColor);background:var(--surfaceDangerColor)}.btn.add-provider-btn{font-size:var(--fontSize);line-height:var(--lineHeight);height:100%}.api-preview-content{scrollbar-width:thin;padding:calc(var(--smSpacing) + 5px) var(--spacing) calc(var(--spacing) - 5px);padding:calc(var(--spacing) - 5px) var(--spacing) calc(var(--spacing) - 5px);flex-grow:1;overflow:auto}.api-preview-content-header{width:100%;margin:0 0 calc(var(--smSpacing) + 5px);align-items:center;display:flex}.api-preview-content-header .preview-close-btn{margin:-10px 0}.api-preview-sidebar{scrollbar-width:thin;background:var(--surfaceAlt1Color);width:195px;padding:var(--inputPadding);border-right:1px solid var(--surfaceAlt2Color);flex-shrink:0;overflow:auto}.api-preview-nav{flex-direction:column;gap:5px;display:flex}.api-preview-nav hr{margin:var(--inputPadding) 0}.api-preview-nav .nav-item{width:100%;padding:5px var(--inputPadding);cursor:pointer;font-size:var(--lgFontSize);min-height:var(--btnHeight);border-radius:var(--borderRadius);color:var(--surfaceTxtHintColor);transition:color var(--animationSpeed), background var(--animationSpeed);outline:0;align-items:center;gap:5px;display:flex}.api-preview-nav .nav-item:hover,.api-preview-nav .nav-item:focus-visible,.api-preview-nav .nav-item.active{background:var(--surfaceAlt2Color)}.api-preview-nav .nav-item.active{color:var(--surfaceTxtColor)}.api-preview-nav .nav-item:active{background:var(--surfaceAlt3Color);transition-duration:var(--activeAnimationSpeed)}.api-preview-nav .nav-item[disabled]{cursor:not-allowed;color:var(--surfaceTxtDisabledColor);background:0 0}.api-preview-alert{margin:var(--smSpacing) 0;align-items:center;gap:10px;display:flex}.api-preview-alert .method{flex-shrink:0;font-weight:700}.api-preview-alert .path{flex-grow:1}.api-preview-alert .extra{color:var(--surfaceTxtHintColor);text-align:right;max-width:180px;margin:-3px 0 -3px auto;font-size:.85em}.api-preview-table{width:100%;margin:var(--smSpacing) 0}code.filter-op{text-align:center;min-width:30px}.api-preview-modal{width:900px;max-width:95%}.api-preview-modal .modal-content{align-items:stretch;padding:0;display:flex}.api-preview-modal .modal-content:before,.api-preview-modal .modal-content:after{content:none;display:none}@media (width<=550px){.api-preview-modal .modal-content{flex-direction:column}.api-preview-modal .api-preview-content>.content{min-width:550px}.api-preview-modal .api-preview-sidebar{border:0;border-bottom:2px solid var(--surfaceAlt3Color);width:100%;max-height:150px}}.color-picker{border-radius:var(--borderRadius);background:0 0;background:var(--surfaceColor);align-items:stretch;gap:3px;width:100%;min-height:28px;padding:3px;display:flex}.color-picker .predefined-colors-btn{padding:0 3px}.color-picker .color-picker-input-wrapper{flex-grow:1;height:auto;display:block;position:relative}.color-picker .color-picker-input-wrapper input[type=color]{-webkit-appearance:none;cursor:cell;border-radius:var(--borderRadius);border:0;width:100%;height:100%;margin:0;padding:0}.color-picker .color-picker-input-wrapper input[type=color]::-webkit-color-swatch-wrapper{padding:0}.color-picker .color-picker-input-wrapper input[type=color]::-webkit-color-swatch{border:none;border-radius:0}.color-picker .color-picker-input-wrapper .result{text-align:center;width:100%;height:100%;font-size:.85rem;line-height:1;font-family:var(--monospaceFontFamily);pointer-events:none;white-space:nowrap;text-overflow:ellipsis;align-content:center;padding:0 2px;position:absolute;top:0;left:0;overflow:hidden}.predefined-colors-list{-webkit-user-select:none;user-select:none;flex-wrap:wrap;gap:5px;display:flex}.predefined-colors-list .color{cursor:pointer;border-radius:var(--borderRadius);width:22px;height:22px;transition:opacity var(--animationSpeed);flex-shrink:0}.predefined-colors-list .color:focus-visible{outline-color:var(--surfaceAlt5Color)}.predefined-colors-list .color:hover,.predefined-colors-list .color:active{opacity:.8}.predefined-colors-list .color:active{opacity:.7;transition-duration:var(--activeAnimationSpeed)}.predefined-colors-dropdown{width:auto;min-width:25px;max-width:170px}.field .color-picker{width:auto;margin:4px}.field label~.color-picker{margin-top:6px}.modal.collections-overview-modal{width:1500px;max-width:90%;min-height:90%;max-height:90%;transform:translateY(3px)}.modal.collections-overview-modal[data-modal-state=open]{transform:translateY(0)}@starting-style{.modal.collections-overview-modal[data-modal-state=open]{transform:translateY(3px)}}.modal.collections-overview-modal .modal-header{padding-top:var(--smSpacing)}.modal.collections-overview-modal .modal-content.erd-tab{align-items:stretch;padding:0;display:flex}.modal.collections-overview-modal .modal-content.erd-tab:before,.modal.collections-overview-modal .modal-content.erd-tab:after{content:none;display:none}.modal.collections-overview-modal .modal-content.rules-tab{scrollbar-gutter:stable;padding-top:0}.modal.collections-overview-modal .rules-table{word-break:break-word;min-width:700px;margin-top:calc(var(--spacing) - 5px)}.modal.collections-overview-modal .rules-table .collection-name{text-overflow:ellipsis;width:200px;overflow:hidden}.modal.collections-overview-modal .rules-table thead{top:-3px}.modal.collections-overview-modal .rule-btns{gap:5px;width:100%;display:flex}.modal.collections-overview-modal .rule-btns .btn{flex:1 1 0;padding:5px}.modal.collections-overview-modal .rule-btns .btn.outline{padding:3px}@media (width<=700px){.modal.collections-overview-modal{max-width:95%;min-height:95%;max-height:95%}.modal.collections-overview-modal .rules-table .collection-name{max-width:130px}}.erd-table-row{width:100%;min-height:var(--smBtnHeight);background:var(--surfaceColor);color:var(--surfaceTxtColor);border:0;border-top:1px solid var(--surfaceAlt2Color);align-items:center;gap:5px;padding:2px 5px;font-weight:400;display:flex}.erd-table-row .txt-ellipsis{min-width:0}.erd-table-row.header{color:inherit;background:inherit;text-align:center;border:0;justify-content:center;font-weight:700}.erd-table-row.type-relation{background:var(--surfaceAlt1Color)}.erd-table-row:first-child,.erd-table-row.header+.erd-table-row{border-top-left-radius:var(--borderRadius);border-top-right-radius:var(--borderRadius);border-top:0}.erd-table-row:last-child{border-bottom-left-radius:var(--borderRadius);border-bottom-right-radius:var(--borderRadius)}.erd-table-row i{font-size:1em}.erd-table-row .field-icon{color:var(--surfaceTxtHintColor)}.erd-table-row .field-name{vertical-align:top;white-space:nowrap;text-overflow:ellipsis;flex-shrink:1;min-width:10px;max-width:100%;display:inline-block;overflow:hidden}.erd-table-row .field-hidden-label{min-height:0;padding:3px;font-size:.78em;line-height:1}.erd-table-row .meta{white-space:nowrap;color:var(--surfaceTxtHintColor);flex-grow:0;flex-shrink:0;margin-left:auto;font-size:.9em;display:flex}.erd-table{z-index:2;text-align:left;-webkit-user-select:none;user-select:none;word-break:break-word;background:var(--surfaceAlt4Color);width:200px;color:var(--surfaceTxtHintColor);border-radius:var(--borderRadius);font-size:var(--smFontSize);line-height:var(--smLineHeight);transition:opacity var(--animationSpeed), background var(--animationSpeed), color var(--animationSpeed), box-shadow var(--animationSpeed);padding:2px;display:block;position:relative}.erd-table.active{color:var(--surfaceTxtColor);background:var(--surfaceAlt5Color)}.erd-table.system{color:var(--dangerTxtColor);background:var(--dangerColor)}.erd-table.active,.erd-table:hover{box-shadow:var(--boxShadow)}.erd{cursor:grab;background-image:radial-gradient(var(--surfaceAlt2Color) 1px, transparent 1px);border-radius:var(--borderRadius);touch-action:none;background-size:20px 20px;width:100%;height:auto;min-height:300px;display:block;position:relative;overflow:hidden}.erd .erd-area{-webkit-user-select:none;user-select:none;transform-origin:0 0;position:relative;top:0;left:0}.erd .erd-table{position:absolute;top:0;left:0}.erd .erd-paths{--pathColor:var(--surfaceAlt2Color);z-index:0;pointer-events:none;width:2000px;height:8000px;position:absolute;top:0;left:0}.erd .paths-group{fill:none;stroke-width:2px;stroke:var(--pathColor)}.erd .erd-paths.front{--pathColor:var(--surfaceTxtDisabledColor);z-index:2}.erd .erd-paths.front .active-from{stroke:var(--surfaceTxtHintColor)}.erd .erd-nav{z-index:3;right:var(--smSpacing);bottom:var(--smSpacing);flex-direction:column;align-items:center;gap:10px;display:flex;position:absolute}.erd.updating .erd-paths,.erd.updating .erd-table{opacity:0}.erd.panning{cursor:grabbing}.erd.active .erd-table{opacity:.7}.erd.active .erd-table.active{opacity:1}.erd.active .erd-paths.back{opacity:.3}.app.hide-controls .btn-collection-settings,.app.hide-controls .sidebar-content.new-collection,.app.hide-controls .settings-sidebar [data-group=Sync]{display:none}.field.sql-console-field .input{resize:vertical;height:250px;min-height:150px;max-height:400px}@media (height<=650px){.field.sql-console-field .input{height:150px}}.sql-console-history-dropdown{width:450px}.sql-console-history-dropdown.no-items{width:300px}.sql-console-history-dropdown .dropdown-item{font-size:.9em;line-height:1.2;font-family:var(--monospaceFontFamily);gap:5px;padding:5px}.sql-console-history-dropdown .dropdown-item .query{-webkit-line-clamp:3;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.leaflet-pane,.leaflet-tile,.leaflet-marker-icon,.leaflet-marker-shadow,.leaflet-tile-container,.leaflet-pane>svg,.leaflet-pane>canvas,.leaflet-zoom-box,.leaflet-image-layer,.leaflet-layer{position:absolute;top:0;left:0}.leaflet-container{overflow:hidden}.leaflet-tile,.leaflet-marker-icon,.leaflet-marker-shadow{-webkit-user-select:none;user-select:none;-webkit-user-drag:none}.leaflet-tile::selection{background:0 0}.leaflet-safari .leaflet-tile{image-rendering:-webkit-optimize-contrast}.leaflet-safari .leaflet-tile-container{-webkit-transform-origin:0 0;width:1600px;height:1600px}.leaflet-marker-icon,.leaflet-marker-shadow{display:block}.leaflet-container .leaflet-overlay-pane svg{max-width:none!important;max-height:none!important}.leaflet-container .leaflet-marker-pane img,.leaflet-container .leaflet-shadow-pane img,.leaflet-container .leaflet-tile-pane img,.leaflet-container img.leaflet-image-layer,.leaflet-container .leaflet-tile{width:auto;padding:0;max-width:none!important;max-height:none!important}.leaflet-container img.leaflet-tile{mix-blend-mode:plus-lighter}.leaflet-container.leaflet-touch-zoom{-ms-touch-action:pan-x pan-y;touch-action:pan-x pan-y}.leaflet-container.leaflet-touch-drag{-ms-touch-action:pinch-zoom;touch-action:none;touch-action:pinch-zoom}.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom{-ms-touch-action:none;touch-action:none}.leaflet-container{-webkit-tap-highlight-color:transparent}.leaflet-container a{-webkit-tap-highlight-color:#33b5e566}.leaflet-tile{filter:inherit;visibility:hidden}.leaflet-tile-loaded{visibility:inherit}.leaflet-zoom-box{box-sizing:border-box;z-index:800;width:0;height:0}.leaflet-overlay-pane svg{-moz-user-select:none}.leaflet-pane{z-index:400}.leaflet-tile-pane{z-index:200}.leaflet-overlay-pane{z-index:400}.leaflet-shadow-pane{z-index:500}.leaflet-marker-pane{z-index:600}.leaflet-tooltip-pane{z-index:650}.leaflet-popup-pane{z-index:700}.leaflet-map-pane canvas{z-index:100}.leaflet-map-pane svg{z-index:200}.leaflet-vml-shape{width:1px;height:1px}.lvml{behavior:url(#default#VML);display:inline-block;position:absolute}.leaflet-control{z-index:800;pointer-events:visiblePainted;pointer-events:auto;position:relative}.leaflet-top,.leaflet-bottom{z-index:1000;pointer-events:none;position:absolute}.leaflet-top{top:0}.leaflet-right{right:0}.leaflet-bottom{bottom:0}.leaflet-left{left:0}.leaflet-control{float:left;clear:both}.leaflet-right .leaflet-control{float:right}.leaflet-top .leaflet-control{margin-top:10px}.leaflet-bottom .leaflet-control{margin-bottom:10px}.leaflet-left .leaflet-control{margin-left:10px}.leaflet-right .leaflet-control{margin-right:10px}.leaflet-fade-anim .leaflet-popup{opacity:0;transition:opacity .2s linear}.leaflet-fade-anim .leaflet-map-pane .leaflet-popup{opacity:1}.leaflet-zoom-animated{transform-origin:0 0}svg.leaflet-zoom-animated{will-change:transform}.leaflet-zoom-anim .leaflet-zoom-animated{-webkit-transition:-webkit-transform .25s cubic-bezier(0,0,.25,1);-moz-transition:-moz-transform .25s cubic-bezier(0,0,.25,1);transition:transform .25s cubic-bezier(0,0,.25,1)}.leaflet-zoom-anim .leaflet-tile,.leaflet-pan-anim .leaflet-tile{transition:none}.leaflet-zoom-anim .leaflet-zoom-hide{visibility:hidden}.leaflet-interactive{cursor:pointer}.leaflet-grab{cursor:-webkit-grab;cursor:-moz-grab;cursor:grab}.leaflet-crosshair,.leaflet-crosshair .leaflet-interactive{cursor:crosshair}.leaflet-popup-pane,.leaflet-control{cursor:auto}.leaflet-dragging .leaflet-grab,.leaflet-dragging .leaflet-grab .leaflet-interactive,.leaflet-dragging .leaflet-marker-draggable{cursor:move;cursor:-webkit-grabbing;cursor:-moz-grabbing;cursor:grabbing}.leaflet-marker-icon,.leaflet-marker-shadow,.leaflet-image-layer,.leaflet-pane>svg path,.leaflet-tile-container{pointer-events:none}.leaflet-marker-icon.leaflet-interactive,.leaflet-image-layer.leaflet-interactive,.leaflet-pane>svg path.leaflet-interactive,svg.leaflet-image-layer.leaflet-interactive path{pointer-events:visiblePainted;pointer-events:auto}.leaflet-container{outline-offset:1px;background:#ddd}.leaflet-container a{color:#0078a8}.leaflet-zoom-box{background:#ffffff80;border:2px dotted #38f}.leaflet-container{font-family:Helvetica Neue,Arial,Helvetica,sans-serif;font-size:.75rem;line-height:1.5}.leaflet-bar{border-radius:4px;box-shadow:0 1px 5px #000000a6}.leaflet-bar a{text-align:center;color:#000;background-color:#fff;border-bottom:1px solid #ccc;width:26px;height:26px;line-height:26px;text-decoration:none;display:block}.leaflet-bar a,.leaflet-control-layers-toggle{background-position:50%;background-repeat:no-repeat;display:block}.leaflet-bar a:hover,.leaflet-bar a:focus{background-color:#f4f4f4}.leaflet-bar a:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.leaflet-bar a:last-child{border-bottom:none;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.leaflet-bar a.leaflet-disabled{cursor:default;color:#bbb;background-color:#f4f4f4}.leaflet-touch .leaflet-bar a{width:30px;height:30px;line-height:30px}.leaflet-touch .leaflet-bar a:first-child{border-top-left-radius:2px;border-top-right-radius:2px}.leaflet-touch .leaflet-bar a:last-child{border-bottom-right-radius:2px;border-bottom-left-radius:2px}.leaflet-control-zoom-in,.leaflet-control-zoom-out{text-indent:1px;font:700 18px Lucida Console,Monaco,monospace}.leaflet-touch .leaflet-control-zoom-in,.leaflet-touch .leaflet-control-zoom-out{font-size:22px}.leaflet-control-layers{background:#fff;border-radius:5px;box-shadow:0 1px 5px #0006}.leaflet-control-layers-toggle{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAQAAAADQ4RFAAACf0lEQVR4AY1UM3gkARTePdvdoTxXKc+qTl3aU5U6b2Kbkz3Gtq3Zw6ziLGNPzrYx7946Tr6/ee/XeCQ4D3ykPtL5tHno4n0d/h3+xfuWHGLX81cn7r0iTNzjr7LrlxCqPtkbTQEHeqOrTy4Yyt3VCi/IOB0v7rVC7q45Q3Gr5K6jt+3Gl5nCoDD4MtO+j96Wu8atmhGqcNGHObuf8OM/x3AMx38+4Z2sPqzCxRFK2aF2e5Jol56XTLyggAMTL56XOMoS1W4pOyjUcGGQdZxU6qRh7B9Zp+PfpOFlqt0zyDZckPi1ttmIp03jX8gyJ8a/PG2yutpS/Vol7peZIbZcKBAEEheEIAgFbDkz5H6Zrkm2hVWGiXKiF4Ycw0RWKdtC16Q7qe3X4iOMxruonzegJzWaXFrU9utOSsLUmrc0YjeWYjCW4PDMADElpJSSQ0vQvA1Tm6/JlKnqFs1EGyZiFCqnRZTEJJJiKRYzVYzJck2Rm6P4iH+cmSY0YzimYa8l0EtTODFWhcMIMVqdsI2uiTvKmTisIDHJ3od5GILVhBCarCfVRmo4uTjkhrhzkiBV7SsaqS+TzrzM1qpGGUFt28pIySQHR6h7F6KSwGWm97ay+Z+ZqMcEjEWebE7wxCSQwpkhJqoZA5ivCdZDjJepuJ9IQjGGUmuXJdBFUygxVqVsxFsLMbDe8ZbDYVCGKxs+W080max1hFCarCfV+C1KATwcnvE9gRRuMP2prdbWGowm1KB1y+zwMMENkM755cJ2yPDtqhTI6ED1M/82yIDtC/4j4BijjeObflpO9I9MwXTCsSX8jWAFeHr05WoLTJ5G8IQVS/7vwR6ohirYM7f6HzYpogfS3R2OAAAAAElFTkSuQmCC);width:36px;height:36px}.leaflet-retina .leaflet-control-layers-toggle{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADQAAAA0CAQAAABvcdNgAAAEsklEQVR4AWL4TydIhpZK1kpWOlg0w3ZXP6D2soBtG42jeI6ZmQTHzAxiTbSJsYLjO9HhP+WOmcuhciVnmHVQcJnp7DFvScowZorad/+V/fVzMdMT2g9Cv9guXGv/7pYOrXh2U+RRR3dSd9JRx6bIFc/ekqHI29JC6pJ5ZEh1yWkhkbcFeSjxgx3L2m1cb1C7bceyxA+CNjT/Ifff+/kDk2u/w/33/IeCMOSaWZ4glosqT3DNnNZQ7Cs58/3Ce5HL78iZH/vKVIaYlqzfdLu8Vi7dnvUbEza5Idt36tquZFldl6N5Z/POLof0XLK61mZCmJSWjVF9tEjUluu74IUXvgttuVIHE7YxSkaYhJZam7yiM9Pv82JYfl9nptxZaxMJE4YSPty+vF0+Y2up9d3wwijfjZbabqm/3bZ9ecKHsiGmRflnn1MW4pjHf9oLufyn2z3y1D6n8g8TZhxyzipLNPnAUpsOiuWimg52psrTZYnOWYNDTMuWBWa0tJb4rgq1UvmutpaYEbZlwU3CLJm/ayYjHW5/h7xWLn9Hh1vepDkyf7dE7MtT5LR4e7yYpHrkhOUpEfssBLq2pPhAqoSWKUkk7EDqkmK6RrCEzqDjhNDWNE+XSMvkJRDWlZTmCW0l0PHQGRZY5t1L83kT0Y3l2SItk5JAWHl2dCOBm+fPu3fo5/3v61RMCO9Jx2EEYYhb0rmNQMX/vm7gqOEJLcXTGw3CAuRNeyaPWwjR8PRqKQ1PDA/dpv+on9Shox52WFnx0KY8onHayrJzm87i5h9xGw/tfkev0jGsQizqezUKjk12hBMKJ4kbCqGPVNXudyyrShovGw5CgxsRICxF6aRmSjlBnHRzg7Gx8fKqEubI2rahQYdR1YgDIRQO7JvQyD52hoIQx0mxa0ODtW2Iozn1le2iIRdzwWewedyZzewidueOGqlsn1MvcnQpuVwLGG3/IR1hIKxCjelIDZ8ldqWz25jWAsnldEnK0Zxro19TGVb2ffIZEsIO89EIEDvKMPrzmBOQcKQ+rroye6NgRRxqR4U8EAkz0CL6uSGOm6KQCdWjvjRiSP1BPalCRS5iQYiEIvxuBMJEWgzSoHADcVMuN7IuqqTeyUPq22qFimFtxDyBBJEwNyt6TM88blFHao/6tWWhuuOM4SAK4EI4QmFHA+SEyWlp4EQoJ13cYGzMu7yszEIBOm2rVmHUNqwAIQabISNMRstmdhNWcFLsSm+0tjJH1MdRxO5Nx0WDMhCtgD6OKgZeljJqJKc9po8juskR9XN0Y1lZ3mWjLR9JCO1jRDMd0fpYC2VnvjBSEFg7wBENc0R9HFlb0xvF1+TBEpF68d+DHR6IOWVv2BECtxo46hOFUBd/APU57WIoEwJhIi2CdpyZX0m93BZicktMj1AS9dClteUFAUNUIEygRZCtik5zSxI9MubTBH1GOiHsiLJ3OCoSZkILa9PxiN0EbvhsAo8tdAf9Seepd36lGWHmtNANTv5Jd0z4QYyeo/UEJqxKRpg5LZx6btLPsOaEmdMyxYdlc8LMaJnikDlhclqmPiQnTEpLUIZEwkRagjYkEibQErwhkTAKCLQEbUgkzJQWc/0PstHHcfEdQ+UAAAAASUVORK5CYII=);background-size:26px 26px}.leaflet-touch .leaflet-control-layers-toggle{width:44px;height:44px}.leaflet-control-layers .leaflet-control-layers-list,.leaflet-control-layers-expanded .leaflet-control-layers-toggle{display:none}.leaflet-control-layers-expanded .leaflet-control-layers-list{display:block;position:relative}.leaflet-control-layers-expanded{color:#333;background:#fff;padding:6px 10px 6px 6px}.leaflet-control-layers-scrollbar{padding-right:5px;overflow:hidden scroll}.leaflet-control-layers-selector{margin-top:2px;position:relative;top:1px}.leaflet-control-layers label{font-size:1.08333em;display:block}.leaflet-control-layers-separator{border-top:1px solid #ddd;height:0;margin:5px -10px 5px -6px}.leaflet-default-icon-path{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAApCAYAAADAk4LOAAAFgUlEQVR4Aa1XA5BjWRTN2oW17d3YaZtr2962HUzbDNpjszW24mRt28p47v7zq/bXZtrp/lWnXr337j3nPCe85NcypgSFdugCpW5YoDAMRaIMqRi6aKq5E3YqDQO3qAwjVWrD8Ncq/RBpykd8oZUb/kaJutow8r1aP9II0WmLKLIsJyv1w/kqw9Ch2MYdB++12Onxee/QMwvf4/Dk/Lfp/i4nxTXtOoQ4pW5Aj7wpici1A9erdAN2OH64x8OSP9j3Ft3b7aWkTg/Fm91siTra0f9on5sQr9INejH6CUUUpavjFNq1B+Oadhxmnfa8RfEmN8VNAsQhPqF55xHkMzz3jSmChWU6f7/XZKNH+9+hBLOHYozuKQPxyMPUKkrX/K0uWnfFaJGS1QPRtZsOPtr3NsW0uyh6NNCOkU3Yz+bXbT3I8G3xE5EXLXtCXbbqwCO9zPQYPRTZ5vIDXD7U+w7rFDEoUUf7ibHIR4y6bLVPXrz8JVZEql13trxwue/uDivd3fkWRbS6/IA2bID4uk0UpF1N8qLlbBlXs4Ee7HLTfV1j54APvODnSfOWBqtKVvjgLKzF5YdEk5ewRkGlK0i33Eofffc7HT56jD7/6U+qH3Cx7SBLNntH5YIPvODnyfIXZYRVDPqgHtLs5ABHD3YzLuespb7t79FY34DjMwrVrcTuwlT55YMPvOBnRrJ4VXTdNnYug5ucHLBjEpt30701A3Ts+HEa73u6dT3FNWwflY86eMHPk+Yu+i6pzUpRrW7SNDg5JHR4KapmM5Wv2E8Tfcb1HoqqHMHU+uWDD7zg54mz5/2BSnizi9T1Dg4QQXLToGNCkb6tb1NU+QAlGr1++eADrzhn/u8Q2YZhQVlZ5+CAOtqfbhmaUCS1ezNFVm2imDbPmPng5wmz+gwh+oHDce0eUtQ6OGDIyR0uUhUsoO3vfDmmgOezH0mZN59x7MBi++WDL1g/eEiU3avlidO671bkLfwbw5XV2P8Pzo0ydy4t2/0eu33xYSOMOD8hTf4CrBtGMSoXfPLchX+J0ruSePw3LZeK0juPJbYzrhkH0io7B3k164hiGvawhOKMLkrQLyVpZg8rHFW7E2uHOL888IBPlNZ1FPzstSJM694fWr6RwpvcJK60+0HCILTBzZLFNdtAzJaohze60T8qBzyh5ZuOg5e7uwQppofEmf2++DYvmySqGBuKaicF1blQjhuHdvCIMvp8whTTfZzI7RldpwtSzL+F1+wkdZ2TBOW2gIF88PBTzD/gpeREAMEbxnJcaJHNHrpzji0gQCS6hdkEeYt9DF/2qPcEC8RM28Hwmr3sdNyht00byAut2k3gufWNtgtOEOFGUwcXWNDbdNbpgBGxEvKkOQsxivJx33iow0Vw5S6SVTrpVq11ysA2Rp7gTfPfktc6zhtXBBC+adRLshf6sG2RfHPZ5EAc4sVZ83yCN00Fk/4kggu40ZTvIEm5g24qtU4KjBrx/BTTH8ifVASAG7gKrnWxJDcU7x8X6Ecczhm3o6YicvsLXWfh3Ch1W0k8x0nXF+0fFxgt4phz8QvypiwCCFKMqXCnqXExjq10beH+UUA7+nG6mdG/Pu0f3LgFcGrl2s0kNNjpmoJ9o4B29CMO8dMT4Q5ox8uitF6fqsrJOr8qnwNbRzv6hSnG5wP+64C7h9lp30hKNtKdWjtdkbuPA19nJ7Tz3zR/ibgARbhb4AlhavcBebmTHcFl2fvYEnW0ox9xMxKBS8btJ+KiEbq9zA4RthQXDhPa0T9TEe69gWupwc6uBUphquXgf+/FrIjweHQS4/pduMe5ERUMHUd9xv8ZR98CxkS4F2n3EUrUZ10EYNw7BWm9x1GiPssi3GgiGRDKWRYZfXlON+dfNbM+GgIwYdwAAAAASUVORK5CYII=)}.leaflet-container .leaflet-control-attribution{background:#fffc;margin:0}.leaflet-control-attribution,.leaflet-control-scale-line{color:#333;padding:0 5px;line-height:1.4}.leaflet-control-attribution a{text-decoration:none}.leaflet-control-attribution a:hover,.leaflet-control-attribution a:focus{text-decoration:underline}.leaflet-attribution-flag{width:1em;height:.6669em;vertical-align:baseline!important;display:inline!important}.leaflet-left .leaflet-control-scale{margin-left:5px}.leaflet-bottom .leaflet-control-scale{margin-bottom:5px}.leaflet-control-scale-line{white-space:nowrap;box-sizing:border-box;text-shadow:1px 1px #fff;background:#fffc;border:2px solid #777;border-top:none;padding:2px 5px 1px;line-height:1.1}.leaflet-control-scale-line:not(:first-child){border-top:2px solid #777;border-bottom:none;margin-top:-2px}.leaflet-control-scale-line:not(:first-child):not(:last-child){border-bottom:2px solid #777}.leaflet-touch .leaflet-control-attribution,.leaflet-touch .leaflet-control-layers,.leaflet-touch .leaflet-bar{box-shadow:none}.leaflet-touch .leaflet-control-layers,.leaflet-touch .leaflet-bar{background-clip:padding-box;border:2px solid #0003}.leaflet-popup{text-align:center;margin-bottom:20px;position:absolute}.leaflet-popup-content-wrapper{text-align:left;border-radius:12px;padding:1px}.leaflet-popup-content{min-height:1px;margin:13px 24px 13px 20px;font-size:1.08333em;line-height:1.3}.leaflet-popup-content p{margin:1.3em 0}.leaflet-popup-tip-container{pointer-events:none;width:40px;height:20px;margin-top:-1px;margin-left:-20px;position:absolute;left:50%;overflow:hidden}.leaflet-popup-tip{pointer-events:auto;width:17px;height:17px;margin:-10px auto 0;padding:1px;transform:rotate(45deg)}.leaflet-popup-content-wrapper,.leaflet-popup-tip{color:#333;background:#fff;box-shadow:0 3px 14px #0006}.leaflet-container a.leaflet-popup-close-button{text-align:center;color:#757575;background:0 0;border:none;width:24px;height:24px;font:16px/24px Tahoma,Verdana,sans-serif;text-decoration:none;position:absolute;top:0;right:0}.leaflet-container a.leaflet-popup-close-button:hover,.leaflet-container a.leaflet-popup-close-button:focus{color:#585858}.leaflet-popup-scrolled{overflow:auto}.leaflet-oldie .leaflet-popup-content-wrapper{-ms-zoom:1}.leaflet-oldie .leaflet-popup-tip{-ms-filter:"progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";width:24px;filter:progid:DXImageTransform.Microsoft.Matrix(M11=.707107, M12=.707107, M21=-.707107, M22=.707107);margin:0 auto}.leaflet-oldie .leaflet-control-zoom,.leaflet-oldie .leaflet-control-layers,.leaflet-oldie .leaflet-popup-content-wrapper,.leaflet-oldie .leaflet-popup-tip{border:1px solid #999}.leaflet-div-icon{background:#fff;border:1px solid #666}.leaflet-tooltip{color:#222;white-space:nowrap;-webkit-user-select:none;user-select:none;pointer-events:none;background-color:#fff;border:1px solid #fff;border-radius:3px;padding:6px;position:absolute;box-shadow:0 1px 3px #0006}.leaflet-tooltip.leaflet-interactive{cursor:pointer;pointer-events:auto}.leaflet-tooltip-top:before,.leaflet-tooltip-bottom:before,.leaflet-tooltip-left:before,.leaflet-tooltip-right:before{pointer-events:none;content:"";background:0 0;border:6px solid #0000;position:absolute}.leaflet-tooltip-bottom{margin-top:6px}.leaflet-tooltip-top{margin-top:-6px}.leaflet-tooltip-bottom:before,.leaflet-tooltip-top:before{margin-left:-6px;left:50%}.leaflet-tooltip-top:before{border-top-color:#fff;margin-bottom:-12px;bottom:0}.leaflet-tooltip-bottom:before{border-bottom-color:#fff;margin-top:-12px;margin-left:-6px;top:0}.leaflet-tooltip-left{margin-left:-6px}.leaflet-tooltip-right{margin-left:6px}.leaflet-tooltip-left:before,.leaflet-tooltip-right:before{margin-top:-6px;top:50%}.leaflet-tooltip-left:before{border-left-color:#fff;margin-right:-12px;right:0}.leaflet-tooltip-right:before{border-right-color:#fff;margin-left:-12px;left:0}@media print{.leaflet-control{-webkit-print-color-adjust:exact;print-color-adjust:exact}} diff --git a/ui/dist/assets/index-DoeyJa3f.js b/ui/dist/assets/index-VdywtJWb.js similarity index 96% rename from ui/dist/assets/index-DoeyJa3f.js rename to ui/dist/assets/index-VdywtJWb.js index 5c4ce4d418..b96b014e01 100644 --- a/ui/dist/assets/index-DoeyJa3f.js +++ b/ui/dist/assets/index-VdywtJWb.js @@ -1,11 +1,11 @@ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./docsList-DsIHfo2q.js","./expandInfo-CJ9aeAaN.js","./fieldsInfo-CiLcXgNq.js","./docsView-oyuvqZP8.js","./docsCreate-Ap21j9FE.js","./docsUpdate-DAnNYWFv.js","./docsListAuthMethods-CYETXzX7.js","./docsAuthWithPassword-NXiq7pZI.js","./docsAuthWithOAuth2-qI6si9uJ.js","./docsAuthWithOTP-75iz1Xmg.js","./docsAuthRefresh-Cq3xTY6M.js"])))=>i.map(i=>d[i]); var e=Object.create,n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.getPrototypeOf,o=Object.prototype.hasOwnProperty,s=(e,n)=>()=>(n||(e((n={exports:{}}).exports,n),e=null),n.exports),c=(e,a,s,c)=>{if(a&&typeof a==`object`||typeof a==`function`)for(var l=i(a),u=0,d=l.length,f;ua[e]).bind(null,f),enumerable:!(c=r(a,f))||c.enumerable});return e},l=(r,i,s)=>(s=r==null?{}:e(a(r)),c(i||!r||!r.__esModule||!o.call(r,`default`)?n(s,`default`,{value:r,enumerable:!0}):s,r));(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))r(e);new MutationObserver(e=>{for(let n of e)if(n.type===`childList`)for(let e of n.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&r(e)}).observe(document,{childList:!0,subtree:!0});function n(e){let n={};return e.integrity&&(n.integrity=e.integrity),e.referrerPolicy&&(n.referrerPolicy=e.referrerPolicy),n.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,n}function r(e){if(e.ep)return;e.ep=!0;let r=n(e);fetch(e.href,r)}})();var u=`abcdefghijklmnopqrstuvwxyz0123456789`,d=store({hash:window.location.hash});window.addEventListener(`hashchange`,()=>{d.hash=window.location.hash}),Prism.languages.pbrule={string:Prism.languages.js.string,number:Prism.languages.js.number,function:Prism.languages.js.function,boolean:/\b(?:true|false)\b/i,constant:/\b(?:null)\b/i,comment:{pattern:/\/\/.*/,greedy:!0},italic:/_via_|\:\w+/,keyword:/&&|\|\||\??(?:!~|!=|>=|<=|=|~|>|>|<)(?=[@\w\s]|$)/};var f={isObject(e){return typeof e==`object`&&!!e&&e.constructor===Object},isEmpty(e){return e==null||e===``||Array.isArray(e)&&e.length===0||typeof e==`object`&&app.utils.isEmptyObject(e)},isEmptyObject(e){for(let n in e)return!1;return!0},toArray(e,n=!1){return Array.isArray(e)?e.slice():(n||!f.isEmpty(e))&&e!==void 0?[e]:[]},removeByValue(e,n){if(!Array.isArray(e)){console.warn(`[removeByValue] not an array:`,e);return}for(let r=e.length-1;r>=0;r--)if(e[r]==n){e.splice(r,1);break}},removeByKey(e,n,r){if(!Array.isArray(e)){console.warn(`[removeByKey] not an array:`,e);return}for(let i in e)if(e[i][n]==r){e.splice(i,1);break}},pushUnique(e,n){if(!Array.isArray(e)){console.warn(`[pushUnique] not an array:`,e);return}e.includes(n)||e.push(n)},mergeUnique(e,n){for(let r of n)app.utils.pushUnique(e,r);return e},pushOrReplaceObject(e,n,r=`id`){for(let i=e.length-1;i>=0;i--)if(e[i][r]==n[r]){e[i]=n;return}e.push(n)},filterDuplicatesByKey(e,n=`id`){e=Array.isArray(e)?e:[];let r={};for(let i of e)r[i[n]]=i;return Object.values(r)},filterRedactedProps(e,n=`******`){let r=JSON.parse(JSON.stringify(e||{}));for(let e in r)typeof r[e]==`object`&&r[e]!==null?r[e]=f.filterRedactedProps(r[e],n):r[e]===n&&delete r[e];return r},getByPath(e,n,r=null,i=`.`){let a=e||{},o=(n||``).split(i);for(let e of o){if(!f.isObject(a)&&!Array.isArray(a)||a[e]===void 0)return r;a=a[e]}return a},setByPath(e,n,r,i=`.`){if(typeof e!=`object`||!e){console.warn(`setByPath: data not an object or array.`);return}let a=e,o=n.split(i),s=o.pop();for(let e of o)(!f.isObject(a)&&!Array.isArray(a)||!f.isObject(a[e])&&!Array.isArray(a[e]))&&(a[e]={}),a=a[e];a[s]=r},deleteByPath(e,n,r=`.`){let i=e||{},a=(n||``).split(r),o=a.pop();for(let e of a)(!f.isObject(i)&&!Array.isArray(i)||!f.isObject(i[e])&&!Array.isArray(i[e]))&&(i[e]={}),i=i[e];Array.isArray(i)?i.splice(o,1):f.isObject(i)&&delete i[o],a.length>0&&(Array.isArray(i)&&!i.length||f.isObject(i)&&!Object.keys(i).length)&&(Array.isArray(e)&&e.length>0||f.isObject(e)&&Object.keys(e).length>0)&&f.deleteByPath(e,a.join(r),r)},emptyClone(e,n=[]){let r=JSON.parse(JSON.stringify(e));for(let e in r)n.includes(e)||(typeof r[e]==`string`?r[e]=``:typeof r[e]==`number`?r[e]=0:typeof r[e]==`boolean`?r[e]=!1:Array.isArray(r[e])?r[e]=[]:app.utils.isObject(r[e])&&(r[e]={}));return r},randomString(e=8,n=u){let r=``;for(let i=0;i`u`)return app.utils.randomString(e);let n=new Uint8Array(e);crypto.getRandomValues(n);let r=``;for(let i=0;i`,`>`).replaceAll(`"`,`"`).replaceAll(`'`,`'`):``},plainText(e){return e?(new DOMParser().parseFromString(e,`text/html`).body.textContent||``).trim():``},truncate(e,n=150,r=!0){if(e=``+e,e.length<=n)return e;if(e=e.slice(0,n),r){for(;e.endsWith(`.`);)e=e.slice(0,-1);e+=`...`}return e},truncateObject(e,n=150,r=!0){let i=Array.isArray(e)?[]:{};for(let a in e){let o=e[a];typeof o==`string`?o=app.utils.truncate(o,n,r):(Array.isArray(o)||app.utils.isObject(o))&&(o=app.utils.truncateObject(o,n,r)),i[a]=o}return i},displayValue(e,n=150,r=`N/A`){if(f.isEmpty(e))return r;if(typeof e!=`string`){if(typeof e==`boolean`)e=e?`True`:`False`;else if(Array.isArray(e)&&typeof e[0]!=`object`)e=e.map(e=>f.displayValue(e,n,r)).join(`, `);else try{e=JSON.stringify(e)||``}catch{e=``+e}}return e?f.truncate(e,n):r},splitNonEmpty(e,n=`,`){let r=(e||``).split(n),i=[];for(let e of r)e=e.trim(),f.isEmpty(e)||i.push(e);return i},joinNonEmpty(e,n=`, `){e||=[];let r=[];for(let n of e)n=typeof n==`string`?n.trim():n,f.isEmpty(n)||r.push(``+n);return r.join(n)},formattedFileSize(e){let n=e?Math.floor(Math.log(e)/Math.log(1024)):0;return(e/1024**n).toFixed(2)*1+` `+[`B`,`KB`,`MB`,`GB`,`TB`][n]},toRFC3339Datetime(e){if(!e)return``;let n;return n=e instanceof Date?e:typeof e==`string`?new Date(e.replace(` `,`T`)):new Date(e),n.toISOString().replace(`T`,` `)},toLocalDatetime(e){if(!e)return``;let n;n=e instanceof Date?e:typeof e==`string`?new Date(e.replace(` `,`T`)):new Date(e);let r=n.getFullYear();return isNaN(r)?``:`${r}-${(n.getMonth()+1).toString().padStart(2,`0`)}-${n.getDate().toString().padStart(2,`0`)} ${n.getHours().toString().padStart(2,`0`)}:${n.getMinutes().toString().padStart(2,`0`)}:${n.getSeconds().toString().padStart(2,`0`)}.${n.getMilliseconds().toString().padStart(3,`0`)}`},toDatetimeLocalInputValue(e){if(!e)return``;let n;n=e instanceof Date?e:typeof e==`string`?new Date(e.replaceAll(` `,`T`)):new Date(e);let r=n.getFullYear();return isNaN(r)?``:`${r}-${(n.getMonth()+1).toString().padStart(2,`0`)}-${n.getDate().toString().padStart(2,`0`)}T${n.getHours().toString().padStart(2,`0`)}:${n.getMinutes().toString().padStart(2,`0`)}:${n.getSeconds().toString().padStart(2,`0`)}`},async copyToClipboard(e){if(e=e==null?``:e instanceof Date?e.toISOString():typeof e==`object`?JSON.stringify(e):``+e,!(!e.length||!window.navigator?.clipboard))return window.navigator.clipboard.writeText(e).catch(e=>{console.warn(`Failed to copy.`,e)})},download(e,n){let r=document.createElement(`a`);r.setAttribute(`href`,e),r.setAttribute(`download`,n),r.setAttribute(`target`,`_blank`),r.setAttribute(`rel`,`noopener noreferrer`),r.click(),r=null},downloadJSON(e,n){n=n.endsWith(`.json`)?n:n+`.json`;let r=new Blob([JSON.stringify(e,null,2)],{type:`application/json`}),i=window.URL.createObjectURL(r);f.download(i,n)},downloadCSV(e,n){n=n.endsWith(`.csv`)?n:n+`.csv`;let r=e.map(e=>e.map(e=>`"`+(``+e).replaceAll(`"`,`""`)+`"`).join(`,`)).join(` -`),i=new Blob([r],{type:`text/csv;charset=utf-8;`}),a=window.URL.createObjectURL(i);f.download(a,n)},getApiExampleURL(){let e;if(app.pb.baseURL.startsWith(`http://`)||app.pb.baseURL.startsWith(`https://`))e=app.pb.baseURL;else{e=window.location.href;let n=e.indexOf(`/_/`);e=n>=0?e.substring(0,n):window.location.origin}return e.replace(`//localhost`,`//127.0.0.1`)},isActivePath(e,n=!0,r=``){r||=d.hash;let i;return i=RegExp(n?`^`+RegExp.escape(e)+`\\/?.*$`:`^`+RegExp.escape(e)+`\\/?(?:\\?.+)?$`),i.test(r)},getHashQueryParams(e=``){e||=d.hash;let n=``,r=e.indexOf(`?`);return r>-1&&(n=window.location.hash.substring(r+1)),Object.fromEntries(new URLSearchParams(n))},replaceHashQueryParams(e,n=null){e||={};let r=``,i=window.location.hash,a=i.indexOf(`?`);a>-1&&(r=i.substring(a+1),i=i.substring(0,a));let o=new URLSearchParams(r);for(let n in e){let r=e[n];f.isEmpty(r)?o.delete(n):o.set(n,r)}r=o.toString(),r!=``&&(i+=`?`+r);let s=window.location.href,c=s.indexOf(`#`);c>-1&&(s=s.substring(0,c));let l=s+i;return n===!1||(n===!0?window.history.pushState(null,``,l):window.history.replaceState(null,``,l)),l},getLocalHistory(e,n=null){try{let r=window.localStorage.getItem(e);if(r)return JSON.parse(r)||n}catch(n){console.log(`failed to load local history:`,e,n)}return n},saveLocalHistory(e,n){try{app.utils.isEmpty(n)?window.localStorage.removeItem(e):typeof n==`string`?window.localStorage.setItem(e,n):window.localStorage.setItem(e,JSON.stringify(n))}catch(n){console.log(`failed to save local history:`,e,n)}},generateThumb(e,n=100,r=100){return new Promise(i=>{let a=new FileReader;a.onload=function(a){let o=new Image;o.onload=function(){let a=document.createElement(`canvas`),s=a.getContext(`2d`),c=o.width,l=o.height;return a.width=n,a.height=r,s.drawImage(o,c>l?(c-l)/2:0,0,c>l?l:c,c>l?l:c,0,0,n,r),i(a.toDataURL(e.type))},o.src=a.target.result},a.readAsDataURL(e)})},normalizeSearchFilter(e,n=[]){if(e=(e||``).trim(),!e||!n.length)return e;for(let n of[`=`,`~`,`>`,`<`])if(e.includes(n))return e;return e=isNaN(e)&&e!=`true`&&e!=`false`?e.replace(/^[\"\'\`]|[\"\'\`]$/gm,``):e,n.map(n=>app.pb.filter(`${n}?~{:searchTerm}`,{searchTerm:e})).join(`||`)},logLevels:{[-4]:{label:`DEBUG`,class:``},0:{label:`INFO`,class:`success`},4:{label:`WARN`,class:`warning`},8:{label:`ERROR`,class:`danger`}},logDataFormatters:{execTime:function(e){return e?.data?.execTime===void 0?`N/A`:e.data.execTime+`ms`}},extendStore(e,n={},...r){let i=[];for(let a in n){let o=n[a];typeof e.__raw?.[a]==`function`||typeof o!=`function`||a.length>2&&a.startsWith(`on`)||r.includes(a)?e[a]=o:i.push(watch(o,n=>{e[a]=n}))}return i},cssTimeToMs(e){return e?(e=e.toLowerCase(),e.endsWith(`ms`)?Number(e.substring(0,e.length-2)):e.endsWith(`s`)?Number(e.substring(0,e.length-1)):Number(e)||0):0},isDarkEnoughForWhiteText(e){if(e=e?.startsWith(`#`)?e.substring(1):e,e?.length!=6)return!1;let n=parseInt(e.substring(0,2),16),r=parseInt(e.substring(2,4),16),i=parseInt(e.substring(4,6),16);return(n*299+r*587+i*114)/1e3<128},bulkSelectRange(e,n,r,i){let a=e.findIndex(e=>e.id==r.id);if(a==-1)return;let o=Object.keys(n),s=o[o.length-1],c=e.findIndex(e=>e.id==s);if(c==-1)return;let l=c,u=a;l>u&&([l,u]=[u,l]);for(let r=l;r<=u;r++)i?n[e[r].id]=e[r]:delete n[e[r].id]},imageExtensions:[`.jpg`,`.jpeg`,`.png`,`.svg`,`.gif`,`.jfif`,`.webp`,`.avif`],videoExtensions:[`.mp4`,`.avi`,`.mov`,`.3gp`,`.wmv`],audioExtensions:[`.aa`,`.aac`,`.m4v`,`.mp3`,`.ogg`,`.oga`,`.mogg`,`.amr`],documentExtensions:[`.pdf`,`.doc`,`.docx`,`.xls`,`.xlsx`,`.ppt`,`.pptx`,`.odp`,`.odt`,`.ods`,`.txt`],archiveExtensions:[`.zip`,`.gz`,`.tar`,`.rar`,`.7z`],hasExtension(e,n){return typeof n==`string`&&(n=n.toLowerCase(),!!e?.find(e=>n.endsWith(e)))},hasImageExtension(e){return app.utils.hasExtension(app.utils.imageExtensions,e)},hasVideoExtension(e){return app.utils.hasExtension(app.utils.videoExtensions,e)},hasAudioExtension(e){return app.utils.hasExtension(app.utils.audioExtensions,e)},hasDocumentExtension(e){return app.utils.hasExtension(app.utils.documentExtensions,e)},hasArchiveExtension(e){return app.utils.hasExtension(app.utils.archiveExtensions,e)},getFileType(e){return app.utils.hasImageExtension(e)?`image`:app.utils.hasVideoExtension(e)?`video`:app.utils.hasAudioExtension(e)?`audio`:app.utils.hasDocumentExtension(e)?`document`:app.utils.hasArchiveExtension(e)?`archive`:`file`},fileTypeIcons:{image:`ri-image-line`,video:`ri-movie-line`,audio:`ri-music-2-line`,document:`ri-file-line`,archive:`ri-file-zip-line`,file:`ri-file-line`},fallbackFieldIcon:`ri-puzzle-line`,fallbackCollectionIcon:`ri-puzzle-line`,fallbackProviderIcon:`ri-puzzle-line`,fallbackPresentableProps:[`title`,`name`,`slug`,`email`,`username`,`nickname`,`displayName`,`label`,`subject`,`topic`,`message`,`heading`,`headline`,`header`,`caption`,`key`,`identifier`,`id`],sortedCollections(e=[]){let n,r;function i(e,i){return n=e.name.startsWith(`_`),r=i.name.startsWith(`_`),n&&!r?1:!n&&r?-1:e.name>i.name?1:e.namee?.id&&!a.find(n=>n.id==e.id)),s=a.filter(e=>e?.id&&!i.find(n=>n.id==e.id)),c=a.filter(e=>{let n=app.utils.isObject(e)&&i.find(n=>n.id==e.id);if(!n)return!1;for(let r in n)if(JSON.stringify(e[r])!=JSON.stringify(n[r]))return!0;return!1});return!!(s.length||c.length||r&&o.length)},extractColumnsFromQuery(e){let n=`__PBGROUP__`;e=(e||``).replace(/\([\s\S]+?\)/gm,n).replace(/[\t\r\n]|(?:\s\s)+/g,` `);let r=e.match(/select\s+([\s\S]+)\s+from/)?.[1]?.split(`,`)||[],i=[];for(let e of r){let r=e.trim().split(` `).pop();r!=``&&r!=n&&i.push(r.replace(/[\'\"\`\[\]\s]/g,``))}return i},getAllCollectionIdentifiers(e,n=``){if(!e)return[];let r=[n+`id`],i=e.type==`auth`;if(e.type===`view`)for(let i of app.utils.extractColumnsFromQuery(e.viewQuery))app.utils.pushUnique(r,n+i);let a=e.fields||[];for(let e of a)if(!(e.type==`password`||i&&e.name==`tokenKey`)){if(app.fieldTypes[e.type]?.identifierExtractor){let i=app.utils.toArray(app.fieldTypes[e.type]?.identifierExtractor(e,n));for(let e of i)app.utils.pushUnique(r,e)}else app.utils.pushUnique(r,n+e.name)}return r},getDummyFieldsData(e,n=!1){let r=e?.fields||[],i={};for(let e of r)if(!e.hidden){if(app.fieldTypes[e.type]?.dummyData){let r=app.fieldTypes[e.type].dummyData(e,n);r!==void 0&&(i[e.name]=r)}else i[e.name]=`[[DATA]]`}return i},parseIndex(e){let n={unique:!1,optional:!1,schemaName:``,indexName:``,tableName:``,columns:[],where:``},r=/create\s+(unique\s+)?\s*index\s*(if\s+not\s+exists\s+)?(\S*)\s+on\s+(\S*)\s*\(([\s\S]*)\)(?:\s*where\s+([\s\S]*))?/gim.exec((e||``).trim());if(r?.length!=7)return n;let i=/^[\"\'\`\[\{}]|[\"\'\`\]\}]$/gm;n.unique=r[1]?.trim().toLowerCase()===`unique`,n.optional=!app.utils.isEmpty(r[2]?.trim());let a=(r[3]||``).split(`.`);a.length==2?(n.schemaName=a[0].replace(i,``),n.indexName=a[1].replace(i,``)):(n.schemaName=``,n.indexName=a[0].replace(i,``)),n.tableName=(r[4]||``).replace(i,``);let o=(r[5]||``).replace(/,(?=[^\(]*\))/gim,`{PB_TEMP}`).split(`,`);for(let e of o){e=e.trim().replaceAll(`{PB_TEMP}`,`,`);let r=/^([\s\S]+?)(?:\s+collate\s+([\w]+))?(?:\s+(asc|desc))?$/gim.exec(e);if(r?.length!=4)continue;let a=r[1]?.trim()?.replace(i,``);a&&n.columns.push({name:a,collate:r[2]||``,sort:r[3]?.toUpperCase()||``})}return n.where=r[6]||``,n},buildIndex(e){let n=`CREATE `;e.unique&&(n+=`UNIQUE `),n+=`INDEX `,e.optional&&(n+=`IF NOT EXISTS `),e.schemaName&&(n+=`\`${e.schemaName}\`.`),n+=`\`${e.indexName||`idx_`+app.utils.randomString(10)}\` `,n+=`ON \`${e.tableName}\` (`;let r=e.columns.filter(e=>!!e?.name);return r.length>1&&(n+=` +`),i=new Blob([r],{type:`text/csv;charset=utf-8;`}),a=window.URL.createObjectURL(i);f.download(a,n)},getApiExampleURL(){let e;if(app.pb.baseURL.startsWith(`http://`)||app.pb.baseURL.startsWith(`https://`))e=app.pb.baseURL;else{e=window.location.href;let n=e.indexOf(`/_/`);e=n>=0?e.substring(0,n):window.location.origin}return e.replace(`//localhost`,`//127.0.0.1`)},isActivePath(e,n=!0,r=``){r||=d.hash;let i;return i=RegExp(n?`^`+RegExp.escape(e)+`\\/?.*$`:`^`+RegExp.escape(e)+`\\/?(?:\\?.+)?$`),i.test(r)},getHashQueryParams(e=``){e||=d.hash;let n=``,r=e.indexOf(`?`);return r>-1&&(n=window.location.hash.substring(r+1)),Object.fromEntries(new URLSearchParams(n))},replaceHashQueryParams(e,n=null){e||={};let r=``,i=window.location.hash,a=i.indexOf(`?`);a>-1&&(r=i.substring(a+1),i=i.substring(0,a));let o=new URLSearchParams(r);for(let n in e){let r=e[n];f.isEmpty(r)?o.delete(n):o.set(n,r)}r=o.toString(),r!=``&&(i+=`?`+r);let s=window.location.href,c=s.indexOf(`#`);c>-1&&(s=s.substring(0,c));let l=s+i;return n===!1||(n===!0?window.history.pushState(null,``,l):window.history.replaceState(null,``,l)),l},getLocalHistory(e,n=null){try{let r=window.localStorage.getItem(e);if(r)return JSON.parse(r)||n}catch(n){console.log(`failed to load local history:`,e,n)}return n},saveLocalHistory(e,n){try{app.utils.isEmpty(n)?window.localStorage.removeItem(e):typeof n==`string`?window.localStorage.setItem(e,n):window.localStorage.setItem(e,JSON.stringify(n))}catch(n){console.log(`failed to save local history:`,e,n)}},generateThumb(e,n=100,r=100){return new Promise(i=>{let a=new FileReader;a.onload=function(a){let o=new Image;o.onload=function(){let a=document.createElement(`canvas`),s=a.getContext(`2d`),c=o.width,l=o.height;return a.width=n,a.height=r,s.drawImage(o,c>l?(c-l)/2:0,0,c>l?l:c,c>l?l:c,0,0,n,r),i(a.toDataURL(e.type))},o.src=a.target.result},a.readAsDataURL(e)})},normalizeSearchFilter(e,n=[]){if(e=(e||``).trim(),!e||!n.length)return e;for(let n of[`=`,`~`,`>`,`<`])if(e.includes(n))return e;return e=isNaN(e)&&e!=`true`&&e!=`false`?e.replace(/^[\"\'\`]|[\"\'\`]$/gm,``):e,n.map(n=>app.pb.filter(`${n}?~{:searchTerm}`,{searchTerm:e})).join(`||`)},logLevels:{[-4]:{label:`DEBUG`,class:``},0:{label:`INFO`,class:`success`},4:{label:`WARN`,class:`warning`},8:{label:`ERROR`,class:`danger`}},logDataFormatters:{execTime:function(e){return e?.data?.execTime===void 0?`N/A`:e.data.execTime+`ms`}},extendStore(e,n={},...r){let i=[];for(let a in n){let o=n[a];typeof e.__raw?.[a]==`function`||typeof o!=`function`||a.length>2&&a.startsWith(`on`)||r.includes(a)?e[a]=o:i.push(watch(o,n=>{e[a]=n}))}return i},cssTimeToMs(e){return e?(e=e.toLowerCase(),e.endsWith(`ms`)?Number(e.substring(0,e.length-2)):e.endsWith(`s`)?Number(e.substring(0,e.length-1)):Number(e)||0):0},isDarkEnoughForWhiteText(e){if(e=e?.startsWith(`#`)?e.substring(1):e,e?.length!=6)return!1;let n=parseInt(e.substring(0,2),16),r=parseInt(e.substring(2,4),16),i=parseInt(e.substring(4,6),16);return(n*299+r*587+i*114)/1e3<128},bulkSelectRange(e,n,r,i){let a=e.findIndex(e=>e.id==r.id);if(a==-1)return;let o=Object.keys(n),s=o[o.length-1],c=e.findIndex(e=>e.id==s);if(c==-1)return;let l=c,u=a;l>u&&([l,u]=[u,l]);for(let r=l;r<=u;r++)i?n[e[r].id]=e[r]:delete n[e[r].id]},imageExtensions:[`.jpg`,`.jpeg`,`.png`,`.svg`,`.gif`,`.jfif`,`.webp`,`.avif`],videoExtensions:[`.mp4`,`.avi`,`.mov`,`.3gp`,`.wmv`],audioExtensions:[`.aa`,`.aac`,`.m4v`,`.mp3`,`.ogg`,`.oga`,`.mogg`,`.amr`],documentExtensions:[`.pdf`,`.doc`,`.docx`,`.xls`,`.xlsx`,`.ppt`,`.pptx`,`.odp`,`.odt`,`.ods`,`.txt`],archiveExtensions:[`.zip`,`.gz`,`.tar`,`.rar`,`.7z`],hasExtension(e,n){return typeof n==`string`&&(n=n.toLowerCase(),!!e?.find(e=>n.endsWith(e)))},hasImageExtension(e){return app.utils.hasExtension(app.utils.imageExtensions,e)},hasVideoExtension(e){return app.utils.hasExtension(app.utils.videoExtensions,e)},hasAudioExtension(e){return app.utils.hasExtension(app.utils.audioExtensions,e)},hasDocumentExtension(e){return app.utils.hasExtension(app.utils.documentExtensions,e)},hasArchiveExtension(e){return app.utils.hasExtension(app.utils.archiveExtensions,e)},getFileType(e){return app.utils.hasImageExtension(e)?`image`:app.utils.hasVideoExtension(e)?`video`:app.utils.hasAudioExtension(e)?`audio`:app.utils.hasDocumentExtension(e)?`document`:app.utils.hasArchiveExtension(e)?`archive`:`file`},fileTypeIcons:{image:`ri-image-line`,video:`ri-movie-line`,audio:`ri-music-2-line`,document:`ri-file-line`,archive:`ri-file-zip-line`,file:`ri-file-line`},fallbackFieldIcon:`ri-puzzle-line`,fallbackCollectionIcon:`ri-puzzle-line`,fallbackProviderIcon:`ri-puzzle-line`,fallbackPresentableProps:[`title`,`name`,`slug`,`email`,`username`,`nickname`,`displayName`,`label`,`subject`,`topic`,`message`,`heading`,`headline`,`header`,`caption`,`key`,`identifier`,`id`],sortedCollections(e=[]){let n,r;function i(e,i){return n=e.name.startsWith(`_`),r=i.name.startsWith(`_`),n&&!r?1:!n&&r?-1:e.name>i.name?1:e.namee?.id&&!a.find(n=>n.id==e.id)),s=a.filter(e=>e?.id&&!i.find(n=>n.id==e.id)),c=a.filter(e=>{let n=app.utils.isObject(e)&&i.find(n=>n.id==e.id);if(!n)return!1;for(let r in n)if(JSON.stringify(e[r])!=JSON.stringify(n[r]))return!0;return!1});return!!(s.length||c.length||r&&o.length)},extractColumnsFromQuery(e){let n=`__PBGROUP__`;e=(e||``).replace(/\([\s\S]+?\)/gm,n).replace(/[\t\r\n]|(?:\s\s)+/g,` `);let r=e.match(/select\s+([\s\S]+)\s+from/)?.[1]?.split(`,`)||[],i=[];for(let e of r){let r=e.trim().split(` `).pop();r!=``&&r!=n&&i.push(r.replace(/[\'\"\`\[\]\s]/g,``))}return i},getAllCollectionIdentifiers(e,n=``){if(!e)return[];let r=[n+`id`],i=e.type==`auth`;if(e.type===`view`)for(let i of app.utils.extractColumnsFromQuery(e.viewQuery))app.utils.pushUnique(r,n+i);let a=e.fields||[];for(let e of a)if(!(e.type==`password`||i&&e.name==`tokenKey`)){if(app.fieldTypes[e.type]?.identifierExtractor){let i=app.utils.toArray(app.fieldTypes[e.type]?.identifierExtractor(e,n));for(let e of i)app.utils.pushUnique(r,e)}else app.utils.pushUnique(r,n+e.name)}return r},getDummyFieldsData(e,n=!1){let r=e?.fields||[],i={};for(let e of r)if(!e.hidden){if(app.fieldTypes[e.type]?.dummyData){let r=app.fieldTypes[e.type].dummyData(e,n);r!==void 0&&(i[e.name]=r)}else i[e.name]=`[[DATA]]`}return i},parseIndex(e){let n={unique:!1,optional:!1,schemaName:``,indexName:``,tableName:``,columns:[],where:``},r=/\s*create\s+(unique\s+)?\s*index\s*(if\s+not\s+exists\s+)?(\S*)\s+on\s+(\S*)\s*\(([\s\S]*?)\)(?:\s*where\s+([\s\S]*?))?\s*$/gi.exec((e||``).trim());if(r?.length!=7)return n;let i=/^[\"\'\`\[\{}]|[\"\'\`\]\}]$/g;n.unique=r[1]?.trim().toLowerCase()===`unique`,n.optional=!app.utils.isEmpty(r[2]?.trim());let a=(r[3]||``).split(`.`);a.length==2?(n.schemaName=a[0].replace(i,``),n.indexName=a[1].replace(i,``)):(n.schemaName=``,n.indexName=a[0].replace(i,``)),n.tableName=(r[4]||``).replace(i,``);let o=(r[5]||``).replace(/,(?=[^\(]*\))/gi,`{PB_TEMP}`).split(`,`);for(let e of o){e=e.trim().replaceAll(`{PB_TEMP}`,`,`);let r=/^([\s\S]+?)(?:\s+collate\s+([\w]+))?(?:\s+(asc|desc))?\s*$/gi.exec(e);if(r?.length!=4)continue;let a=r[1]?.trim()?.replace(i,``);a&&n.columns.push({name:a,collate:r[2]||``,sort:r[3]?.toUpperCase()||``})}return n.where=r[6]||``,n},buildIndex(e){let n=`CREATE `;e.unique&&(n+=`UNIQUE `),n+=`INDEX `,e.optional&&(n+=`IF NOT EXISTS `),e.schemaName&&(n+=`\`${e.schemaName}\`.`),n+=`\`${e.indexName||`idx_`+app.utils.randomString(10)}\` `,n+=`ON \`${e.tableName}\` (`;let r=e.columns.filter(e=>!!e?.name);return r.length>1&&(n+=` `),n+=r.map(e=>{let n=``;return e.name.includes(`(`)||e.name.includes(` `)?n+=e.name:n+="`"+e.name+"`",e.collate&&(n+=` COLLATE `+e.collate),e.sort&&(n+=` `+e.sort.toUpperCase()),n}).join(`, `),r.length>1&&(n+=` -`),n+=`)`,e.where&&(n+=` WHERE ${e.where}`),n},replaceIndexFields(e,n){let r=app.utils.parseIndex(e);return typeof n==`function`?Object.assign(r,n(r)||{}):Object.assign(r,n||{}),app.utils.buildIndex(r)},replaceIndexColumn(e,n,r){if(n===r)return e;let i=app.utils.parseIndex(e),a=!1;for(let e of i.columns)e.name===n&&(e.name=r,a=!0);return a?app.utils.buildIndex(i):e}};window.app=window.app||{},window.app.utils=f,window.app=window.app||{},window.app.utils=window.app.utils||{},window.app.utils.mimeTypes=[{ext:``,mimeType:`application/octet-stream`},{ext:`.xpm`,mimeType:`image/x-xpixmap`},{ext:`.7z`,mimeType:`application/x-7z-compressed`},{ext:`.zip`,mimeType:`application/zip`},{ext:`.xlsx`,mimeType:`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`},{ext:`.docx`,mimeType:`application/vnd.openxmlformats-officedocument.wordprocessingml.document`},{ext:`.pptx`,mimeType:`application/vnd.openxmlformats-officedocument.presentationml.presentation`},{ext:`.epub`,mimeType:`application/epub+zip`},{ext:`.apk`,mimeType:`application/vnd.android.package-archive`},{ext:`.jar`,mimeType:`application/jar`},{ext:`.odt`,mimeType:`application/vnd.oasis.opendocument.text`},{ext:`.ott`,mimeType:`application/vnd.oasis.opendocument.text-template`},{ext:`.ods`,mimeType:`application/vnd.oasis.opendocument.spreadsheet`},{ext:`.ots`,mimeType:`application/vnd.oasis.opendocument.spreadsheet-template`},{ext:`.odp`,mimeType:`application/vnd.oasis.opendocument.presentation`},{ext:`.otp`,mimeType:`application/vnd.oasis.opendocument.presentation-template`},{ext:`.odg`,mimeType:`application/vnd.oasis.opendocument.graphics`},{ext:`.otg`,mimeType:`application/vnd.oasis.opendocument.graphics-template`},{ext:`.odf`,mimeType:`application/vnd.oasis.opendocument.formula`},{ext:`.odc`,mimeType:`application/vnd.oasis.opendocument.chart`},{ext:`.sxc`,mimeType:`application/vnd.sun.xml.calc`},{ext:`.pdf`,mimeType:`application/pdf`},{ext:`.fdf`,mimeType:`application/vnd.fdf`},{ext:``,mimeType:`application/x-ole-storage`},{ext:`.msi`,mimeType:`application/x-ms-installer`},{ext:`.aaf`,mimeType:`application/octet-stream`},{ext:`.msg`,mimeType:`application/vnd.ms-outlook`},{ext:`.xls`,mimeType:`application/vnd.ms-excel`},{ext:`.pub`,mimeType:`application/vnd.ms-publisher`},{ext:`.ppt`,mimeType:`application/vnd.ms-powerpoint`},{ext:`.doc`,mimeType:`application/msword`},{ext:`.ps`,mimeType:`application/postscript`},{ext:`.psd`,mimeType:`image/vnd.adobe.photoshop`},{ext:`.p7s`,mimeType:`application/pkcs7-signature`},{ext:`.ogg`,mimeType:`application/ogg`},{ext:`.oga`,mimeType:`audio/ogg`},{ext:`.ogv`,mimeType:`video/ogg`},{ext:`.png`,mimeType:`image/png`},{ext:`.png`,mimeType:`image/vnd.mozilla.apng`},{ext:`.jpg`,mimeType:`image/jpeg`},{ext:`.jxl`,mimeType:`image/jxl`},{ext:`.jp2`,mimeType:`image/jp2`},{ext:`.jpf`,mimeType:`image/jpx`},{ext:`.jpm`,mimeType:`image/jpm`},{ext:`.jxs`,mimeType:`image/jxs`},{ext:`.gif`,mimeType:`image/gif`},{ext:`.webp`,mimeType:`image/webp`},{ext:`.exe`,mimeType:`application/vnd.microsoft.portable-executable`},{ext:``,mimeType:`application/x-elf`},{ext:``,mimeType:`application/x-object`},{ext:``,mimeType:`application/x-executable`},{ext:`.so`,mimeType:`application/x-sharedlib`},{ext:``,mimeType:`application/x-coredump`},{ext:`.a`,mimeType:`application/x-archive`},{ext:`.deb`,mimeType:`application/vnd.debian.binary-package`},{ext:`.tar`,mimeType:`application/x-tar`},{ext:`.xar`,mimeType:`application/x-xar`},{ext:`.bz2`,mimeType:`application/x-bzip2`},{ext:`.fits`,mimeType:`application/fits`},{ext:`.tiff`,mimeType:`image/tiff`},{ext:`.bmp`,mimeType:`image/bmp`},{ext:`.ico`,mimeType:`image/x-icon`},{ext:`.mp3`,mimeType:`audio/mpeg`},{ext:`.flac`,mimeType:`audio/flac`},{ext:`.midi`,mimeType:`audio/midi`},{ext:`.ape`,mimeType:`audio/ape`},{ext:`.mpc`,mimeType:`audio/musepack`},{ext:`.amr`,mimeType:`audio/amr`},{ext:`.wav`,mimeType:`audio/wav`},{ext:`.aiff`,mimeType:`audio/aiff`},{ext:`.au`,mimeType:`audio/basic`},{ext:`.mpeg`,mimeType:`video/mpeg`},{ext:`.mov`,mimeType:`video/quicktime`},{ext:`.mp4`,mimeType:`video/mp4`},{ext:`.avif`,mimeType:`image/avif`},{ext:`.3gp`,mimeType:`video/3gpp`},{ext:`.3g2`,mimeType:`video/3gpp2`},{ext:`.mp4`,mimeType:`audio/mp4`},{ext:`.mqv`,mimeType:`video/quicktime`},{ext:`.m4a`,mimeType:`audio/x-m4a`},{ext:`.m4v`,mimeType:`video/x-m4v`},{ext:`.heic`,mimeType:`image/heic`},{ext:`.heic`,mimeType:`image/heic-sequence`},{ext:`.heif`,mimeType:`image/heif`},{ext:`.heif`,mimeType:`image/heif-sequence`},{ext:`.mj2`,mimeType:`video/mj2`},{ext:`.dvb`,mimeType:`video/vnd.dvb.file`},{ext:`.webm`,mimeType:`video/webm`},{ext:`.avi`,mimeType:`video/x-msvideo`},{ext:`.flv`,mimeType:`video/x-flv`},{ext:`.mkv`,mimeType:`video/x-matroska`},{ext:`.asf`,mimeType:`video/x-ms-asf`},{ext:`.asf`,mimeType:`video/x-ms-wmv`},{ext:`.asf`,mimeType:`video/asf`},{ext:`.aac`,mimeType:`audio/aac`},{ext:`.voc`,mimeType:`audio/x-unknown`},{ext:`.m3u`,mimeType:`application/vnd.apple.mpegurl`},{ext:`.rmvb`,mimeType:`application/vnd.rn-realmedia-vbr`},{ext:`.gz`,mimeType:`application/gzip`},{ext:`.class`,mimeType:`application/x-java-applet`},{ext:`.swf`,mimeType:`application/x-shockwave-flash`},{ext:`.crx`,mimeType:`application/x-chrome-extension`},{ext:`.ttf`,mimeType:`font/ttf`},{ext:`.woff`,mimeType:`font/woff`},{ext:`.woff2`,mimeType:`font/woff2`},{ext:`.otf`,mimeType:`font/otf`},{ext:`.ttc`,mimeType:`font/collection`},{ext:`.eot`,mimeType:`application/vnd.ms-fontobject`},{ext:`.wasm`,mimeType:`application/wasm`},{ext:`.shx`,mimeType:`application/vnd.shx`},{ext:`.shp`,mimeType:`application/vnd.shp`},{ext:`.dbf`,mimeType:`application/x-dbf`},{ext:`.dcm`,mimeType:`application/dicom`},{ext:`.rar`,mimeType:`application/x-rar-compressed`},{ext:`.djvu`,mimeType:`image/vnd.djvu`},{ext:`.mobi`,mimeType:`application/x-mobipocket-ebook`},{ext:`.lit`,mimeType:`application/x-ms-reader`},{ext:`.bpg`,mimeType:`image/bpg`},{ext:`.cbor`,mimeType:`application/cbor`},{ext:`.sqlite`,mimeType:`application/vnd.sqlite3`},{ext:`.dwg`,mimeType:`image/vnd.dwg`},{ext:`.nes`,mimeType:`application/vnd.nintendo.snes.rom`},{ext:`.lnk`,mimeType:`application/x-ms-shortcut`},{ext:`.macho`,mimeType:`application/x-mach-binary`},{ext:`.qcp`,mimeType:`audio/qcelp`},{ext:`.icns`,mimeType:`image/x-icns`},{ext:`.hdr`,mimeType:`image/vnd.radiance`},{ext:`.mrc`,mimeType:`application/marc`},{ext:`.mdb`,mimeType:`application/x-msaccess`},{ext:`.accdb`,mimeType:`application/x-msaccess`},{ext:`.zst`,mimeType:`application/zstd`},{ext:`.cab`,mimeType:`application/vnd.ms-cab-compressed`},{ext:`.rpm`,mimeType:`application/x-rpm`},{ext:`.xz`,mimeType:`application/x-xz`},{ext:`.lz`,mimeType:`application/lzip`},{ext:`.torrent`,mimeType:`application/x-bittorrent`},{ext:`.cpio`,mimeType:`application/x-cpio`},{ext:``,mimeType:`application/tzif`},{ext:`.xcf`,mimeType:`image/x-xcf`},{ext:`.pat`,mimeType:`image/x-gimp-pat`},{ext:`.gbr`,mimeType:`image/x-gimp-gbr`},{ext:`.glb`,mimeType:`model/gltf-binary`},{ext:`.cab`,mimeType:`application/x-installshield`},{ext:`.jxr`,mimeType:`image/jxr`},{ext:`.parquet`,mimeType:`application/vnd.apache.parquet`},{ext:`.txt`,mimeType:`text/plain`},{ext:`.html`,mimeType:`text/html`},{ext:`.svg`,mimeType:`image/svg+xml`},{ext:`.xml`,mimeType:`text/xml`},{ext:`.rss`,mimeType:`application/rss+xml`},{ext:`.atom`,mimeType:`application/atom+xml`},{ext:`.x3d`,mimeType:`model/x3d+xml`},{ext:`.kml`,mimeType:`application/vnd.google-earth.kml+xml`},{ext:`.xlf`,mimeType:`application/x-xliff+xml`},{ext:`.dae`,mimeType:`model/vnd.collada+xml`},{ext:`.gml`,mimeType:`application/gml+xml`},{ext:`.gpx`,mimeType:`application/gpx+xml`},{ext:`.tcx`,mimeType:`application/vnd.garmin.tcx+xml`},{ext:`.amf`,mimeType:`application/x-amf`},{ext:`.3mf`,mimeType:`application/vnd.ms-package.3dmanufacturing-3dmodel+xml`},{ext:`.xfdf`,mimeType:`application/vnd.adobe.xfdf`},{ext:`.owl`,mimeType:`application/owl+xml`},{ext:`.php`,mimeType:`text/x-php`},{ext:`.js`,mimeType:`text/javascript`},{ext:`.lua`,mimeType:`text/x-lua`},{ext:`.pl`,mimeType:`text/x-perl`},{ext:`.py`,mimeType:`text/x-python`},{ext:`.json`,mimeType:`application/json`},{ext:`.geojson`,mimeType:`application/geo+json`},{ext:`.har`,mimeType:`application/json`},{ext:`.ndjson`,mimeType:`application/x-ndjson`},{ext:`.rtf`,mimeType:`text/rtf`},{ext:`.srt`,mimeType:`application/x-subrip`},{ext:`.tcl`,mimeType:`text/x-tcl`},{ext:`.csv`,mimeType:`text/csv`},{ext:`.tsv`,mimeType:`text/tab-separated-values`},{ext:`.vcf`,mimeType:`text/vcard`},{ext:`.ics`,mimeType:`text/calendar`},{ext:`.warc`,mimeType:`application/warc`},{ext:`.vtt`,mimeType:`text/vtt`},{ext:`.pbm`,mimeType:`image/x-portable-bitmap`},{ext:`.pgm`,mimeType:`image/x-portable-graymap`},{ext:`.ppm`,mimeType:`image/x-portable-pixmap`},{ext:`.eml`,mimeType:`message/rfc822`}];var p=new BroadcastChannel(`tabsSync`),m=`pbSettings`,h=`pbColorScheme`;window.app=window.app||{},window.app.store=store({_ready:!1,superuser:null,showHeader:!0,page:t.div({className:`page`},()=>{if(!app.store._ready)return t.span({className:`loader lg m-auto`,title:`Loading plugins...`})}),mainLogo:`./images/logo.svg`,headerLogo:`./images/logo_white.svg`,favicon:``,title:``,_mediaColorScheme:``,userColorScheme:window.localStorage.getItem(h)||``,get activeColorScheme(){return app.store.userColorScheme?app.store.userColorScheme:app.store._mediaColorScheme||`light`},errors:null,creditLinks:[{href:`https://pocketbase.io/docs`,icon:`ri-book-open-line`,label:`Docs`},{href:`https://github.com/pocketbase/pocketbase/releases`,icon:`ri-github-line`,label:`PocketBase v0.40.2`}],headerLinks:[{href:`#/collections`,icon:`ri-database-2-line`,label:`Collections`},{href:`#/logs`,icon:`ri-bar-chart-box-line`,label:`Logs`},{href:`#/settings`,icon:`ri-settings-3-line`,label:`Settings`}],settingsNavGroups:{System:[{href:`#/settings`,icon:`ri-home-gear-line`,label:`Application`},{href:`#/settings/mail`,icon:`ri-send-plane-2-line`,label:`Mail settings`},{href:`#/settings/storage`,icon:`ri-archive-drawer-line`,label:`Files storage`},{href:`#/settings/backups`,icon:`ri-archive-line`,label:`Backups`},{href:`#/settings/crons`,icon:`ri-time-line`,label:`Crons`}],Sync:[{href:`#/settings/export-collections`,icon:`ri-uninstall-line`,label:`Export collections`},{href:`#/settings/import-collections`,icon:`ri-install-line`,label:`Import collections`}],Debug:[{href:`#/settings/sql`,icon:`ri-terminal-box-line`,label:`SQL console`}]},predefinedAccentColors:[`#1055c9`,`#a3142a`,`#096d5c`,`#e6620a`,`#007d9c`,`#3f3da9`],settings:app.utils.getLocalHistory(m,{}),isLoadingSettings:!1,async loadSettings(){app.store.isLoadingSettings=!0;try{let e=await app.pb.settings.getAll({requestKey:`appStore.loadSettings`});app.store.settings=e,app.store.isLoadingSettings=!1}catch(e){e.isAbort||(app.store.isLoadingSettings=!1,app.checkApiError(e))}},collections:[],collectionScaffolds:{},isLoadingCollections:!1,_activeCollectionIdOrName:``,get activeCollection(){let e=app.store._activeCollectionIdOrName;return app.store.collections.find(n=>n.id==e||n.name==e)||app.store.collections[0]},set activeCollection(e){typeof e==`string`?app.store._activeCollectionIdOrName=e:app.store._activeCollectionIdOrName=e?.id},async silentlyReloadCollections(){try{let e=await app.pb.collections.getFullList({requestKey:`appStore.silentlyReloadCollections`});e=app.utils.sortedCollectionsByType(e),JSON.stringify(e)!=JSON.stringify(app.store.collections)&&(app.store.collections=e)}catch(e){e.isAbort||console.warn(`failed to reload app store collections:`,e)}},async loadCollections(e=null){app.store.isLoadingCollections=!0;try{let[n,r]=await Promise.all([app.pb.collections.getScaffolds({requestKey:`appStore.loadCollections.getScaffolds`}),app.pb.collections.getFullList({requestKey:`appStore.loadCollections.getFullList`})]);r=app.utils.sortedCollectionsByType(r),JSON.stringify(app.store.collections)!=JSON.stringify(r)&&(app.store.collections=r),app.store.collectionScaffolds=n,app.store._activeCollectionIdOrName=e||app.store._activeCollectionIdOrName||app.store.collections[0]?.id||``,app.store.isLoadingCollections=!1}catch(e){e.isAbort||(app.store.isLoadingCollections=!1,app.checkApiError(e))}},addOrUpdateCollection(e){let n=app.store.collections.findIndex(n=>n.id==e.id);n>=0?(app.store.activeCollection?.id==e.id&&(app.store._activeCollectionIdOrName=e.id),app.store.collections[n]=e):app.store.collections.push(e),app.store.collections=app.utils.sortedCollectionsByType(app.store.collections)},oauth2Providers:[],isLoadingOAuth2Providers:!1,async loadOAuth2Providers(){app.store.isLoadingOAuth2Providers=!0;try{app.store.oauth2Providers=await app.pb.collections.getAllOAuth2Providers(),app.store.isLoadingOAuth2Providers=!1}catch(e){e.isAbort||(app.checkApiError(e),app.store.isLoadingOAuth2Providers=!1)}}}),window.addEventListener(`hashchange`,()=>{app.store.title=``,app.store.errors=null}),watch(()=>{let e=app.utils.toArray(app.store.title),n=app.store.settings?.meta?.appName||``;n&&e.push(n),document.title=e.join(` - `)});var g;watch(()=>app.store.settings?.meta?.accentColor,e=>{g||(g=t.meta({name:`theme-color`}),document.head.appendChild(g)),e?(g?.setAttribute(`content`,e),document.documentElement.style.setProperty(`--accentColor`,e)):(g?.removeAttribute(`content`),document.documentElement.style.removeProperty(`--accentColor`))});var _;watch(()=>app.store.favicon,e=>{_||(_=t.link({rel:`icon`}),document.head.appendChild(_)),e?_.href=e:_.href=window.location.href.startsWith(`https://`)?`./images/favicon_prod.png`:`./images/favicon.png`});var v=window.matchMedia(`(prefers-color-scheme: dark)`);app.store._mediaColorScheme=v.matches?`dark`:`light`,v.addEventListener(`change`,({matches:e})=>{app.store._mediaColorScheme=e?`dark`:`light`}),watch(()=>app.store.userColorScheme,e=>{e?window.localStorage.setItem(h,e):window.localStorage.removeItem(h),p?.postMessage({colorScheme:e})});var ee;watch(()=>app.store.activeColorScheme,e=>{clearTimeout(ee),document.documentElement.style.setProperty(`--animationSpeed`,`0`),document.documentElement.setAttribute(`data-color-scheme`,e),ee=setTimeout(()=>{document.documentElement.style.removeProperty(`--animationSpeed`)},100)});function te(e,n){e.__errListener&&=(e.removeEventListener(`input`,e.__errListener),e.removeEventListener(`change`,e.__errListener),null),e.setCustomValidity&&(e.setCustomValidity(``),e._oldTitle?e.setAttribute(`title`,e._oldTitle):e.removeAttribute(`title`)),e.removeAttribute(`data-error`);let r=n.nextSibling;r&&r.classList?.contains(`generated-error`)&&r.getAttribute(`data-input-name`)==e.getAttribute(`name`)&&r.remove(),n.querySelector(`[data-error]`)||n.classList.remove(`error`)}watch(()=>JSON.stringify(app.store.errors)&&app.store.errors,e=>{let n=document.querySelectorAll(`[name]`);for(let r of n){if(r.classList.contains(`no-error`))continue;let n=r.closest(`.field-list`)||r.closest(`.fields`)||r.closest(`.field`);if(!n)continue;let i=r.getAttribute(`name`);te(r,n);let a=app.utils.getByPath(e,i),o=a?.message||``;if(!o&&!app.utils.isEmpty(a)){let e=[];for(let n in a)a[n]?.message&&e.push(`${n}: ${a[n]?.message}`);o=e.join(` +`),n+=`)`,e.where&&(n+=` WHERE ${e.where}`),n},replaceIndexFields(e,n){let r=app.utils.parseIndex(e);return typeof n==`function`?Object.assign(r,n(r)||{}):Object.assign(r,n||{}),app.utils.buildIndex(r)},replaceIndexColumn(e,n,r){if(n===r)return e;let i=app.utils.parseIndex(e),a=!1;for(let e of i.columns)e.name===n&&(e.name=r,a=!0);return a?app.utils.buildIndex(i):e}};window.app=window.app||{},window.app.utils=f,window.app=window.app||{},window.app.utils=window.app.utils||{},window.app.utils.mimeTypes=[{ext:``,mimeType:`application/octet-stream`},{ext:`.xpm`,mimeType:`image/x-xpixmap`},{ext:`.7z`,mimeType:`application/x-7z-compressed`},{ext:`.zip`,mimeType:`application/zip`},{ext:`.xlsx`,mimeType:`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`},{ext:`.docx`,mimeType:`application/vnd.openxmlformats-officedocument.wordprocessingml.document`},{ext:`.pptx`,mimeType:`application/vnd.openxmlformats-officedocument.presentationml.presentation`},{ext:`.epub`,mimeType:`application/epub+zip`},{ext:`.apk`,mimeType:`application/vnd.android.package-archive`},{ext:`.jar`,mimeType:`application/jar`},{ext:`.odt`,mimeType:`application/vnd.oasis.opendocument.text`},{ext:`.ott`,mimeType:`application/vnd.oasis.opendocument.text-template`},{ext:`.ods`,mimeType:`application/vnd.oasis.opendocument.spreadsheet`},{ext:`.ots`,mimeType:`application/vnd.oasis.opendocument.spreadsheet-template`},{ext:`.odp`,mimeType:`application/vnd.oasis.opendocument.presentation`},{ext:`.otp`,mimeType:`application/vnd.oasis.opendocument.presentation-template`},{ext:`.odg`,mimeType:`application/vnd.oasis.opendocument.graphics`},{ext:`.otg`,mimeType:`application/vnd.oasis.opendocument.graphics-template`},{ext:`.odf`,mimeType:`application/vnd.oasis.opendocument.formula`},{ext:`.odc`,mimeType:`application/vnd.oasis.opendocument.chart`},{ext:`.sxc`,mimeType:`application/vnd.sun.xml.calc`},{ext:`.pdf`,mimeType:`application/pdf`},{ext:`.fdf`,mimeType:`application/vnd.fdf`},{ext:``,mimeType:`application/x-ole-storage`},{ext:`.msi`,mimeType:`application/x-ms-installer`},{ext:`.aaf`,mimeType:`application/octet-stream`},{ext:`.msg`,mimeType:`application/vnd.ms-outlook`},{ext:`.xls`,mimeType:`application/vnd.ms-excel`},{ext:`.pub`,mimeType:`application/vnd.ms-publisher`},{ext:`.ppt`,mimeType:`application/vnd.ms-powerpoint`},{ext:`.doc`,mimeType:`application/msword`},{ext:`.ps`,mimeType:`application/postscript`},{ext:`.psd`,mimeType:`image/vnd.adobe.photoshop`},{ext:`.p7s`,mimeType:`application/pkcs7-signature`},{ext:`.ogg`,mimeType:`application/ogg`},{ext:`.oga`,mimeType:`audio/ogg`},{ext:`.ogv`,mimeType:`video/ogg`},{ext:`.png`,mimeType:`image/png`},{ext:`.png`,mimeType:`image/vnd.mozilla.apng`},{ext:`.jpg`,mimeType:`image/jpeg`},{ext:`.jxl`,mimeType:`image/jxl`},{ext:`.jp2`,mimeType:`image/jp2`},{ext:`.jpf`,mimeType:`image/jpx`},{ext:`.jpm`,mimeType:`image/jpm`},{ext:`.jxs`,mimeType:`image/jxs`},{ext:`.gif`,mimeType:`image/gif`},{ext:`.webp`,mimeType:`image/webp`},{ext:`.exe`,mimeType:`application/vnd.microsoft.portable-executable`},{ext:``,mimeType:`application/x-elf`},{ext:``,mimeType:`application/x-object`},{ext:``,mimeType:`application/x-executable`},{ext:`.so`,mimeType:`application/x-sharedlib`},{ext:``,mimeType:`application/x-coredump`},{ext:`.a`,mimeType:`application/x-archive`},{ext:`.deb`,mimeType:`application/vnd.debian.binary-package`},{ext:`.tar`,mimeType:`application/x-tar`},{ext:`.xar`,mimeType:`application/x-xar`},{ext:`.bz2`,mimeType:`application/x-bzip2`},{ext:`.fits`,mimeType:`application/fits`},{ext:`.tiff`,mimeType:`image/tiff`},{ext:`.bmp`,mimeType:`image/bmp`},{ext:`.ico`,mimeType:`image/x-icon`},{ext:`.mp3`,mimeType:`audio/mpeg`},{ext:`.flac`,mimeType:`audio/flac`},{ext:`.midi`,mimeType:`audio/midi`},{ext:`.ape`,mimeType:`audio/ape`},{ext:`.mpc`,mimeType:`audio/musepack`},{ext:`.amr`,mimeType:`audio/amr`},{ext:`.wav`,mimeType:`audio/wav`},{ext:`.aiff`,mimeType:`audio/aiff`},{ext:`.au`,mimeType:`audio/basic`},{ext:`.mpeg`,mimeType:`video/mpeg`},{ext:`.mov`,mimeType:`video/quicktime`},{ext:`.mp4`,mimeType:`video/mp4`},{ext:`.avif`,mimeType:`image/avif`},{ext:`.3gp`,mimeType:`video/3gpp`},{ext:`.3g2`,mimeType:`video/3gpp2`},{ext:`.mp4`,mimeType:`audio/mp4`},{ext:`.mqv`,mimeType:`video/quicktime`},{ext:`.m4a`,mimeType:`audio/x-m4a`},{ext:`.m4v`,mimeType:`video/x-m4v`},{ext:`.heic`,mimeType:`image/heic`},{ext:`.heic`,mimeType:`image/heic-sequence`},{ext:`.heif`,mimeType:`image/heif`},{ext:`.heif`,mimeType:`image/heif-sequence`},{ext:`.mj2`,mimeType:`video/mj2`},{ext:`.dvb`,mimeType:`video/vnd.dvb.file`},{ext:`.webm`,mimeType:`video/webm`},{ext:`.avi`,mimeType:`video/x-msvideo`},{ext:`.flv`,mimeType:`video/x-flv`},{ext:`.mkv`,mimeType:`video/x-matroska`},{ext:`.asf`,mimeType:`video/x-ms-asf`},{ext:`.asf`,mimeType:`video/x-ms-wmv`},{ext:`.asf`,mimeType:`video/asf`},{ext:`.aac`,mimeType:`audio/aac`},{ext:`.voc`,mimeType:`audio/x-unknown`},{ext:`.m3u`,mimeType:`application/vnd.apple.mpegurl`},{ext:`.rmvb`,mimeType:`application/vnd.rn-realmedia-vbr`},{ext:`.gz`,mimeType:`application/gzip`},{ext:`.class`,mimeType:`application/x-java-applet`},{ext:`.swf`,mimeType:`application/x-shockwave-flash`},{ext:`.crx`,mimeType:`application/x-chrome-extension`},{ext:`.ttf`,mimeType:`font/ttf`},{ext:`.woff`,mimeType:`font/woff`},{ext:`.woff2`,mimeType:`font/woff2`},{ext:`.otf`,mimeType:`font/otf`},{ext:`.ttc`,mimeType:`font/collection`},{ext:`.eot`,mimeType:`application/vnd.ms-fontobject`},{ext:`.wasm`,mimeType:`application/wasm`},{ext:`.shx`,mimeType:`application/vnd.shx`},{ext:`.shp`,mimeType:`application/vnd.shp`},{ext:`.dbf`,mimeType:`application/x-dbf`},{ext:`.dcm`,mimeType:`application/dicom`},{ext:`.rar`,mimeType:`application/x-rar-compressed`},{ext:`.djvu`,mimeType:`image/vnd.djvu`},{ext:`.mobi`,mimeType:`application/x-mobipocket-ebook`},{ext:`.lit`,mimeType:`application/x-ms-reader`},{ext:`.bpg`,mimeType:`image/bpg`},{ext:`.cbor`,mimeType:`application/cbor`},{ext:`.sqlite`,mimeType:`application/vnd.sqlite3`},{ext:`.dwg`,mimeType:`image/vnd.dwg`},{ext:`.nes`,mimeType:`application/vnd.nintendo.snes.rom`},{ext:`.lnk`,mimeType:`application/x-ms-shortcut`},{ext:`.macho`,mimeType:`application/x-mach-binary`},{ext:`.qcp`,mimeType:`audio/qcelp`},{ext:`.icns`,mimeType:`image/x-icns`},{ext:`.hdr`,mimeType:`image/vnd.radiance`},{ext:`.mrc`,mimeType:`application/marc`},{ext:`.mdb`,mimeType:`application/x-msaccess`},{ext:`.accdb`,mimeType:`application/x-msaccess`},{ext:`.zst`,mimeType:`application/zstd`},{ext:`.cab`,mimeType:`application/vnd.ms-cab-compressed`},{ext:`.rpm`,mimeType:`application/x-rpm`},{ext:`.xz`,mimeType:`application/x-xz`},{ext:`.lz`,mimeType:`application/lzip`},{ext:`.torrent`,mimeType:`application/x-bittorrent`},{ext:`.cpio`,mimeType:`application/x-cpio`},{ext:``,mimeType:`application/tzif`},{ext:`.xcf`,mimeType:`image/x-xcf`},{ext:`.pat`,mimeType:`image/x-gimp-pat`},{ext:`.gbr`,mimeType:`image/x-gimp-gbr`},{ext:`.glb`,mimeType:`model/gltf-binary`},{ext:`.cab`,mimeType:`application/x-installshield`},{ext:`.jxr`,mimeType:`image/jxr`},{ext:`.parquet`,mimeType:`application/vnd.apache.parquet`},{ext:`.txt`,mimeType:`text/plain`},{ext:`.html`,mimeType:`text/html`},{ext:`.svg`,mimeType:`image/svg+xml`},{ext:`.xml`,mimeType:`text/xml`},{ext:`.rss`,mimeType:`application/rss+xml`},{ext:`.atom`,mimeType:`application/atom+xml`},{ext:`.x3d`,mimeType:`model/x3d+xml`},{ext:`.kml`,mimeType:`application/vnd.google-earth.kml+xml`},{ext:`.xlf`,mimeType:`application/x-xliff+xml`},{ext:`.dae`,mimeType:`model/vnd.collada+xml`},{ext:`.gml`,mimeType:`application/gml+xml`},{ext:`.gpx`,mimeType:`application/gpx+xml`},{ext:`.tcx`,mimeType:`application/vnd.garmin.tcx+xml`},{ext:`.amf`,mimeType:`application/x-amf`},{ext:`.3mf`,mimeType:`application/vnd.ms-package.3dmanufacturing-3dmodel+xml`},{ext:`.xfdf`,mimeType:`application/vnd.adobe.xfdf`},{ext:`.owl`,mimeType:`application/owl+xml`},{ext:`.php`,mimeType:`text/x-php`},{ext:`.js`,mimeType:`text/javascript`},{ext:`.lua`,mimeType:`text/x-lua`},{ext:`.pl`,mimeType:`text/x-perl`},{ext:`.py`,mimeType:`text/x-python`},{ext:`.json`,mimeType:`application/json`},{ext:`.geojson`,mimeType:`application/geo+json`},{ext:`.har`,mimeType:`application/json`},{ext:`.ndjson`,mimeType:`application/x-ndjson`},{ext:`.rtf`,mimeType:`text/rtf`},{ext:`.srt`,mimeType:`application/x-subrip`},{ext:`.tcl`,mimeType:`text/x-tcl`},{ext:`.csv`,mimeType:`text/csv`},{ext:`.tsv`,mimeType:`text/tab-separated-values`},{ext:`.vcf`,mimeType:`text/vcard`},{ext:`.ics`,mimeType:`text/calendar`},{ext:`.warc`,mimeType:`application/warc`},{ext:`.vtt`,mimeType:`text/vtt`},{ext:`.pbm`,mimeType:`image/x-portable-bitmap`},{ext:`.pgm`,mimeType:`image/x-portable-graymap`},{ext:`.ppm`,mimeType:`image/x-portable-pixmap`},{ext:`.eml`,mimeType:`message/rfc822`}];var p=new BroadcastChannel(`tabsSync`),m=`pbSettings`,h=`pbColorScheme`;window.app=window.app||{},window.app.store=store({_ready:!1,superuser:null,showHeader:!0,page:t.div({className:`page`},()=>{if(!app.store._ready)return t.span({className:`loader lg m-auto`,title:`Loading plugins...`})}),mainLogo:`./images/logo.svg`,headerLogo:`./images/logo_white.svg`,favicon:``,title:``,_mediaColorScheme:``,userColorScheme:window.localStorage.getItem(h)||``,get activeColorScheme(){return app.store.userColorScheme?app.store.userColorScheme:app.store._mediaColorScheme||`light`},errors:null,creditLinks:[{href:`https://pocketbase.io/docs`,icon:`ri-book-open-line`,label:`Docs`},{href:`https://github.com/pocketbase/pocketbase/releases`,icon:`ri-github-line`,label:`PocketBase v0.40.3`}],headerLinks:[{href:`#/collections`,icon:`ri-database-2-line`,label:`Collections`},{href:`#/logs`,icon:`ri-bar-chart-box-line`,label:`Logs`},{href:`#/settings`,icon:`ri-settings-3-line`,label:`Settings`}],settingsNavGroups:{System:[{href:`#/settings`,icon:`ri-home-gear-line`,label:`Application`},{href:`#/settings/mail`,icon:`ri-send-plane-2-line`,label:`Mail settings`},{href:`#/settings/storage`,icon:`ri-archive-drawer-line`,label:`Files storage`},{href:`#/settings/backups`,icon:`ri-archive-line`,label:`Backups`},{href:`#/settings/crons`,icon:`ri-time-line`,label:`Crons`}],Sync:[{href:`#/settings/export-collections`,icon:`ri-uninstall-line`,label:`Export collections`},{href:`#/settings/import-collections`,icon:`ri-install-line`,label:`Import collections`}],Debug:[{href:`#/settings/sql`,icon:`ri-terminal-box-line`,label:`SQL console`}]},predefinedAccentColors:[`#1055c9`,`#a3142a`,`#096d5c`,`#e6620a`,`#007d9c`,`#3f3da9`],settings:app.utils.getLocalHistory(m,{}),isLoadingSettings:!1,async loadSettings(){app.store.isLoadingSettings=!0;try{let e=await app.pb.settings.getAll({requestKey:`appStore.loadSettings`});app.store.settings=e,app.store.isLoadingSettings=!1}catch(e){e.isAbort||(app.store.isLoadingSettings=!1,app.checkApiError(e))}},collections:[],collectionScaffolds:{},isLoadingCollections:!1,_activeCollectionIdOrName:``,get activeCollection(){let e=app.store._activeCollectionIdOrName;return app.store.collections.find(n=>n.id==e||n.name==e)||app.store.collections[0]},set activeCollection(e){typeof e==`string`?app.store._activeCollectionIdOrName=e:app.store._activeCollectionIdOrName=e?.id},async silentlyReloadCollections(){try{let e=await app.pb.collections.getFullList({requestKey:`appStore.silentlyReloadCollections`});e=app.utils.sortedCollectionsByType(e),JSON.stringify(e)!=JSON.stringify(app.store.collections)&&(app.store.collections=e)}catch(e){e.isAbort||console.warn(`failed to reload app store collections:`,e)}},async loadCollections(e=null){app.store.isLoadingCollections=!0;try{let[n,r]=await Promise.all([app.pb.collections.getScaffolds({requestKey:`appStore.loadCollections.getScaffolds`}),app.pb.collections.getFullList({requestKey:`appStore.loadCollections.getFullList`})]);r=app.utils.sortedCollectionsByType(r),JSON.stringify(app.store.collections)!=JSON.stringify(r)&&(app.store.collections=r),app.store.collectionScaffolds=n,app.store._activeCollectionIdOrName=e||app.store._activeCollectionIdOrName||app.store.collections[0]?.id||``,app.store.isLoadingCollections=!1}catch(e){e.isAbort||(app.store.isLoadingCollections=!1,app.checkApiError(e))}},addOrUpdateCollection(e){let n=app.store.collections.findIndex(n=>n.id==e.id);n>=0?(app.store.activeCollection?.id==e.id&&(app.store._activeCollectionIdOrName=e.id),app.store.collections[n]=e):app.store.collections.push(e),app.store.collections=app.utils.sortedCollectionsByType(app.store.collections)},oauth2Providers:[],isLoadingOAuth2Providers:!1,async loadOAuth2Providers(){app.store.isLoadingOAuth2Providers=!0;try{app.store.oauth2Providers=await app.pb.collections.getAllOAuth2Providers(),app.store.isLoadingOAuth2Providers=!1}catch(e){e.isAbort||(app.checkApiError(e),app.store.isLoadingOAuth2Providers=!1)}}}),window.addEventListener(`hashchange`,()=>{app.store.title=``,app.store.errors=null}),watch(()=>{let e=app.utils.toArray(app.store.title),n=app.store.settings?.meta?.appName||``;n&&e.push(n),document.title=e.join(` - `)});var g;watch(()=>app.store.settings?.meta?.accentColor,e=>{g||(g=t.meta({name:`theme-color`}),document.head.appendChild(g)),e?(g?.setAttribute(`content`,e),document.documentElement.style.setProperty(`--accentColor`,e)):(g?.removeAttribute(`content`),document.documentElement.style.removeProperty(`--accentColor`))});var _;watch(()=>app.store.favicon,e=>{_||(_=t.link({rel:`icon`}),document.head.appendChild(_)),e?_.href=e:_.href=window.location.href.startsWith(`https://`)?`./images/favicon_prod.png`:`./images/favicon.png`});var v=window.matchMedia(`(prefers-color-scheme: dark)`);app.store._mediaColorScheme=v.matches?`dark`:`light`,v.addEventListener(`change`,({matches:e})=>{app.store._mediaColorScheme=e?`dark`:`light`}),watch(()=>app.store.userColorScheme,e=>{e?window.localStorage.setItem(h,e):window.localStorage.removeItem(h),p?.postMessage({colorScheme:e})});var ee;watch(()=>app.store.activeColorScheme,e=>{clearTimeout(ee),document.documentElement.style.setProperty(`--animationSpeed`,`0`),document.documentElement.setAttribute(`data-color-scheme`,e),ee=setTimeout(()=>{document.documentElement.style.removeProperty(`--animationSpeed`)},100)});function te(e,n){e.__errListener&&=(e.removeEventListener(`input`,e.__errListener),e.removeEventListener(`change`,e.__errListener),null),e.setCustomValidity&&(e.setCustomValidity(``),e._oldTitle?e.setAttribute(`title`,e._oldTitle):e.removeAttribute(`title`)),e.removeAttribute(`data-error`);let r=n.nextSibling;r&&r.classList?.contains(`generated-error`)&&r.getAttribute(`data-input-name`)==e.getAttribute(`name`)&&r.remove(),n.querySelector(`[data-error]`)||n.classList.remove(`error`)}watch(()=>JSON.stringify(app.store.errors)&&app.store.errors,e=>{let n=document.querySelectorAll(`[name]`);for(let r of n){if(r.classList.contains(`no-error`))continue;let n=r.closest(`.field-list`)||r.closest(`.fields`)||r.closest(`.field`);if(!n)continue;let i=r.getAttribute(`name`);te(r,n);let a=app.utils.getByPath(e,i),o=a?.message||``;if(!o&&!app.utils.isEmpty(a)){let e=[];for(let n in a)a[n]?.message&&e.push(`${n}: ${a[n]?.message}`);o=e.join(` `)}o&&(n.classList.add(`error`),r.__errListener=function(){te(r,n),app.utils.deleteByPath(app.store.errors,i)},r.addEventListener(`input`,r.__errListener),r.addEventListener(`change`,r.__errListener),r.setAttribute(`data-error`,!0),r.setCustomValidity&&r.reportValidity&&r.classList.contains(`inline-error`)?(r.setCustomValidity(o),r.reportValidity(),r._oldTitle=r.title,r.title=o):n.after(t.div({"html-data-input-name":i,className:`field-help error generated-error`,textContent:o})))}}),p.onmessage=e=>{e.data?.collections&&JSON.stringify(app.store.collections)!=JSON.stringify(e.data.collections)&&(app.store.collections=e.data.collections),e.data?.settings&&JSON.stringify(app.store.settings)!=JSON.stringify(e.data.settings)&&(app.store.settings=e.data.settings),e.data?.colorScheme&&(app.store.userColorScheme=e.data.colorScheme)},watch(()=>JSON.stringify(app.store.collections),(e,n)=>{e&&e!=`[]`&&n&&n!=`[]`&&e!=n&&p?.postMessage({collections:JSON.parse(e)})}),watch(()=>JSON.stringify(app.store.settings),(e,n)=>{e&&e!=`{}`&&n&&n!=`{}`&&e!=n&&p?.postMessage({settings:JSON.parse(e)}),window.localStorage.setItem(m,e)});var y=class e extends Error{constructor(n){super(`ClientResponseError`),this.url=``,this.status=0,this.response={},this.isAbort=!1,this.originalError=null,Object.setPrototypeOf(this,e.prototype),typeof n==`object`&&n&&(this.originalError=n.originalError,this.url=typeof n.url==`string`?n.url:``,this.status=typeof n.status==`number`?n.status:0,this.isAbort=!!n.isAbort||n.name===`AbortError`||n.message===`Aborted`,this.response=n.response!==null&&typeof n.response==`object`?n.response:n.data!==null&&typeof n.data==`object`?n.data:{}),this.originalError||n instanceof e||(this.originalError=n),this.name=`ClientResponseError `+this.status,this.message=this.response?.message,this.message||=this.isAbort?`The request was aborted (most likely autocancelled; you can find more info in https://github.com/pocketbase/js-sdk#auto-cancellation).`:this.originalError?.cause?.message?.includes(`ECONNREFUSED ::1`)?`Failed to connect to the PocketBase server. Try changing the SDK URL from localhost to 127.0.0.1 (https://github.com/pocketbase/js-sdk/issues/21).`:`Something went wrong.`,this.cause=this.originalError}get data(){return this.response}toJSON(){return{...this}}},ne=/^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;function re(e,n){let r={};if(typeof e!=`string`)return r;let i=Object.assign({},n||{}).decode||ae,a=0;for(;a0&&(!r.exp||r.exp-n>Date.now()/1e3))}oe=typeof atob!=`function`||x?e=>{let n=String(e).replace(/=+$/,``);if(n.length%4==1)throw Error(`'atob' failed: The string to be decoded is not correctly encoded.`);for(var r,i,a=0,o=0,s=``;i=n.charAt(o++);~i&&(r=a%4?64*r+i:i,a++%4)&&(s+=String.fromCharCode(255&r>>(-2*a&6))))i=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=`.indexOf(i);return s}:atob;var C=`pb_auth`,ce=class{constructor(){this.baseToken=``,this.baseModel=null,this._onChangeCallbacks=[]}get token(){return this.baseToken}get record(){return this.baseModel}get model(){return this.baseModel}get isValid(){return!se(this.token)}get isSuperuser(){let e=S(this.token);return e.type==`auth`&&(this.record?.collectionName==`_superusers`||!this.record?.collectionName&&e.collectionId==`pbc_3142635823`)}get isAdmin(){return console.warn(`Please replace pb.authStore.isAdmin with pb.authStore.isSuperuser OR simply check the value of pb.authStore.record?.collectionName`),this.isSuperuser}get isAuthRecord(){return console.warn(`Please replace pb.authStore.isAuthRecord with !pb.authStore.isSuperuser OR simply check the value of pb.authStore.record?.collectionName`),S(this.token).type==`auth`&&!this.isSuperuser}save(e,n){this.baseToken=e||``,this.baseModel=n||null,this.triggerChange()}clear(){this.baseToken=``,this.baseModel=null,this.triggerChange()}loadFromCookie(e,n=C){let r=re(e||``)[n]||``,i={};try{i=JSON.parse(r),(typeof i!=`object`||Array.isArray(i))&&(i={})}catch{}this.save(i.token||``,i.record||i.model||null)}exportToCookie(e,n=C){let r={secure:!0,sameSite:!0,httpOnly:!0,path:`/`},i=S(this.token);r.expires=i?.exp?new Date(1e3*i.exp):new Date(`1970-01-01`),e=Object.assign({},r,e);let a={token:this.token,record:this.record?JSON.parse(JSON.stringify(this.record)):null},o=ie(n,JSON.stringify(a),e),s=typeof Blob<`u`?new Blob([o]).size:o.length;if(a.record&&s>4096){a.record={id:a.record?.id,email:a.record?.email};let r=[`collectionId`,`collectionName`,`verified`];for(let e in this.record)r.includes(e)&&(a.record[e]=this.record[e]);o=ie(n,JSON.stringify(a),e)}return o}onChange(e,n=!1){return this._onChangeCallbacks.push(e),n&&e(this.token,this.record),()=>{for(let n=this._onChangeCallbacks.length-1;n>=0;n--)if(this._onChangeCallbacks[n]==e)return delete this._onChangeCallbacks[n],void this._onChangeCallbacks.splice(n,1)}}triggerChange(){for(let e of this._onChangeCallbacks)e&&e(this.token,this.record)}},w=class extends ce{constructor(e=`pocketbase_auth`){super(),this.storageFallback={},this.storageKey=e,this._bindStorageEvent()}get token(){return(this._storageGet(this.storageKey)||{}).token||``}get record(){let e=this._storageGet(this.storageKey)||{};return e.record||e.model||null}get model(){return this.record}save(e,n){this._storageSet(this.storageKey,{token:e,record:n}),super.save(e,n)}clear(){this._storageRemove(this.storageKey),super.clear()}_storageGet(e){if(typeof window<`u`&&window?.localStorage){let n=window.localStorage.getItem(e)||``;try{return JSON.parse(n)}catch{return n}}return this.storageFallback[e]}_storageSet(e,n){if(typeof window<`u`&&window?.localStorage){let r=n;typeof n!=`string`&&(r=JSON.stringify(n)),window.localStorage.setItem(e,r)}else this.storageFallback[e]=n}_storageRemove(e){typeof window<`u`&&window?.localStorage&&window.localStorage?.removeItem(e),delete this.storageFallback[e]}_bindStorageEvent(){typeof window<`u`&&window?.localStorage&&window.addEventListener&&window.addEventListener(`storage`,(e=>{if(e.key!=this.storageKey)return;let n=this._storageGet(this.storageKey)||{};super.save(n.token||``,n.record||n.model||null)}))}},T=class{constructor(e){this.client=e}},E=class extends T{async getAll(e){return e=Object.assign({method:`GET`},e),this.client.send(`/api/settings`,e)}async update(e,n){return n=Object.assign({method:`PATCH`,body:e},n),this.client.send(`/api/settings`,n)}async testS3(e=`storage`,n){return n=Object.assign({method:`POST`,body:{filesystem:e}},n),this.client.send(`/api/settings/test/s3`,n).then((()=>!0))}async testEmail(e,n,r,i){return i=Object.assign({method:`POST`,body:{email:n,template:r,collection:e}},i),this.client.send(`/api/settings/test/email`,i).then((()=>!0))}async generateAppleClientSecret(e,n,r,i,a,o){return o=Object.assign({method:`POST`,body:{clientId:e,teamId:n,keyId:r,privateKey:i,duration:a}},o),this.client.send(`/api/settings/apple/generate-client-secret`,o)}},D=[`requestKey`,`$cancelKey`,`$autoCancel`,`fetch`,`headers`,`body`,`query`,`params`,`cache`,`credentials`,`headers`,`integrity`,`keepalive`,`method`,`mode`,`redirect`,`referrer`,`referrerPolicy`,`signal`,`window`];function O(e){if(e){e.query=e.query||{};for(let n in e)D.includes(n)||(e.query[n]=e[n],delete e[n])}}function k(e){let n=[];for(let r in e){let i=encodeURIComponent(r),a=Array.isArray(e[r])?e[r]:[e[r]];for(let e of a)e=A(e),e!==null&&n.push(i+`=`+e)}return n.join(`&`)}function A(e){return e==null?null:e instanceof Date?encodeURIComponent(e.toISOString().replace(`T`,` `)):encodeURIComponent(typeof e==`object`?JSON.stringify(e):e)}var j=class extends T{constructor(){super(...arguments),this.clientId=``,this.eventSource=null,this.subscriptions={},this.lastSentSubscriptions=[],this.maxConnectTimeout=15e3,this.reconnectAttempts=0,this.maxReconnectAttempts=1/0,this.predefinedReconnectIntervals=[200,300,500,1e3,1200,1500,2e3],this.pendingConnects=[],this.pendingSubmits=[],this.isProcessingPendingSubmits=!1}get isConnected(){return!!this.eventSource&&!!this.clientId&&!this.pendingConnects.length}async subscribe(e,n,r){if(!e)throw Error(`topic must be set.`);let i=e;if(r){O(r=Object.assign({},r));let e=`options=`+encodeURIComponent(JSON.stringify({query:r.query,headers:r.headers}));i+=(i.includes(`?`)?`&`:`?`)+e}let a=function(e){let r=e,i;try{i=JSON.parse(r?.data)}catch{}n(i||{})};return this.subscriptions[i]||(this.subscriptions[i]=[]),this.subscriptions[i].push(a),this.isConnected?this.subscriptions[i].length===1?await this.submitSubscriptions():this.eventSource?.addEventListener(i,a):await this.connect(),async()=>this.unsubscribeByTopicAndListener(e,a)}async unsubscribe(e){if(e){let n=this.getSubscriptionsByTopic(e);for(let e in n)if(this.hasSubscriptionListeners(e)){for(let n of this.subscriptions[e])this.eventSource?.removeEventListener(e,n);delete this.subscriptions[e]}}else this.subscriptions={};await this.submitSubscriptions()}async unsubscribeByPrefix(e){let n=!1;for(let r in this.subscriptions)if((r+`?`).startsWith(e)){n=!0;for(let e of this.subscriptions[r])this.eventSource?.removeEventListener(r,e);delete this.subscriptions[r]}n&&await this.submitSubscriptions()}async unsubscribeByTopicAndListener(e,n){let r=this.getSubscriptionsByTopic(e);for(let e in r){if(!Array.isArray(this.subscriptions[e])||!this.subscriptions[e].length)continue;let r=!1;for(let i=this.subscriptions[e].length-1;i>=0;i--)this.subscriptions[e][i]===n&&(r=!0,delete this.subscriptions[e][i],this.subscriptions[e].splice(i,1),this.eventSource?.removeEventListener(e,n));r&&(this.subscriptions[e].length||delete this.subscriptions[e])}await this.submitSubscriptions()}hasSubscriptionListeners(e){if(this.subscriptions=this.subscriptions||{},e)return!!this.subscriptions[e]?.length;for(let e in this.subscriptions)if(this.subscriptions[e]?.length)return!0;return!1}async submitSubscriptions(){return new Promise(((e,n)=>{this.pendingSubmits.push({resolve:e,reject:n}),this.pendingSubmits.length==1&&queueMicrotask((()=>this.finalizePendingSubscriptions()))}))}async finalizePendingSubscriptions(){if(this.isProcessingPendingSubmits||!this.pendingSubmits.length)return;let e=this.pendingSubmits.slice();this.pendingSubmits=[],this.isProcessingPendingSubmits=!0;try{await this.sendSubscriptions();for(let n of e)n.resolve()}catch(n){for(let r of e)n?r.reject(n):r.resolve()}finally{this.isProcessingPendingSubmits=!1,this.pendingSubmits.length>0&&await this.finalizePendingSubscriptions()}}getSubscriptionsCancelKey(){return`realtime_`+this.clientId}getSubscriptionsByTopic(e){let n={};e=e.includes(`?`)?e:e+`?`;for(let r in this.subscriptions)(r+`?`).startsWith(e)&&(n[r]=this.subscriptions[r]);return n}getNonEmptySubscriptionKeys(){let e=[];for(let n in this.subscriptions)this.subscriptions[n].length&&e.push(n);return e}hasUnsentSubscriptions(){let e=this.getNonEmptySubscriptionKeys();if(e.length!=this.lastSentSubscriptions.length)return!0;for(let n of e)if(!this.lastSentSubscriptions.includes(n))return!0;return!1}async sendSubscriptions(){if(this.clientId){if(!this.hasSubscriptionListeners())return this.disconnect();if(this.hasUnsentSubscriptions())return this.addAllSubscriptionListeners(),this.lastSentSubscriptions=this.getNonEmptySubscriptionKeys(),this.client.send(`/api/realtime`,{method:`POST`,body:{clientId:this.clientId,subscriptions:this.lastSentSubscriptions},requestKey:this.getSubscriptionsCancelKey()}).catch((e=>{if(!e?.isAbort)throw e}))}}addAllSubscriptionListeners(){if(this.eventSource){this.removeAllSubscriptionListeners();for(let e in this.subscriptions)for(let n of this.subscriptions[e])this.eventSource.addEventListener(e,n)}}removeAllSubscriptionListeners(){if(this.eventSource)for(let e in this.subscriptions)for(let n of this.subscriptions[e])this.eventSource.removeEventListener(e,n)}async connect(){if(!(this.reconnectAttempts>0))return new Promise(((e,n)=>{this.pendingConnects.push({resolve:e,reject:n}),this.pendingConnects.length==1&&queueMicrotask((()=>this.initConnect()))}))}initConnect(){this.disconnect(!0),clearTimeout(this.connectTimeoutId),this.connectTimeoutId=setTimeout((()=>{this.connectErrorHandler(Error(`EventSource connect took too long.`))}),this.maxConnectTimeout),this.eventSource=new EventSource(this.client.buildURL(`/api/realtime`)),this.eventSource.onerror=e=>{this.connectErrorHandler(Error(`Failed to establish realtime connection.`))},this.eventSource.addEventListener(`PB_CONNECT`,(e=>{let n=e;this.clientId=n?.lastEventId,this.lastSentSubscriptions=[],this.submitSubscriptions().then((async()=>{let n=3;for(;this.hasUnsentSubscriptions()&&n>0;)n--,await this.submitSubscriptions();for(let e of this.pendingConnects)e.resolve();this.pendingConnects=[],this.reconnectAttempts=0,clearTimeout(this.reconnectTimeoutId),clearTimeout(this.connectTimeoutId);let r=this.getSubscriptionsByTopic(`PB_CONNECT`);for(let n in r)for(let i of r[n])i(e);this.hasUnsentSubscriptions()&&await this.submitSubscriptions()})).catch((e=>{this.clientId=``,this.lastSentSubscriptions=[],this.connectErrorHandler(e)}))}))}connectErrorHandler(e){if(clearTimeout(this.connectTimeoutId),clearTimeout(this.reconnectTimeoutId),!this.clientId&&!this.reconnectAttempts||this.reconnectAttempts>this.maxReconnectAttempts){for(let n of this.pendingConnects)n.reject(new y(e));this.pendingConnects=[],this.disconnect();return}this.disconnect(!0);let n=this.predefinedReconnectIntervals[this.reconnectAttempts]||this.predefinedReconnectIntervals[this.predefinedReconnectIntervals.length-1];this.reconnectAttempts++,this.reconnectTimeoutId=setTimeout((()=>{this.initConnect()}),n)}disconnect(e=!1){if(this.clientId&&this.onDisconnect&&this.onDisconnect(Object.keys(this.subscriptions)),clearTimeout(this.connectTimeoutId),clearTimeout(this.reconnectTimeoutId),this.removeAllSubscriptionListeners(),this.client.cancelRequest(this.getSubscriptionsCancelKey()),this.eventSource?.close(),this.eventSource=null,this.clientId=``,this.lastSentSubscriptions=[],!e){this.reconnectAttempts=0;for(let e of this.pendingConnects)e.resolve();this.pendingConnects=[]}}},M=class extends T{decode(e){return e}async getFullList(e,n){if(typeof e==`number`)return this._getFullList(e,n);let r=1e3;return(n=Object.assign({},e,n)).batch&&(r=n.batch,delete n.batch),this._getFullList(r,n)}async getList(e=1,n=30,r){return(r=Object.assign({method:`GET`},r)).query=Object.assign({page:e,perPage:n},r.query),this.client.send(this.baseCrudPath,r).then((e=>(e.items=e.items?.map((e=>this.decode(e)))||[],e)))}async getFirstListItem(e,n){return(n=Object.assign({requestKey:`one_by_filter_`+this.baseCrudPath+`_`+e},n)).query=Object.assign({filter:e,skipTotal:1},n.query),this.getList(1,1,n).then((e=>{if(!e?.items?.length)throw new y({status:404,response:{code:404,message:`The requested resource wasn't found.`,data:{}}});return e.items[0]}))}async getOne(e,n){if(!e)throw new y({url:this.client.buildURL(this.baseCrudPath+`/`),status:404,response:{code:404,message:`Missing required record id.`,data:{}}});return n=Object.assign({method:`GET`},n),this.client.send(this.baseCrudPath+`/`+encodeURIComponent(e),n).then((e=>this.decode(e)))}async create(e,n){return n=Object.assign({method:`POST`,body:e},n),this.client.send(this.baseCrudPath,n).then((e=>this.decode(e)))}async update(e,n,r){return r=Object.assign({method:`PATCH`,body:n},r),this.client.send(this.baseCrudPath+`/`+encodeURIComponent(e),r).then((e=>this.decode(e)))}async delete(e,n){return n=Object.assign({method:`DELETE`},n),this.client.send(this.baseCrudPath+`/`+encodeURIComponent(e),n).then((()=>!0))}_getFullList(e=1e3,n){(n||={}).query=Object.assign({skipTotal:1},n.query);let r=[],i=async a=>this.getList(a,e||1e3,n).then((e=>{let n=e.items;return r=r.concat(n),n.length==e.perPage?i(a+1):r}));return i(1)}};function N(e,n,r,i){let a=i!==void 0;return a||r!==void 0?a?(console.warn(e),n.body=Object.assign({},n.body,r),n.query=Object.assign({},n.query,i),n):Object.assign(n,r):n}function le(e){e._resetAutoRefresh?.()}var ue=class extends M{constructor(e,n){super(e),this.collectionIdOrName=n}get baseCrudPath(){return this.baseCollectionPath+`/records`}get baseCollectionPath(){return`/api/collections/`+encodeURIComponent(this.collectionIdOrName)}get isSuperusers(){return this.collectionIdOrName==`_superusers`||this.collectionIdOrName==`_pbc_2773867675`}async subscribe(e,n,r){if(!e)throw Error(`Missing topic.`);if(!n)throw Error(`Missing subscription callback.`);return this.client.realtime.subscribe(this.collectionIdOrName+`/`+e,n,r)}async unsubscribe(e){return e?this.client.realtime.unsubscribe(this.collectionIdOrName+`/`+e):this.client.realtime.unsubscribeByPrefix(this.collectionIdOrName)}async getFullList(e,n){if(typeof e==`number`)return super.getFullList(e,n);let r=Object.assign({},e,n);return super.getFullList(r)}async getList(e=1,n=30,r){return super.getList(e,n,r)}async getFirstListItem(e,n){return super.getFirstListItem(e,n)}async getOne(e,n){return super.getOne(e,n)}async create(e,n){return super.create(e,n)}async update(e,n,r){return super.update(e,n,r).then((e=>{if(this.client.authStore.record?.id===e?.id&&(this.client.authStore.record?.collectionId===this.collectionIdOrName||this.client.authStore.record?.collectionName===this.collectionIdOrName)){let n=Object.assign({},this.client.authStore.record.expand),r=Object.assign({},this.client.authStore.record,e);n&&(r.expand=Object.assign(n,e.expand)),this.client.authStore.save(this.client.authStore.token,r)}return e}))}async delete(e,n){return super.delete(e,n).then((n=>(!n||this.client.authStore.record?.id!==e||this.client.authStore.record?.collectionId!==this.collectionIdOrName&&this.client.authStore.record?.collectionName!==this.collectionIdOrName||this.client.authStore.clear(),n)))}authResponse(e){let n=this.decode(e?.record||{});return this.client.authStore.save(e?.token,n),Object.assign({},e,{token:e?.token||``,record:n})}async listAuthMethods(e){return e=Object.assign({method:`GET`,fields:`mfa,otp,password,oauth2`},e),this.client.send(this.baseCollectionPath+`/auth-methods`,e)}async authWithPassword(e,n,r){let i;r=Object.assign({method:`POST`,body:{identity:e,password:n}},r),this.isSuperusers&&(i=r.autoRefreshThreshold,delete r.autoRefreshThreshold,r.autoRefresh||le(this.client));let a=await this.client.send(this.baseCollectionPath+`/auth-with-password`,r);return a=this.authResponse(a),i&&this.isSuperusers&&function(e,n,r,i){le(e);let a=e.beforeSend,o=e.authStore.record,s=e.authStore.onChange(((n,r)=>{(!n||r?.id!=o?.id||(r?.collectionId||o?.collectionId)&&r?.collectionId!=o?.collectionId)&&le(e)}));e._resetAutoRefresh=function(){s(),e.beforeSend=a,delete e._resetAutoRefresh},e.beforeSend=async(o,s)=>{let c=e.authStore.token;if(s.query?.autoRefresh)return a?a(o,s):{url:o,sendOptions:s};let l=e.authStore.isValid;if(l&&se(e.authStore.token,n))try{await r()}catch{l=!1}l||await i();let u=s.headers||{};for(let n in u)if(n.toLowerCase()==`authorization`&&c==u[n]&&e.authStore.token){u[n]=e.authStore.token;break}return s.headers=u,a?a(o,s):{url:o,sendOptions:s}}}(this.client,i,(()=>this.authRefresh({autoRefresh:!0})),(()=>this.authWithPassword(e,n,Object.assign({autoRefresh:!0},r)))),a}async authWithOAuth2Code(e,n,r,i,a,o,s){let c={method:`POST`,body:{provider:e,code:n,codeVerifier:r,redirectURL:i,createData:a}};return c=N(`This form of authWithOAuth2Code(provider, code, codeVerifier, redirectURL, createData?, body?, query?) is deprecated. Consider replacing it with authWithOAuth2Code(provider, code, codeVerifier, redirectURL, createData?, options?).`,c,o,s),this.client.send(this.baseCollectionPath+`/auth-with-oauth2`,c).then((e=>this.authResponse(e)))}authWithOAuth2(...e){if(e.length>1||typeof e?.[0]==`string`)return console.warn(`PocketBase: This form of authWithOAuth2() is deprecated and may get removed in the future. Please replace with authWithOAuth2Code() OR use the authWithOAuth2() realtime form as shown in https://pocketbase.io/docs/authentication/#oauth2-integration.`),this.authWithOAuth2Code(e?.[0]||``,e?.[1]||``,e?.[2]||``,e?.[3]||``,e?.[4]||{},e?.[5]||{},e?.[6]||{});let n=e?.[0]||{},r=null;n.urlCallback||(r=de(void 0));let i=new j(this.client);function a(){r?.close(),i.unsubscribe()}let o={},s=n.requestKey;return s&&(o.requestKey=s),this.listAuthMethods(o).then((e=>{let o=e.oauth2.providers.find((e=>e.name===n.provider));if(!o)throw new y(Error(`Missing or invalid provider "${n.provider}".`));let c=this.client.buildURL(`/api/oauth2-redirect`);return new Promise((async(e,l)=>{let u=s?this.client.cancelControllers?.[s]:void 0;u&&(u.signal.onabort=()=>{a(),l(new y({isAbort:!0,message:`manually cancelled`}))}),i.onDisconnect=e=>{e.length&&l&&(a(),l(new y(Error(`realtime connection interrupted`))))};try{await i.subscribe(`@oauth2`,(async r=>{let s=i.clientId;try{if(!r.state||s!==r.state)throw Error(`State parameters don't match.`);if(r.error||!r.code)throw Error(`OAuth2 redirect error or missing code: `+r.error);let i=Object.assign({},n);delete i.provider,delete i.scopes,delete i.createData,delete i.urlCallback,u?.signal?.onabort&&(u.signal.onabort=null),e(await this.authWithOAuth2Code(o.name,r.code,o.codeVerifier,c,n.createData,i))}catch(e){l(new y(e))}a()}));let s={state:i.clientId};n.scopes?.length&&(s.scope=n.scopes.join(` `));let d=this._replaceQueryParams(o.authURL+c,s);await(n.urlCallback||function(e){r?r.location.href=e:r=de(e)})(d)}catch(e){u?.signal?.onabort&&(u.signal.onabort=null),a(),l(new y(e))}}))})).catch((e=>{throw a(),e}))}async authRefresh(e,n){let r={method:`POST`};return r=N(`This form of authRefresh(body?, query?) is deprecated. Consider replacing it with authRefresh(options?).`,r,e,n),this.client.send(this.baseCollectionPath+`/auth-refresh`,r).then((e=>this.authResponse(e)))}async requestPasswordReset(e,n,r){let i={method:`POST`,body:{email:e}};return i=N(`This form of requestPasswordReset(email, body?, query?) is deprecated. Consider replacing it with requestPasswordReset(email, options?).`,i,n,r),this.client.send(this.baseCollectionPath+`/request-password-reset`,i).then((()=>!0))}async confirmPasswordReset(e,n,r,i,a){let o={method:`POST`,body:{token:e,password:n,passwordConfirm:r}};return o=N(`This form of confirmPasswordReset(token, password, passwordConfirm, body?, query?) is deprecated. Consider replacing it with confirmPasswordReset(token, password, passwordConfirm, options?).`,o,i,a),this.client.send(this.baseCollectionPath+`/confirm-password-reset`,o).then((()=>!0))}async requestVerification(e,n,r){let i={method:`POST`,body:{email:e}};return i=N(`This form of requestVerification(email, body?, query?) is deprecated. Consider replacing it with requestVerification(email, options?).`,i,n,r),this.client.send(this.baseCollectionPath+`/request-verification`,i).then((()=>!0))}async confirmVerification(e,n,r){let i={method:`POST`,body:{token:e}};return i=N(`This form of confirmVerification(token, body?, query?) is deprecated. Consider replacing it with confirmVerification(token, options?).`,i,n,r),this.client.send(this.baseCollectionPath+`/confirm-verification`,i).then((()=>{let n=S(e),r=this.client.authStore.record;return r&&!r.verified&&r.id===n.id&&r.collectionId===n.collectionId&&(r.verified=!0,this.client.authStore.save(this.client.authStore.token,r)),!0}))}async requestEmailChange(e,n,r){let i={method:`POST`,body:{newEmail:e}};return i=N(`This form of requestEmailChange(newEmail, body?, query?) is deprecated. Consider replacing it with requestEmailChange(newEmail, options?).`,i,n,r),this.client.send(this.baseCollectionPath+`/request-email-change`,i).then((()=>!0))}async confirmEmailChange(e,n,r,i){let a={method:`POST`,body:{token:e,password:n}};return a=N(`This form of confirmEmailChange(token, password, body?, query?) is deprecated. Consider replacing it with confirmEmailChange(token, password, options?).`,a,r,i),this.client.send(this.baseCollectionPath+`/confirm-email-change`,a).then((()=>{let n=S(e),r=this.client.authStore.record;return r&&r.id===n.id&&r.collectionId===n.collectionId&&this.client.authStore.clear(),!0}))}async listExternalAuths(e,n){return this.client.collection(`_externalAuths`).getFullList(Object.assign({},n,{filter:this.client.filter(`recordRef = {:id}`,{id:e})}))}async unlinkExternalAuth(e,n,r){let i=await this.client.collection(`_externalAuths`).getFirstListItem(this.client.filter(`recordRef = {:recordId} && provider = {:provider}`,{recordId:e,provider:n}));return this.client.collection(`_externalAuths`).delete(i.id,r).then((()=>!0))}async requestOTP(e,n){return n=Object.assign({method:`POST`,body:{email:e}},n),this.client.send(this.baseCollectionPath+`/request-otp`,n)}async authWithOTP(e,n,r){return r=Object.assign({method:`POST`,body:{otpId:e,password:n}},r),this.client.send(this.baseCollectionPath+`/auth-with-otp`,r).then((e=>this.authResponse(e)))}async impersonate(e,n,r){(r=Object.assign({method:`POST`,body:{duration:n}},r)).headers=r.headers||{},r.headers.Authorization||(r.headers.Authorization=this.client.authStore.token);let i=new Ee(this.client.baseURL,new ce,this.client.lang),a=await i.send(this.baseCollectionPath+`/impersonate/`+encodeURIComponent(e),r);return i.authStore.save(a?.token,this.decode(a?.record||{})),i}_replaceQueryParams(e,n={}){let r=e,i=``;e.indexOf(`?`)>=0&&(r=e.substring(0,e.indexOf(`?`)),i=e.substring(e.indexOf(`?`)+1));let a={},o=i.split(`&`);for(let e of o){if(e==``)continue;let n=e.split(`=`);a[decodeURIComponent(n[0].replace(/\+/g,` `))]=decodeURIComponent((n[1]||``).replace(/\+/g,` `))}for(let e in n)n.hasOwnProperty(e)&&(n[e]==null?delete a[e]:a[e]=n[e]);i=``;for(let e in a)a.hasOwnProperty(e)&&(i!=``&&(i+=`&`),i+=encodeURIComponent(e.replace(/%20/g,`+`))+`=`+encodeURIComponent(a[e].replace(/%20/g,`+`)));return i==``?r:r+`?`+i}};function de(e){if(typeof window>`u`||!window?.open)throw new y(Error(`Not in a browser context - please pass a custom urlCallback function.`));let n=1024,r=768,i=window.innerWidth,a=window.innerHeight;n=n>i?i:n,r=r>a?a:r;let o=i/2-n/2,s=a/2-r/2;return window.open(e,`popup_window`,`width=`+n+`,height=`+r+`,top=`+s+`,left=`+o+`,resizable,menubar=no`)}var fe=class extends M{get baseCrudPath(){return`/api/collections`}async import(e,n=!1,r){return r=Object.assign({method:`PUT`,body:{collections:e,deleteMissing:n}},r),this.client.send(this.baseCrudPath+`/import`,r).then((()=>!0))}async truncate(e,n){return n=Object.assign({method:`DELETE`},n),this.client.send(this.baseCrudPath+`/`+encodeURIComponent(e)+`/truncate`,n).then((()=>!0))}async getScaffolds(e){return e=Object.assign({method:`GET`},e),this.client.send(this.baseCrudPath+`/meta/scaffolds`,e)}async getAllOAuth2Providers(e){return e=Object.assign({method:`GET`},e),this.client.send(this.baseCrudPath+`/meta/oauth2-providers`,e)}async dryRunViewQuery(e,n){return n=Object.assign({method:`POST`,body:{query:e}},n),this.client.send(this.baseCrudPath+`/meta/dry-run-view`,n)}},pe=class extends T{async getList(e=1,n=30,r){return(r=Object.assign({method:`GET`},r)).query=Object.assign({page:e,perPage:n},r.query),this.client.send(`/api/logs`,r)}async getOne(e,n){if(!e)throw new y({url:this.client.buildURL(`/api/logs/`),status:404,response:{code:404,message:`Missing required log id.`,data:{}}});return n=Object.assign({method:`GET`},n),this.client.send(`/api/logs/`+encodeURIComponent(e),n)}async getStats(e){return e=Object.assign({method:`GET`},e),this.client.send(`/api/logs/stats`,e)}async truncate(e){return e=Object.assign({method:`DELETE`},e),this.client.send(`/api/logs`,e).then((()=>!0))}},me=class extends T{async check(e){return e=Object.assign({method:`GET`},e),this.client.send(`/api/health`,e)}},he=class extends T{getUrl(e,n,r={}){return console.warn(`Please replace pb.files.getUrl() with pb.files.getURL()`),this.getURL(e,n,r)}getURL(e,n,r={}){if(!n||!e?.id||!e?.collectionId&&!e?.collectionName)return``;let i=[];i.push(`api`),i.push(`files`),i.push(encodeURIComponent(e.collectionId||e.collectionName)),i.push(encodeURIComponent(e.id)),i.push(encodeURIComponent(n));let a=this.client.buildURL(i.join(`/`));!1===r.download&&delete r.download;let o=k(r);return o&&(a+=(a.includes(`?`)?`&`:`?`)+o),a}async getToken(e){return e=Object.assign({method:`POST`},e),this.client.send(`/api/files/token`,e).then((e=>e?.token||``))}},ge=class extends T{async getFullList(e){return e=Object.assign({method:`GET`},e),this.client.send(`/api/backups`,e)}async create(e,n){return n=Object.assign({method:`POST`,body:{name:e}},n),this.client.send(`/api/backups`,n).then((()=>!0))}async upload(e,n){return n=Object.assign({method:`POST`,body:e},n),this.client.send(`/api/backups/upload`,n).then((()=>!0))}async delete(e,n){return n=Object.assign({method:`DELETE`},n),this.client.send(`/api/backups/${encodeURIComponent(e)}`,n).then((()=>!0))}async restore(e,n){return n=Object.assign({method:`POST`},n),this.client.send(`/api/backups/${encodeURIComponent(e)}/restore`,n).then((()=>!0))}getDownloadUrl(e,n){return console.warn(`Please replace pb.backups.getDownloadUrl() with pb.backups.getDownloadURL()`),this.getDownloadURL(e,n)}getDownloadURL(e,n){return this.client.buildURL(`/api/backups/${encodeURIComponent(n)}?token=${encodeURIComponent(e)}`)}},_e=class extends T{async getFullList(e){return e=Object.assign({method:`GET`},e),this.client.send(`/api/crons`,e)}async run(e,n){return n=Object.assign({method:`POST`},n),this.client.send(`/api/crons/${encodeURIComponent(e)}`,n).then((()=>!0))}},ve=class extends T{async run(e,n){return n=Object.assign({method:`POST`,body:{query:e}},n),this.client.send(`/api/sql`,n)}};function ye(e){return typeof Blob<`u`&&e instanceof Blob||typeof File<`u`&&e instanceof File||typeof e==`object`&&!!e&&e.uri&&(typeof navigator<`u`&&navigator.product===`ReactNative`||typeof global<`u`&&global.HermesInternal)}function be(e){return e&&(e.constructor?.name===`FormData`||typeof FormData<`u`&&e instanceof FormData)}function xe(e){for(let n in e){let r=Array.isArray(e[n])?e[n]:[e[n]];for(let e of r)if(ye(e))return!0}return!1}var Se=/^[\-\.\d]+$/;function Ce(e){if(typeof e!=`string`)return e;if(e==`true`)return!0;if(e==`false`)return!1;if((e[0]===`-`||e[0]>=`0`&&e[0]<=`9`)&&Se.test(e)){let n=+e;if(``+n===e)return n}return e}var we=class extends T{constructor(){super(...arguments),this.requests=[],this.subs={}}collection(e){return this.subs[e]||(this.subs[e]=new Te(this.requests,e)),this.subs[e]}async send(e){let n=new FormData,r=[];for(let e=0;e{if(r===`@jsonPayload`&&typeof e==`string`)try{let r=JSON.parse(e);Object.assign(n,r)}catch(e){console.warn(`@jsonPayload error:`,e)}else n[r]===void 0?n[r]=Ce(e):(Array.isArray(n[r])||(n[r]=[n[r]]),n[r].push(Ce(e)))})),n}(r));for(let n in r){let i=r[n];if(ye(i))e.files[n]=e.files[n]||[],e.files[n].push(i);else if(Array.isArray(i)){let r=[],a=[];for(let e of i)ye(e)?r.push(e):a.push(e);if(r.length>0&&r.length==i.length){e.files[n]=e.files[n]||[];for(let i of r)e.files[n].push(i)}else if(e.json[n]=a,r.length>0){let i=n;n.startsWith(`+`)||n.endsWith(`+`)||(i+=`+`),e.files[i]=e.files[i]||[];for(let n of r)e.files[i].push(n)}}else e.json[n]=i}}},Ee=class{get baseUrl(){return this.baseURL}set baseUrl(e){this.baseURL=e}constructor(e=`/`,n,r=`en-US`){this.cancelControllers={},this.recordServices={},this.enableAutoCancellation=!0,this.baseURL=e,this.lang=r,this.authStore=n||(typeof window<`u`&&window.Deno?new ce:new w),this.collections=new fe(this),this.files=new he(this),this.logs=new pe(this),this.settings=new E(this),this.realtime=new j(this),this.health=new me(this),this.backups=new ge(this),this.crons=new _e(this),this.sql=new ve(this)}get admins(){return this.collection(`_superusers`)}createBatch(){return new we(this)}collection(e){return this.recordServices[e]||(this.recordServices[e]=new ue(this,e)),this.recordServices[e]}autoCancellation(e){return this.enableAutoCancellation=!!e,this}cancelRequest(e){return this.cancelControllers[e]&&(this.cancelControllers[e].abort(),delete this.cancelControllers[e]),this}cancelAllRequests(){for(let e in this.cancelControllers)this.cancelControllers[e].abort();return this.cancelControllers={},this}filter(e,n){if(!n)return e;function r(e){switch(typeof e){case`boolean`:case`number`:return``+e;case`string`:return JSON.stringify(e);default:if(e==null)return`null`;if(e instanceof Date)return JSON.stringify(e.toISOString().replace(`T`,` `));{let n=JSON.stringify(e);return n.startsWith(`[`)||n.startsWith(`{`)?JSON.stringify(n):n}}}for(let i in n)e=e.replaceAll(`{:`+i+`}`,r(n[i]));return e}getFileUrl(e,n,r={}){return console.warn(`Please replace pb.getFileUrl() with pb.files.getURL()`),this.files.getURL(e,n,r)}buildUrl(e){return console.warn(`Please replace pb.buildUrl() with pb.buildURL()`),this.buildURL(e)}buildURL(e){let n=this.baseURL;return typeof window>`u`||!window.location||n.startsWith(`https://`)||n.startsWith(`http://`)||(n=window.location.origin?.endsWith(`/`)?window.location.origin.substring(0,window.location.origin.length-1):window.location.origin||``,this.baseURL.startsWith(`/`)||(n+=window.location.pathname||`/`,n+=n.endsWith(`/`)?``:`/`),n+=this.baseURL),e&&(n+=n.endsWith(`/`)?``:`/`,n+=e.startsWith(`/`)?e.substring(1):e),n}async send(e,n){n=this.initSendOptions(e,n);let r=this.buildURL(e);if(this.beforeSend){let e=Object.assign({},await this.beforeSend(r,n));e.url!==void 0||e.options!==void 0?(r=e.url||r,n=e.options||n):Object.keys(e).length&&(n=e,console?.warn&&console.warn("Deprecated format of beforeSend return: please use `return { url, options }`, instead of `return options`."))}if(n.query!==void 0){let e=k(n.query);e&&(r+=(r.includes(`?`)?`&`:`?`)+e),delete n.query}return this.getHeader(n.headers,`Content-Type`)==`application/json`&&n.body&&typeof n.body!=`string`&&(n.body=JSON.stringify(n.body)),(n.fetch||fetch)(r,n).then((async e=>{let r={};try{r=await e.json()}catch(e){if(n.signal?.aborted||e?.name==`AbortError`||e?.message==`Aborted`)throw e}if(this.afterSend&&(r=await this.afterSend(e,r,n)),e.status>=400)throw new y({url:e.url,status:e.status,data:r});return r})).catch((e=>{throw new y(e)}))}initSendOptions(e,n){if((n=Object.assign({method:`GET`},n)).body=function(e){if(typeof FormData>`u`||e===void 0||typeof e!=`object`||!e||be(e)||!xe(e))return e;let n=new FormData;for(let r in e){let i=e[r];if(i!==void 0){if(typeof i!=`object`||xe({data:i})){let e=Array.isArray(i)?i:[i];for(let i of e)n.append(r,i)}else{let e={};e[r]=i,n.append(`@jsonPayload`,JSON.stringify(e))}}}return n}(n.body),O(n),n.query=Object.assign({},n.params,n.query),n.requestKey===void 0&&(!1===n.$autoCancel||!1===n.query.$autoCancel?n.requestKey=null:(n.$cancelKey||n.query.$cancelKey)&&(n.requestKey=n.$cancelKey||n.query.$cancelKey)),delete n.$autoCancel,delete n.query.$autoCancel,delete n.$cancelKey,delete n.query.$cancelKey,this.getHeader(n.headers,`Content-Type`)!==null||be(n.body)||(n.headers=Object.assign({},n.headers,{"Content-Type":`application/json`})),this.getHeader(n.headers,`Accept-Language`)===null&&(n.headers=Object.assign({},n.headers,{"Accept-Language":this.lang})),this.authStore.token&&this.getHeader(n.headers,`Authorization`)===null&&(n.headers=Object.assign({},n.headers,{Authorization:this.authStore.token})),this.enableAutoCancellation&&n.requestKey!==null){let r=n.requestKey||(n.method||`GET`)+e;delete n.requestKey,this.cancelRequest(r);let i=new AbortController;this.cancelControllers[r]=i,n.signal=i.signal}return n}getHeader(e,n){e||={},n=n.toLowerCase();for(let r in e)if(r.toLowerCase()==n)return e[r];return null}},De=`#/login`,Oe=window.location.pathname.endsWith(`/`)?window.location.pathname.substring(0,window.location.pathname.length-1):window.location.pathname;window.app=window.app||{},window.app.pb=new Ee(`../`,new w(`__pb_superusers__`+Oe)),app.pb.beforeSend=function(e,n){return n.headers[`x-request-source`]=`pbui`,{url:e,options:n}},app.store.superuser=app.pb.authStore.record,app.pb.authStore.onChange((e,n)=>{!n&&window.location.hash!=De&&(app.modals.close(),window.location.hash=De),app.store.superuser=n}),app.pb.authStore.isValid&&app.pb.collection(app.pb.authStore.record?.collectionName||`_superusers`).authRefresh().catch(e=>{console.warn(`Failed to refresh the existing auth token:`,e);let n=e?.status<<0;(n==401||n==403)&&(app.pb.cancelAllRequests(),app.pb.authStore.clear())}),app.pb.authStore.onChange((e,n)=>{n?.id&&(app.store.loadCollections(),app.store.loadSettings(),app.store.loadOAuth2Providers())});var ke=app.pb.collection;app.pb.collection=function(e){let n=ke.call(this,e);return Ae(n),n};function Ae(e){if(e.__customUIEvents)return;e.__customUIEvents=!0;let n=e.create;e.create=function(){return n.apply(e,arguments).then(e=>(setTimeout(()=>{document.dispatchEvent(new CustomEvent(`record:create`,{detail:e})),document.dispatchEvent(new CustomEvent(`record:save`,{detail:e}))},0),e))};let r=e.update;e.update=function(){return r.apply(e,arguments).then(e=>(setTimeout(()=>{document.dispatchEvent(new CustomEvent(`record:update`,{detail:e})),document.dispatchEvent(new CustomEvent(`record:save`,{detail:e}))},0),e))};let i=e.delete;e.delete=function(){return i.apply(e,arguments).then(n=>{let r={id:arguments[0],collectionId:e.collectionIdOrName,collectionName:e.collectionIdOrName};return setTimeout(()=>{document.dispatchEvent(new CustomEvent(`record:delete`,{detail:r}))},0),n})}}var je=`pbLastFileToken`,Me=!1,Ne=[];app.pb.authStore.onChange((e,n)=>{n?.id||window.localStorage.removeItem(je)}),window.app.getFileToken=async function(e=``){let n=e&&app.store.collections?.find(n=>n.id==e||n.name==e);if(n&&!n.fields?.find(e=>e.type==`file`&&e.protected))return;let r=window.localStorage.getItem(je);return(!r||se(r,60))&&(r=await Pe()),r};async function Pe(){return new Promise(async(e,n)=>{if(Ne.push({resolve:e,reject:n}),!Me){Me=!0;try{let e=await app.pb.files.getToken();window.localStorage.setItem(je,e),Ne.forEach(n=>n.resolve(e))}catch(e){Ne.forEach(n=>n.reject(e))}Me=!1,Ne=[]}})}window.app.checkApiError=function(e,n=!0){if(!e||!(e instanceof Error)||e.isAbort){console.warn(`checkApiError - unexpected error type:`,e);return}let r=e?.status<<0,i=e?.response||{},a=n&&(i.message||e.message||`Something went wrong!`);if(a&&app.toasts.error(a),r==0&&console.log(e),app.utils.isEmpty(i.data)||(app.store.errors=i.data),r===401&&window.location.hash!=De)return app.pb.cancelAllRequests(),app.pb.authStore.clear()};function Fe(){return()=>{if(!(!app.store._ready||!app.store.showHeader||!app.store.superuser?.id))return t.header({pbEvent:`appHeader`,rid:`appHeader`,className:`app-header accent-surface`,onmount:async e=>{await new Promise(e=>setTimeout(e,0)),e._scrollToActiveMenuItem=function(){e?.querySelector(`.app-main-nav .header-link.active`)?.scrollIntoView()},e._scrollToActiveMenuItem(),window.addEventListener(`hashchange`,e._scrollToActiveMenuItem)},onunmount:e=>{window.removeEventListener(`hashchange`,e?._scrollToActiveMenuItem)}},t.a({href:`#/`,className:`logo`},t.img({src:()=>app.store.headerLogo,alt:`App logo`})),t.nav({pbEvent:`mainNav`,className:`app-main-nav`},()=>app.store.headerLinks.map(e=>{let n=e.href.startsWith(`#/`);return t.a({href:()=>e.href,target:()=>n?void 0:`_blank`,rel:()=>n?void 0:`noopener noreferrer`,className:n=>`header-link ${e.isActive?.(n)||app.utils.isActivePath(e.href)?`active`:``}`},()=>{if(e.icon)return t.i({className:e.icon,ariaHidden:!0})},t.span({className:`txt`},()=>e.label))})),t.div({className:`flex-fill app-header-separator`}),Ie(),t.button({type:`button`,className:`header-link logged-user txt-normal`,"html-popovertarget":`logged-user-dropdown`},t.span({className:`superuser-name txt-ellipsis`},()=>app.store.superuser?.email),t.i({className:`ri-arrow-drop-down-line`,ariaHidden:!0})),t.div({pbEvent:`loggedUserDropdown`,id:`logged-user-dropdown`,className:`dropdown sm nowrap logged-user-dropdown`,popover:`auto`},t.a({className:`dropdown-item dropdown-item-manage`,href:`#/collections?collection=_superusers`,onclick:e=>{e.target.closest(`.dropdown`).hidePopover()}},t.i({className:`ri-group-line`,ariaHidden:!0}),t.span({className:`txt`},`Manage superusers`)),t.hr(),t.button({type:`button`,className:`dropdown-item txt-danger dropdown-item-logout`,onclick:()=>app.pb.authStore.clear()},t.i({className:`ri-logout-circle-line`,ariaHidden:!0}),t.span({className:`txt`},`Logout`))))}}function Ie(){let e=[{value:`light`,icon:`ri-sun-line`,label:`Light`},{value:`dark`,icon:`ri-moon-line`,label:`Dark`},{value:``,icon:`ri-subtract-line`,label:`Auto`}];return[t.button({type:`button`,className:`header-link color-scheme-picker`,"html-popovertarget":`color-scheme-dropdown`,title:`Color scheme`},t.i({className:()=>app.store.activeColorScheme==`dark`?`ri-moon-line`:`ri-sun-line`,ariaHidden:!0})),t.div({pbEvent:`colorSchemeDropdown`,id:`color-scheme-dropdown`,className:`dropdown sm nowrap color-scheme-dropdown`,popover:`auto`},()=>e.map(e=>t.button({type:`button`,className:()=>`dropdown-item dropdown-item-light ${app.store.userColorScheme==e.value?`active`:``}`,onclick:n=>{n.target.closest(`.dropdown`).hidePopover(),app.store.userColorScheme=e.value}},t.i({className:e.icon,ariaHidden:!0}),t.span({className:`txt`},e.label))))]}document.addEventListener(`invalid`,e=>{let n=e.target.closest(`details`);n&&!n.open&&!e.target.closest(`summary`)&&(n.open=!0,e.target.reportValidity&&e.target.reportValidity())},!0);var Le=`dropdown-item`;document.addEventListener(`toggle`,e=>{if(e.newState!=`open`||!e.target||e.target.__keyboardNavRegistered||!e.target.matches(`.dropdown`))return;e.target.__keyboardNavRegistered=!0;let n=e.target;function r(e){if(!n.isConnected){document.removeEventListener(`keydown`,r);return}let i;if(i=document.activeElement&&document.activeElement.classList.contains(Le)?document.activeElement:n.querySelector(`.dropdown-item:not([hidden]):not(.disabled)`),i){if(e.key==`ArrowUp`){e.preventDefault();let n=ze(i,-1);i==document.activeElement&&n?.classList?.contains(Le)?n?.focus():i.focus()}else if(e.key==`ArrowDown`){e.preventDefault();let n=ze(i,1);i==document.activeElement&&n?.classList?.contains(Le)?n?.focus():i.focus()}else if(e.keyCode>=65&&e.keyCode<=90||e.keyCode>=48&&e.keyCode<=57){let e=n.querySelectorAll(`input,textare,select`);e.length==1&&e[0].focus()}}}n.addEventListener(`toggle`,e=>{e.newState==`open`?(n.__dropdownSource=e.source,n.__dropdownSource?.setAttribute(`data-popover-state`,!0),Re(e.target.id,!0),document.addEventListener(`keydown`,r)):(n.__dropdownSource?.setAttribute(`data-popover-state`,!1),Re(e.target.id,!1),document.removeEventListener(`keydown`,r))})},!0);function Re(e,n=!1){e&&document.querySelectorAll(`[popovertarget='`+e+`']`)?.forEach(e=>e.setAttribute(`data-popover-state`,n))}function ze(e,n=-1){let r=n<0?e.previousElementSibling:e.nextElementSibling;return r&&(r.hidden||r.classList.contains(`disabled`)||!r.classList.contains(Le))?ze(r,n):r}var Be=5,P=t.div({ariaHidden:!0,popover:`manual`,className:`pb-tooltip`});document.body.appendChild(P);function Ve(e,n,r){P._relatedNode=e;let i=e.getBoundingClientRect();P.setAttribute(`data-style`,r||``),P.setAttribute(`data-position`,n),P.style.top=`0px`,P.style.left=`0px`;let a=P.offsetHeight,o=P.offsetWidth,s=0,c=0;n==`left`?(s=i.top+i.height/2-a/2,c=i.left-o-Be):n==`right`?(s=i.top+i.height/2-a/2,c=i.right+Be):n==`top`?(s=i.top-a-Be,c=i.left+i.width/2-o/2):n==`top-left`?(s=i.top-a-Be,c=i.left):n==`top-right`?(s=i.top-a-Be,c=i.right-o):n==`bottom-left`?(s=i.top+i.height+Be,c=i.left):n==`bottom-right`?(s=i.top+i.height+Be,c=i.right-o):(s=i.top+i.height+Be,c=i.left+i.width/2-o/2),c+o>document.documentElement.clientWidth&&(c=document.documentElement.clientWidth-o),c=c>=0?c:0,s+a>document.documentElement.clientHeight&&(s=document.documentElement.clientHeight-a),s=s>=0?s:0,P.style.top=s+`px`,P.style.left=c+`px`}function He(){P._relatedNode=null,P.hidePopover()}function Ue(e,n,r,i){if(!e||!n){He();return}P.showPopover(),P.textContent=n,Ve(e,r,i)}document.body.addEventListener(`mouseleave`,()=>{He()});function We(e,n=`top`,r=``){return i=>{if(!i._tooltipText){i._tooltipText=store({value:``});let e;function a(){e?.unwatch(),e=watch(()=>i._tooltipText.value,async e=>{Ue(i,e,n,r)})}async function o(){e?.unwatch(),e=null,He()}i.addEventListener(`mouseenter`,a),i.addEventListener(`focusin`,a),i.addEventListener(`mouseleave`,o),i.addEventListener(`focusout`,o),i.addEventListener(`blur`,o);let s=i.onunmount;i.onunmount=n=>{P._relatedNode==n&&He(),e?.unwatch(),n._tooltipText=null,n?.removeEventListener(`mouseenter`,a),n?.removeEventListener(`focusin`,a),n?.removeEventListener(`mouseleave`,o),n?.removeEventListener(`focusout`,o),n?.removeEventListener(`blur`,o),s(n)}}return typeof e==`function`?i._tooltipText.value=e():i._tooltipText.value=e,i._tooltipText.value}}window.app=window.app||{},window.app.attrs=window.app.attrs||{},window.app.attrs.tooltip=We,window.app=window.app||{},window.app.modals=window.app.modals||{},window.app.modals.confirm=function(e,n,r,i={className:void 0,yesButton:``,noButton:``}){F.textOrElem=e,F.yesCallback=n,F.yesCallbackWaiting=!1,F.noCallback=r,F.noCallbackWaiting=!1,F.className=typeof i.className==`string`?i.className:`sm`,F.yesButton=i.yesButton||`Yes`,F.noButton=i.noButton||`No`,Ge.isConnected||document.body.appendChild(Ge),window.app.modals.open(Ge)};var F=store({className:``,textOrElem:null,yesButton:``,yesCallback:null,yesCallbackWaiting:!1,noButton:``,noCallback:null,noCallbackWaiting:!1,get isBusy(){return F.yesCallbackWaiting||F.noCallbackWaiting}}),Ge=t.div({className:()=>`modal popup manual ${F.className||``}`},t.div({className:`modal-content`},e=>typeof F.textOrElem==`string`?t.h6({className:`block txt-center`},F.textOrElem):typeof F.textOrElem==`function`?F.textOrElem(e):F.textOrElem),t.footer({className:`modal-footer p-sm`},t.div({className:`grid sm`},t.div({className:`col-sm-6`},t.button({type:`button`,className:()=>`btn lg block secondary ${F.noCallbackWaiting?`loading`:``}`,disabled:()=>F.isBusy,onclick:async()=>{if(F.noCallback){F.noCallbackWaiting=!0;try{if(await F.noCallback()===!1)return}catch(e){console.log(`confirm noCallback error:`,e)}finally{F.noCallbackWaiting=!1}}window.app.modals.close(Ge)}},()=>typeof F.noButton==`string`?t.span({className:`txt`},F.noButton):typeof F.noButton==`function`?F.noButton(el):F.noButton)),t.div({className:`col-sm-6`},t.button({type:`button`,className:()=>`btn lg block warning ${F.yesCallbackWaiting?`loading`:``}`,disabled:()=>F.isBusy,onclick:async()=>{if(F.yesCallback){F.yesCallbackWaiting=!0;try{if(await F.yesCallback()===!1)return}catch(e){console.log(`confirm yesCallback error:`,e)}finally{F.yesCallbackWaiting=!1}}window.app.modals.close(Ge)}},()=>typeof F.yesButton==`string`?t.span({className:`txt`},F.yesButton):typeof F.yesButton==`function`?F.yesButton(el):F.yesButton)))));window.app=window.app||{},window.app.components=window.app.components||{},window.app.components.dragline=function(e={}){let n,r=store({rid:void 0,id:void 0,hidden:void 0,inert:void 0,className:``,tolerance:0,ondragstart:function(e){},ondragstop:function(e){},ondragging:function(e,n,r){}}),i=app.utils.extendStore(r,e),a=store({dragStarted:!1}),o,s,c,l;function u(){document.addEventListener(`touchmove`,m),document.addEventListener(`mousemove`,m),document.addEventListener(`touchend`,p),document.addEventListener(`mouseup`,p)}function d(){document.removeEventListener(`touchmove`,m),document.removeEventListener(`mousemove`,m),document.removeEventListener(`touchend`,p),document.removeEventListener(`mouseup`,p)}function f(e){e.stopPropagation(),o=e.clientX,s=e.clientY,c=e.clientX-n.offsetLeft,l=e.clientY-n.offsetTop,u()}function p(e){a.dragStarted&&(e.preventDefault(),a.dragStarted=!1,r.ondragstop?.(e)),d()}function m(e){let i=e.clientX-o,u=e.clientY-s,d=e.clientX-c,f=e.clientY-l;!a.dragStarted&&Math.abs(d-n.offsetLeft)r.id,hidden:()=>r.hidden,inert:()=>r.inert,className:()=>`dragline ${a.dragStarted?`dragging`:``} ${r.className}`,onmousedown:e=>{e.button==0&&f(e)},ontouchstart:f,onunmount:()=>{d(),i.forEach(e=>e?.unwatch())}}),n},window.app=window.app||{},window.app.components=window.app.components||{},window.app.components.slide=function(e,...n){let r;return t.div({className:n=>`block slide-block ${e?.(n)?``:`hidden`}`,onmount:e=>{r=setTimeout(()=>{e?.setAttribute(`data-slide`,`1`)},200)},onunmount:()=>{clearTimeout(r)}},...n)},window.app=window.app||{},window.app.modals=window.app.modals||{};var Ke=`data-modal-state`,qe=`manual`,Je;window.app.modals.open=async function(e){if(!e?.isConnected){console.error(`modals.open requies an active DOM element`,e);return}let n;if(e.onbeforeopen&&(n=await e.onbeforeopen(e)),n===!1)return;if(e.onafteropen){let n=new ResizeObserver(r=>{for(let i of r)i.contentRect.height>0&&e?.onafteropen&&(e.onafteropen(e),n.disconnect(),n=null)});n.observe(e)}Je=document.activeElement,Ye(e),e._forceClose=()=>app.modals.close(e,!0),window.addEventListener(`popstate`,e._forceClose);let r=Math.max(Xe(e)?.style.zIndex<<0,1e3);e.style.zIndex=r+1,e.setAttribute(Ke,`open`)},window.app.modals.close=async function(e=null,n=!1){if(e||=Xe(),e){if(window.removeEventListener(`popstate`,e._forceClose),n)e.onbeforeclose?.(e,!0),e.setAttribute(Ke,`close`),e.onafterclose?.(e,!0);else{if(e.onbeforeclose&&await e.onbeforeclose(e,!1)===!1)return;if(e.onafterclose){let n=new ResizeObserver(r=>{for(let i of r)i.contentRect.height<=0&&e?.onafterclose&&(e.onafterclose(e,!1),n.disconnect(),n=null)});n.observe(e)}e.setAttribute(Ke,`close`)}Je&&(Je.focus?.(),setTimeout(()=>{Je?.blur?.(),Je=null},0))}};function Ye(e){if(e.getAttribute(`tabindex`)||e.setAttribute(`tabindex`,`-1`),setTimeout(()=>{let n=e?.querySelector(`[autofocus]`);n?n.focus():e?.focus()},0),e.getAttribute(Ke))return;e.setAttribute(Ke,``),e.addEventListener(`keydown`,n=>{n.key!=`Escape`||e.classList.contains(qe)||n.target!==e&&e.contains(n.target)||window.app.modals.close(e)});let n=!1,r=r=>{n=r.target!==e&&e.contains(r.target)};e.addEventListener(`mousedown`,r),e.addEventListener(`touchstart`,r);let i=!1,a=n=>{i=n.target!==e&&e.contains(n.target)};e.addEventListener(`mouseup`,a),e.addEventListener(`touchend`,a),e.addEventListener(`click`,r=>{n||i||e.classList.contains(qe)||r.target!==e&&e.contains(r.target)||window.app.modals.close(e)})}function Xe(e){let n=document.querySelectorAll(`[${Ke}="open"]`),r=0,i=0,a;for(let o of n)e&&o==e||(r=o.style.zIndex<<0,r>i&&(i=r,a=o));return a}window.app.modals.getTop=function(){return Xe()};var Ze=new Map,Qe=t.div({className:`toasts-container`});function I(e,n=!0){let r=Ze.get(e);!r||!r.isConnected||(Ze.delete(e),clearTimeout(r._removeTimeout),n?(r.classList.add(`removing`),setTimeout(()=>{r.remove()},300)):r.remove())}function R(e=!0){Ze.forEach((n,r)=>{window.app.toasts.remove(r,e)})}function $e(e,n={}){n.type=`info`,n.duration=n.duration||3e3,nt(e,n)}function et(e,n={}){n.type=`success`,n.duration=n.duration||3e3,nt(e,n)}function tt(e,n={}){n.type=`error`,n.duration=n.duration||3500,nt(e,n)}function nt(e,n={}){n=Object.assign({duration:3e3,key:void 0,type:`info`},n),Qe.isConnected||document.body.appendChild(Qe);let r=n.key||e;Ze.has(r)&&I(r,!1);function i(e){e?._removeTimeout&&clearTimeout(e?._removeTimeout),e._removeTimeout=setTimeout(()=>{I(r)},n.duration)}let a=t.div({className:`toast ${n.type||``}`,onmount:e=>{i(e)},onunmount:e=>{e?._removeTimeout&&(clearTimeout(e?._removeTimeout),a=null)},onmouseover:()=>{clearTimeout(a?._removeTimeout)},onmouseout:()=>{i(a)}},t.div({className:`toast-container`},t.div({className:`toast-icon`}),t.div({className:`toast-content`},e,t.button({type:`button`,className:`m-l-auto btn circle sm transparent secondary toast-remove`,title:`Clear`,onclick:()=>I(r)},t.i({className:`ri-close-line`,ariaHidden:!0})))));Ze.set(r,a),Qe.prepend(a)}window.app=window.app||{},window.app.toasts=window.app.toasts||{},window.app.toasts.info=$e,window.app.toasts.error=tt,window.app.toasts.success=et,window.app.toasts.remove=I,window.app.toasts.removeAll=R,window.app=window.app||{},window.app.components=window.app.components||{},window.app.components.sortable=function(e={}){let n=store({rid:void 0,id:void 0,hidden:void 0,inert:void 0,className:``,data:[],dataItem:function(e,n,r){return t.span(null,`Item `+n)},onchange:function(e,n,r){},handle:``,before:void 0,after:void 0}),r=app.utils.extendStore(n,e);function i(e){function r(){e.querySelectorAll(`:scope > [data-dragstart="true"]`)?.forEach(e=>{e.dataset.dragstart=!1}),e.querySelectorAll(`:scope > [data-dragover="true"]`)?.forEach(e=>{e.dataset.dragover=!1})}e.addEventListener(`dragstart`,r=>{if(n.handle&&!r.target.closest(n.handle)){r.preventDefault();return}let i=o(e,r.target);i&&(i.dataset.dragstart=!0)}),e.addEventListener(`dragenter`,n=>{for(let n of e.children)n.dataset.dragover&&(n.dataset.dragover=!1);let r=o(e,n.target);r&&(r.dataset.dragover=!0)}),e.addEventListener(`dragover`,e=>{e.preventDefault()}),e.addEventListener(`drop`,i=>{if(!n.onchange){r();return}let s=e.querySelector(`:scope > [data-dragstart="true"]`),c=o(e,i.target);if(r(),!s||!c||c==s)return;let l=e.querySelectorAll(`:scope > [data-sortable-child]`),u=a(l,s),d=a(l,c);if(u==-1||d==-1)return;let f=n.data.slice(),p=f.splice(u,1);f.splice(d,0,p[0]),n.onchange(f,u,d)}),e._documentDragend=function(){r()},document.addEventListener(`dragend`,e._documentDragend)}function a(e,n){for(let r=0;rn.id,hidden:()=>n.hidden,inert:()=>n.inert,className:()=>n.className,onmount:e=>{i(e)},onunmount:e=>{r.forEach(e=>e?.unwatch()),e._documentDragend&&document.removeEventListener(`dragend`,e._documentDragend)}},e=>typeof n.before==`function`?n.before(e):n.before,e=>{let r=[];for(let i=0;itypeof n.after==`function`?n.after(e):n.after)},window.app=window.app||{},window.app.components=window.app.components||{},window.app.components.copyButton=function(e,...n){let r=store({active:!1}),i;function a(){let n=e;typeof n==`function`&&(n=e()),app.utils.copyToClipboard(n),r.active=!0,clearTimeout(i),i=setTimeout(()=>{r.active=!1},500)}return t.button({tabIndex:-1,type:`button`,className:()=>`copy-to-clipboard ${r.active?`active`:``}`,title:`Copy`,ariaDescription:app.attrs.tooltip(()=>r.active?`Copied`:null),onclick:e=>{e.preventDefault(),e.stopPropagation(),a()}},t.i({hidden:n?.length,ariaHidden:!0,className:()=>`copy-icon ${r.active?`ri-check-double-line`:`ri-file-copy-line`}`}),...n)},window.app=window.app||{},window.app.components=window.app.components||{},window.app.components.codeBlock=function(e={}){let n=store({rid:void 0,id:void 0,hidden:void 0,inert:void 0,className:``,language:`js`,value:void 0,footnote:void 0}),r=app.utils.extendStore(n,e);return t.div({rid:n.rid,id:()=>n.id,hidden:()=>n.hidden,inert:()=>n.inert,className:()=>`code-wrapper ${n.className}`,tabIndex:-1,onmount:e=>{e.addEventListener(`keydown`,n=>{(n.ctrlKey||n.metaKey)&&(n.key==`a`||n.key==`A`)&&(n.preventDefault(),window.getSelection().selectAllChildren(e))})},onunmount:()=>{r.forEach(e=>e?.unwatch())}},t.code({className:`block`,innerHTML:()=>rt(n.value,n.language)}),t.div({className:`footnote`},e=>typeof n.footnote==`function`?n.footnote(e):n.footnote))};function rt(e,n){return e=typeof e==`string`?e:``,e=Prism.plugins.NormalizeWhitespace.normalize(e,{"remove-trailing":!0,"remove-indent":!0,"left-trim":!0,"right-trim":!0}),Prism.highlight(e,Prism.languages[n]||Prism.languages.js,n)}window.app=window.app||{},window.app.components=window.app.components||{},window.app.components.codeEditor=function(e={}){let n=store({rid:void 0,id:void 0,hidden:void 0,inert:void 0,name:void 0,className:``,value:``,language:`js`,placeholder:``,disabled:!1,required:!1,singleLine:!1,autocomplete:void 0,oninput:function(e){},onfocus:function(e){},onblur:function(e){}}),r=app.utils.extendStore(n,e,`autocomplete`),i,a,o=!0;function s(e){c(),i=t.div({className:`dropdown autocomplete code-editor-dropdown`,onmount:e=>{e._updatePosition=()=>{o?dt(i):c()},e._closeOnEsc=e=>{e.key==`Escape`&&(e.preventDefault(),c())},window.addEventListener(`scroll`,e._updatePosition,!0),window.addEventListener(`resize`,e._updatePosition),window.addEventListener(`keydown`,e._closeOnEsc),e._updatePosition()},onunmount:e=>{e&&(window.removeEventListener(`scroll`,e._updatePosition,!0),window.removeEventListener(`resize`,e._updatePosition),window.removeEventListener(`keydown`,e._closeOnEsc))}},e),document.body.appendChild(i),p&&(a?.disconnect(),a=new IntersectionObserver(([e])=>{o=e.isIntersecting},{root:null,threshold:.1}),a.observe(p))}function c(){clearTimeout(f),i&&=(i.remove(),null),a&&=(a.disconnect(),null),o=!0}function l(e){n.value=e,n.oninput?.(e),p.dispatchEvent(new CustomEvent(`change`,{detail:e}))}let u=!1,d,f,p=t.div({contentEditable:()=>!n.disabled&&`plaintext-only`,tabIndex:0,spellcheck:!1,autocorrect:!1,autocomplete:`off`,autocapitalize:`off`,role:`textbox`,className:`editor-content`,"html-data-placeholder":()=>n.placeholder,onmount:e=>{d?.unwatch(),d=watch(()=>n.value,e=>{e!=p.textContent&&(p.textContent=e,c())})},onunmount:e=>{d?.unwatch(),c()},onfocus:()=>{n.onfocus?.(n.value)},onblur:e=>{i&&!i.contains(e.relatedTarget)&&c(),n.onblur?.(n.value)},oninput:e=>{if(clearTimeout(f),l(p.textContent),!n.value?.length){p.textContent=``,c();return}f=setTimeout(()=>{if(c(),!p?.isConnected)return;let e=ut(p),r=st(n.value,e);if(!r.word.length||e==r.start)return;let i=[];if(typeof n.autocomplete==`function`)i=n.autocomplete(r.prefix||r.word)||[];else if(!app.utils.isEmpty(n.autocomplete)){let e=(r.prefix||r.word).toLowerCase();i=n.autocomplete.filter(n=>(typeof n==`object`&&(n=n?.value),n=n?.toLowerCase(),n&&n!=e&&n.includes(e)))}!i?.length||i.length==1&&(i[0].value||i[0])==r.word||s(()=>i.map((e,n)=>t.button({type:`button`,className:`dropdown-item ${n==0?`active`:``}`,textContent:e.label||e.value||e,onclick:n=>{n.preventDefault(),p.focus();let i=e.value||e;p.textContent=p.textContent.substring(0,r.start)+i+p.textContent.substring(r.end+1),l(p.textContent);try{window.getSelection().setPosition(p.childNodes[0],r.start+i.length)}catch(e){console.warn(`failed to set caret position`,e)}c()}})))},50)},onkeydown:e=>{if(u=e.ctrlKey||e.metaKey,(e.key==`Enter`||e.key==`Tab`)&&i?.isConnected){e.preventDefault(),i.querySelector(`.dropdown-item.active`)?.click();return}if(e.key==`ArrowUp`&&i?.isConnected){e.preventDefault();let n=i.querySelector(`.dropdown-item.active`);n?.previousElementSibling&&(n.classList.remove(`active`),n.previousElementSibling.classList.add(`active`),n.previousElementSibling.scrollIntoView(!1));return}if(e.key==`ArrowDown`&&i?.isConnected){e.preventDefault();let n=i.querySelector(`.dropdown-item.active`);n?.nextElementSibling&&(n.classList.remove(`active`),n.nextElementSibling.classList.add(`active`),n.nextElementSibling.scrollIntoView(!1));return}if(u&&e.key.toLowerCase()==`l`){e.preventDefault(),ct(p);return}if(u&&e.key.toLowerCase()==`d`){e.preventDefault(),lt(p);return}if(!n.singleLine&&e.key==`Escape`&&!i?.isConnected){p?.blur();return}if(!n.singleLine&&e.key==`Tab`){e.preventDefault();let n=window.getSelection();if(!n)return;if(e.shiftKey){n.modify(`extend`,`backward`,`character`),n.toString()[0]==` `?(n.deleteFromDocument(),l(p.textContent)):(n.modify(`extend`,`forward`,`character`),n.toString()[0]==` `&&(n.deleteFromDocument(),l(p.textContent)));return}let r=n.getRangeAt(0);r&&(r.deleteContents(),r.insertNode(document.createTextNode(` `)),r.collapse(),l(p.textContent));return}if(n.singleLine&&e.key==`Enter`){e.preventDefault(),h.click();return}},onscroll:()=>{c(),m&&(m.scrollLeft=p.scrollLeft,m.scrollTop=p.scrollTop)}}),m=t.div({className:`highlight-overlay`,innerHTML:()=>at(n.value,n.language),onscroll:()=>{p&&(p.scrollLeft=m.scrollLeft,p.scrollTop=m.scrollTop)}}),h=t.button({type:`submit`,className:`hidden`});return t.div({rid:n.rid,id:()=>n.id,inert:()=>n.inert,hidden:()=>n.hidden,"html-name":()=>n.name,"html-required":()=>n.required||void 0,className:()=>`input code-editor ${n.className} ${n.disabled?`disabled`:``} ${n.singleLine?`single-line`:``}`,onclick:()=>{p?.focus()},onunmount:()=>{r?.forEach(e=>e?.unwatch())}},t.div({className:`code-editor-container`},p,m,h))};var it=800;function at(e,n){return e=typeof e==`string`?e:``,e?((!Prism.languages[n]||e.length>it)&&(n=`plain`),Prism.highlight(e,Prism.languages[n],n)):``}var ot=new RegExp(/[\p{Alphabetic}\p{Number}_@:\."'{}]/,`u`);function st(e,n){let r=n;for(let i=n-1;i>=0&&ot.test(e[i]);i--)r=i;let i=r;for(let r=n-1;rdocument.documentElement.clientHeight&&(o=Math.max(n.top-r,0)),a+i>document.documentElement.clientWidth&&(a=Math.max(document.documentElement.clientWidth-i,0)),e.style.left=a+`px`,e.style.top=o+`px`}window.app=window.app||{},window.app.components=window.app.components||{},window.app.components.codeBlockTabs=function(e={}){let n=store({rid:void 0,id:void 0,hidden:void 0,inert:void 0,className:``,activeTabIndex:0,historyKey:``,tabs:[],get activeTab(){return n.tabs[n.activeTabIndex]||n.tabs[0]}}),r=app.utils.extendStore(n,e);return r.push(watch(()=>n.activeTabIndex,(e,r)=>{r!=null&&n.historyKey&&localStorage.setItem(n.historyKey,e)})),t.div({rid:n.rid,id:()=>n.id,hidden:()=>n.hidden||!n.tabs.length,inert:()=>n.inert,className:()=>`code-block-tabs ${n.className}`,onmount:()=>{n.historyKey&&(n.activeTabIndex=localStorage.getItem(n.historyKey)<<0)},onunmount:()=>{r.forEach(e=>e?.unwatch())}},t.header({className:`tabs-header`},()=>n.tabs.map((e,r)=>t.button({type:`button`,className:()=>`tab-item ${n.activeTabIndex==r?`active`:``}`,onclick:()=>n.activeTabIndex=r},n=>typeof e.title==`function`?e.title(n):e.title))),t.div({className:`code-block-tabs-content`},()=>{if(n.activeTab)return app.components.codeBlock(n.activeTab)}))},window.app=window.app||{},window.app.components=window.app.components||{},window.app.components.select=function(e={}){let n=store({rid:void 0,id:void 0,name:void 0,hidden:void 0,inert:void 0,className:``,value:void 0,options:[],before:null,after:null,max:1,searchThreshold:6,required:!1,disabled:!1,placeholder:`- Select -`,noItemsFoundText:`No items found`,onchange:function(e){},ondropdowntoggle:function(e){}}),r=app.utils.extendStore(n,e);n.max<=0&&(n.max=1);let i=store({selected:[],search:``,get hasSearch(){return i.search?.length>0},get allowRemove(){return!n.disabled&&(!n.required||n.max>1)}});function a(){if(n.value===void 0)return;let e=app.utils.toArray(n.value,!0),r=e.slice(0,n.max||1);e.length!=r.length&&(console.warn(`[select] the provided select values (${e.length}) are more than the allowed max selected options (${r.length}):`,e),n.value=n.max>1?r:r[0]),i.selected=e.map(e=>n.options.find(n=>n.value===e)).filter(Boolean)}r.push(watch(()=>n.value,()=>a()));async function o(e){let r=i.selected.findIndex(n=>n.value===e.value);if(r>=0){if(!i.allowRemove){f?.hidePopover();return}i.selected.splice(r,1)}else{let r=i.selected.length-n.max;for(;r>=0;)i.selected.pop(),r--;i.selected.push(e)}n.max<=1&&f?.hidePopover(),n.onchange&&(await n.onchange(i.selected),a()),p?.isConnected&&p.dispatchEvent(new CustomEvent(`change`,{detail:i.selected,bubbles:!0}))}function s(e){return i.selected.findIndex(n=>n.value===e.value)>=0}let c=t.input({type:`text`,placeholder:`Search...`,value:()=>i.search,oninput:e=>i.search=e.target.value});function l(e=!1){i.search=``,e&&c?.focus()}let u=t.div({className:`txt-hint txt-center m-0 p-5`,hidden:!0},e=>typeof n.noItemsFoundText==`function`?n.noItemsFoundText(e):n.noItemsFoundText);async function d(){f&&(await new Promise(e=>setTimeout(e,0)),f.querySelector(`.select-option:not([hidden])`)?u.hidden=!0:u.hidden=!1)}let f=t.div({tabIndex:-1,popover:`auto`,className:`dropdown`,onbeforetoggle:e=>(e.newState==`closed`&&l(),n.ondropdowntoggle?.(e))},t.div({className:`fields dropdown-search`,hidden:()=>n.options.length!i.hasSearch},t.button({type:`button`,title:`Clear`,className:`btn sm secondary transparent circle`,onclick:()=>l(!0)},t.i({className:`ri-close-line`,ariaHidden:!0})))),()=>n.before?.__raw||n.before,()=>n.options.map(e=>t.button({type:`button`,className:()=>`dropdown-item select-option ${s(e)?`active`:``}`,onclick:()=>(o(e),!1)},e.label||e.value)),u,()=>n.after?.__raw||n.after),p=t.button({type:`button`,id:()=>n.id,disabled:()=>n.disabled,className:`selected-container`,popoverTargetElement:f,onclick:e=>{e.stopPropagation()}},()=>i.selected.length?i.selected.map(e=>t.div({className:`selected-item`},e.selected||e.label||e.value,()=>{if(i.allowRemove)return t.i({tabIndex:-1,role:`button`,className:`ri-close-line link-hint btn-option-unset`,ariaLabel:app.attrs.tooltip(`Unset`),onclick:()=>(o(e),!1)})})):t.span({rid:`selected-placeholder`,className:`placeholder`},e=>typeof n.placeholder==`function`?n.placeholder(e):n.placeholder));r.push(watch(()=>n.options,()=>{d()}));let m;return r.push(watch(()=>i.search,()=>{let e=i.search.toLowerCase().replaceAll(` `,``);clearTimeout(m),m=setTimeout(()=>{let n=f.querySelectorAll(`.select-option`);e.length?n.forEach(n=>{n.hidden=!n.textContent.toLowerCase().replaceAll(` `,``).includes(e)}):n.forEach(e=>e.hidden=!1),d()},100)})),t.output({rid:n.rid,name:()=>n.name,hidden:()=>n.hidden,inert:()=>n.inert,onmount:e=>{e.addEventListener(`focusout`,function(n){(!n.relatedTarget||!e.contains(n.relatedTarget))&&f?.hidePopover()})},onunmount:()=>{clearTimeout(m),r.forEach(e=>e.unwatch())},className:()=>[`input`,`select`,n.max>1?`multiple`:`single`,n.disabled?`disabled`:null,n.required?`required`:null,n.className||null].filter(Boolean).join(` `)},p,f)},window.app=window.app||{},window.app.components=window.app.components||{};var ft=Intl.DateTimeFormat().resolvedOptions().timeZone;window.app.components.formattedDate=function(e={}){let n=store({rid:void 0,id:void 0,hidden:void 0,value:``,short:!1}),r=app.utils.extendStore(n,e);return t.div({rid:n.rid,id:()=>n.id,hidden:()=>n.hidden,ariaDescription:app.attrs.tooltip(()=>n.short&&n.value?app.utils.toLocalDatetime(n.value)+` -`+ft:null),"html-class":`formatted-date`,className:()=>`formatted-date ${n.short?`short`:`full`}`,onunmount:()=>{r.forEach(e=>e?.unwatch())}},()=>{if(!n.value)return t.span({className:`missing-value`});if(n.short){let e=n.value.split(` `);return[t.span({className:`primary-date`},e[0]),t.span({className:`secondary-date`},e[1])]}return[t.span({className:`primary-date`},app.utils.toLocalDatetime(n.value)),t.span({className:`secondary-date`},n.value)]})},window.app=window.app||{},window.app.components=window.app.components||{},window.app.components.refreshButton=function(e={}){let n=store({rid:void 0,id:void 0,hidden:void 0,inert:void 0,tooltip:`Refresh`,className:`btn transparent secondary circle rotate-btn`,disabled:!1,onclick:function(e){}}),r=app.utils.extendStore(n,e),i,a=t.button({rid:n.rid,id:()=>n.id,hidden:()=>n.hidden,inert:()=>n.inert,type:`button`,ariaLabel:app.attrs.tooltip(()=>n.tooltip),disabled:()=>n.disabled,className:()=>n.className,onunmount:()=>{clearTimeout(i),r.forEach(e=>e?.unwatch())},onclick:e=>{e.preventDefault(),n.onclick&&n.onclick(e),a.dataset.rotate=!0,a.addEventListener(`animationend`,()=>{a.dataset.rotate=!1}),clearTimeout(i),i=setTimeout(()=>{clearTimeout(i),a.dataset.rotate=!1},500)}},t.i({className:`ri-refresh-line`,ariaHidden:!0}));return a},window.app=window.app||{},window.app.components=window.app.components||{},window.app.components.searchHistoryButton=function(e={}){let n=store({rid:void 0,id:void 0,hidden:void 0,inert:void 0,value:void 0,historyKey:`default`,max:15,openInNewTabParam:`filter`,btnClassName:`btn sm pill secondary transparent p-r-5`,onselect:function(e){}}),r=app.utils.extendStore(n,e),i=store({items:app.utils.getLocalHistory(n.historyKey,[])});function a(e){o(e),i.items.unshift(e)}function o(e){app.utils.removeByValue(i.items,e)}let s=`history_dropdown_`+app.utils.randomString();r.push(watch(()=>n.value,e=>{e&&a(e)})),r.push(watch(()=>{i.items.length>n.max&&(i.items=i.items.slice(0,n.max)),app.utils.saveLocalHistory(n.historyKey,i.items)}));let c=t.div({id:s,className:`dropdown sm left nowrap history-searchbar-dropdown`,popover:`hint`,onclick:e=>(e.stopPropagation(),!1)},t.div({className:`block p-5`},t.small({className:`txt-hint`},`Search history`)),()=>i.items?.length?i.items.slice(0,n.max).map(e=>t.button({type:`button`,className:`dropdown-item txt-code`,onclick:()=>{c.hidePopover(),n.onselect?.(e),a(e)},onauxclick:()=>{if(n.openInNewTabParam){a(e),c.hidePopover();let r=app.utils.replaceHashQueryParams({[n.openInNewTabParam]:e},!1);window.open(r,`_blank`)}}},t.span({className:`txt-ellipsis`,title:e,textContent:e}),t.small({role:`button`,className:`remove-btn link-hint m-l-auto p-l-5 p-r-5`,title:`Clear`,onauxclick:e=>(e.stopPropagation(),!1),onclick:n=>(n.stopPropagation(),o(e),!1)},t.i({className:`ri-close-line`,ariaHidden:!0})))):t.div({rid:`no-history`,className:`block p-5`},t.span(null,`Your recent searches will show up here.`)));return t.button({rid:n.rid,id:()=>n.id,hidden:()=>n.hidden,inert:()=>n.inert,type:`button`,title:`Search history`,className:()=>n.btnClassName,"html-popovertarget":s,onunmount:()=>{r?.forEach(e=>e?.unwatch())}},t.i({className:`ri-search-line`,ariaHidden:!0}),t.i({className:`ri-arrow-drop-down-line`,ariaHidden:!0}),c)},window.app=window.app||{},window.app.components=window.app.components||{},window.app.components.s3Test=function(e={}){let n=`s3_test_request`,r=store({rid:void 0,config:null,label:`Use S3 storage`,testFilesystem:`storage`}),i=app.utils.extendStore(r,e),a=store({isTesting:!1,testError:null,get hasError(){return!app.utils.isEmpty(a.testError)}}),o,s;function c(e=150){if(!r.config.enabled){clearTimeout(o);return}a.isTesting=!0,clearTimeout(o),o=setTimeout(()=>{l()},e)}async function l(){if(a.isTesting=!0,!r.config.enabled||!r.testFilesystem){a.testError=null,a.isTesting=!1;return}app.pb.cancelRequest(n),clearTimeout(s),s=setTimeout(()=>{app.pb.cancelRequest(n),a.testError=Error(`S3 test connection timeout.`),a.isTesting=!1},3e4);try{await app.pb.props.testS3(r.testFilesystem,{requestKey:n}),a.testError=null,a.isTesting=!1}catch(e){e?.isAbort||(a.testError=e,a.isTesting=!1,clearTimeout(s))}}return i.push(watch(()=>r.testFilesystem&&r.config,()=>c())),t.div({pbEvent:`s3Test`,rid:r.rid,hidden:()=>!r.testFilesystem,className:()=>`label s3-test-label txt-nowrap ${a.hasError?`warning`:`success`}`,ariaDescription:app.attrs.tooltip(()=>a.testError?.data?.message),onunmount:()=>{clearTimeout(s),clearTimeout(o),i.forEach(e=>e?.unwatch())}},()=>a.isTesting?t.span({className:`loader sm`}):a.hasError?[t.i({className:`ri-error-warning-line txt-warning`,ariaHidden:!0}),t.span({className:`txt`},`Failed to establish S3 connection`)]:[t.i({className:`ri-checkbox-circle-line txt-success`,ariaHidden:!0}),t.span({className:`txt`},`S3 connected successfully`)])},window.app=window.app||{},window.app.components=window.app.components||{},window.app.components.s3ConfigFields=function(e={}){let n=store({rid:void 0,id:void 0,hidden:void 0,inert:void 0,className:``,config:{},configKey:`s3`,toggleLabel:`Use S3 storage`,testFilesystem:`storage`,before:null,after:null}),r=app.utils.extendStore(n,e);n.configKey.endsWith(`.`)&&(n.configKey=n.configKey.substring(0,n.configKey.length-1));let i=store({originalHash:``,originalConfig:null});return r.push(watch(()=>n.config,e=>{i.originalHash=JSON.stringify(e),i.originalConfig=JSON.parse(i.originalHash)})),t.div({pbEvent:`s3ConfigFields`,rid:n.rid,id:()=>n.id,hidden:()=>n.hidden,inert:()=>n.inert,className:()=>`block s3-fields s3-config-${n.configKey} ${n.className}`,onunmount:()=>{r.forEach(e=>e?.unwatch())}},t.div({className:`field`},t.input({id:()=>`${n.configKey}.enabled`,name:()=>`${n.configKey}.enabled`,type:`checkbox`,className:`switch`,checked:()=>n.config.enabled,onchange:e=>n.config.enabled=e.target.checked}),t.label({htmlFor:()=>`${n.configKey}.enabled`},()=>n.toggleLabel)),e=>typeof n.before==`function`?n.before(e):n.before,app.components.slide(()=>n.config.enabled,t.div({className:`grid m-t-base`},t.div({className:`col-lg-6`},t.div({className:`field`},t.label({htmlFor:()=>`${n.configKey}.endpoint`},`Endpoint`),t.input({id:()=>`${n.configKey}.endpoint`,name:()=>`${n.configKey}.endpoint`,type:`text`,required:()=>n.config.enabled,value:()=>n.config.endpoint||``,oninput:e=>n.config.endpoint=e.target.value}))),t.div({className:`col-lg-3`},t.div({className:`field`},t.label({htmlFor:()=>`${n.configKey}.bucket`},`Bucket`),t.input({id:()=>`${n.configKey}.bucket`,name:()=>`${n.configKey}.bucket`,type:`text`,required:()=>n.config.enabled,value:()=>n.config.bucket||``,oninput:e=>n.config.bucket=e.target.value}))),t.div({className:`col-lg-3`},t.div({className:`field`},t.label({htmlFor:()=>`${n.configKey}.region`},`Region`),t.input({id:()=>`${n.configKey}.region`,name:()=>`${n.configKey}.region`,type:`text`,required:()=>n.config.enabled,value:()=>n.config.region||``,oninput:e=>n.config.region=e.target.value}))),t.div({className:`col-lg-6`},t.div({className:`field`},t.label({htmlFor:()=>`${n.configKey}.accessKey`},`Access key`),t.input({id:()=>`${n.configKey}.accessKey`,name:()=>`${n.configKey}.accessKey`,type:`text`,autocomplete:`off`,required:()=>n.config.enabled,value:()=>n.config.accessKey||``,oninput:e=>n.config.accessKey=e.target.value}))),t.div({className:`col-lg-6`},t.div({className:()=>`field ${n.config.enabled?``:`required`}`},t.label({htmlFor:()=>`${n.configKey}.secret`},`Secret`),t.input({id:()=>`${n.configKey}.secret`,name:()=>`${n.configKey}.secret`,type:`password`,autocomplete:`new-password`,value:()=>n.config.secret||``,oninput:e=>n.config.secret=e.target.value,onkeyup:e=>{e.key==`Backspace`&&n.config.secret===void 0&&(n.config.secret=``)},placeholder:()=>n.config.secret===void 0?`* * * * * *`:``}))),t.div({className:`col-lg-6`,style:`min-height: 25px`},t.div({className:`field`},t.input({id:()=>`${n.configKey}.forcePathStyle`,name:()=>`${n.configKey}.forcePathStyle`,type:`checkbox`,checked:()=>n.config.forcePathStyle||!1,onchange:e=>n.config.forcePathStyle=e.target.checked}),t.label({htmlFor:()=>`${n.configKey}.forcePathStyle`},t.span({className:`txt`},`Force path-style addressing`),t.i({className:`ri-information-line link-hint`,ariaDescription:app.attrs.tooltip(`Forces the request to use path-style addressing, eg. "https://s3.amazonaws.com/BUCKET/KEY" instead of the default "https://BUCKET.s3.amazonaws.com/KEY".`)})))),t.div({className:`col-lg-6 txt-right`},()=>{if(!(!n.config?.enabled||i.originalHash!=JSON.stringify(n.config)))return app.components.s3Test({config:()=>n.config,testFilesystem:()=>n.testFilesystem})}))),e=>typeof n.after==`function`?n.after(e):n.after)};var pt=l(s(((e,n)=>{(function(r,i){typeof e==`object`&&n!==void 0?i(e):typeof define==`function`&&define.amd?define([`exports`],i):(r=typeof globalThis<`u`?globalThis:r||self,i(r.leaflet={}))})(e,(function(e){var n=`1.9.4`;function r(e){var n,r,i,a;for(r=1,i=arguments.length;r`u`||!L||!L.Mixin)){e=v(e)?e:[e];for(var n=0;n0?Math.floor(e):Math.ceil(e)};w.prototype={clone:function(){return new w(this.x,this.y)},add:function(e){return this.clone()._add(E(e))},_add:function(e){return this.x+=e.x,this.y+=e.y,this},subtract:function(e){return this.clone()._subtract(E(e))},_subtract:function(e){return this.x-=e.x,this.y-=e.y,this},divideBy:function(e){return this.clone()._divideBy(e)},_divideBy:function(e){return this.x/=e,this.y/=e,this},multiplyBy:function(e){return this.clone()._multiplyBy(e)},_multiplyBy:function(e){return this.x*=e,this.y*=e,this},scaleBy:function(e){return new w(this.x*e.x,this.y*e.y)},unscaleBy:function(e){return new w(this.x/e.x,this.y/e.y)},round:function(){return this.clone()._round()},_round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this},floor:function(){return this.clone()._floor()},_floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this},ceil:function(){return this.clone()._ceil()},_ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this},trunc:function(){return this.clone()._trunc()},_trunc:function(){return this.x=T(this.x),this.y=T(this.y),this},distanceTo:function(e){e=E(e);var n=e.x-this.x,r=e.y-this.y;return Math.sqrt(n*n+r*r)},equals:function(e){return e=E(e),e.x===this.x&&e.y===this.y},contains:function(e){return e=E(e),Math.abs(e.x)<=Math.abs(this.x)&&Math.abs(e.y)<=Math.abs(this.y)},toString:function(){return`Point(`+d(this.x)+`, `+d(this.y)+`)`}};function E(e,n,r){return e instanceof w?e:v(e)?new w(e[0],e[1]):e==null?e:typeof e==`object`&&`x`in e&&`y`in e?new w(e.x,e.y):new w(e,n,r)}function D(e,n){if(e)for(var r=n?[e,n]:e,i=0,a=r.length;i=this.min.x&&r.x<=this.max.x&&n.y>=this.min.y&&r.y<=this.max.y},intersects:function(e){e=O(e);var n=this.min,r=this.max,i=e.min,a=e.max,o=a.x>=n.x&&i.x<=r.x,s=a.y>=n.y&&i.y<=r.y;return o&&s},overlaps:function(e){e=O(e);var n=this.min,r=this.max,i=e.min,a=e.max,o=a.x>n.x&&i.xn.y&&i.y=n.lat&&a.lat<=r.lat&&i.lng>=n.lng&&a.lng<=r.lng},intersects:function(e){e=A(e);var n=this._southWest,r=this._northEast,i=e.getSouthWest(),a=e.getNorthEast(),o=a.lat>=n.lat&&i.lat<=r.lat,s=a.lng>=n.lng&&i.lng<=r.lng;return o&&s},overlaps:function(e){e=A(e);var n=this._southWest,r=this._northEast,i=e.getSouthWest(),a=e.getNorthEast(),o=a.lat>n.lat&&i.latn.lng&&i.lng1,Ke=function(){var e=!1;try{var n=Object.defineProperty({},"passive",{get:function(){e=!0}});window.addEventListener(`testPassiveEventSupport`,u,n),window.removeEventListener(`testPassiveEventSupport`,u,n)}catch{}return e}(),qe=function(){return!!document.createElement(`canvas`).getContext}(),Je=!!(document.createElementNS&&ge(`svg`).createSVGRect),Ye=!!Je&&(function(){var e=document.createElement(`div`);return e.innerHTML=``,(e.firstChild&&e.firstChild.namespaceURI)===`http://www.w3.org/2000/svg`})(),Xe=!Je&&function(){try{var e=document.createElement(`div`);e.innerHTML=``;var n=e.firstChild;return n.style.behavior=`url(#default#VML)`,n&&typeof n.adj==`object`}catch{return!1}}(),Ze=navigator.platform.indexOf(`Mac`)===0,Qe=navigator.platform.indexOf(`Linux`)===0;function I(e){return navigator.userAgent.toLowerCase().indexOf(e)>=0}var R={ie:ye,ielt9:be,edge:xe,webkit:Se,android:Ce,android23:we,androidStock:Ee,opera:De,chrome:Oe,gecko:ke,safari:Ae,phantom:je,opera12:Me,win:Ne,ie3d:Pe,webkit3d:Fe,gecko3d:Ie,any3d:Le,mobile:Re,mobileWebkit:ze,mobileWebkit3d:Be,msPointer:P,pointer:Ve,touch:Ue,touchNative:He,mobileOpera:We,mobileGecko:F,retina:Ge,passiveEvents:Ke,canvas:qe,svg:Je,vml:Xe,inlineSvg:Ye,mac:Ze,linux:Qe},$e=R.msPointer?`MSPointerDown`:`pointerdown`,et=R.msPointer?`MSPointerMove`:`pointermove`,tt=R.msPointer?`MSPointerUp`:`pointerup`,nt=R.msPointer?`MSPointerCancel`:`pointercancel`,rt={touchstart:$e,touchmove:et,touchend:tt,touchcancel:nt},it={touchstart:mt,touchmove:pt,touchend:pt,touchcancel:pt},at={},ot=!1;function st(e,n,r){return n===`touchstart`&&ft(),it[n]?(r=it[n].bind(this,r),e.addEventListener(rt[n],r,!1),r):(console.warn(`wrong event specified:`,n),u)}function ct(e,n,r){if(!rt[n]){console.warn(`wrong event specified:`,n);return}e.removeEventListener(rt[n],r,!1)}function lt(e){at[e.pointerId]=e}function ut(e){at[e.pointerId]&&(at[e.pointerId]=e)}function dt(e){delete at[e.pointerId]}function ft(){ot||=(document.addEventListener($e,lt,!0),document.addEventListener(et,ut,!0),document.addEventListener(tt,dt,!0),document.addEventListener(nt,dt,!0),!0)}function pt(e,n){if(n.pointerType!==(n.MSPOINTER_TYPE_MOUSE||`mouse`)){for(var r in n.touches=[],at)n.touches.push(at[r]);n.changedTouches=[n],e(n)}}function mt(e,n){n.MSPOINTER_TYPE_TOUCH&&n.pointerType===n.MSPOINTER_TYPE_TOUCH&&X(n),pt(e,n)}function ht(e){var n={},r,i;for(i in e)r=e[i],n[i]=r&&r.bind?r.bind(e):r;return e=n,n.type=`dblclick`,n.detail=2,n.isTrusted=!1,n._simulated=!0,n}var gt=200;function _t(e,n){e.addEventListener(`dblclick`,n);var r=0,i;function a(e){if(e.detail!==1){i=e.detail;return}if(!(e.pointerType===`mouse`||e.sourceCapabilities&&!e.sourceCapabilities.firesTouchEvents)){var a=$t(e);if(!(a.some(function(e){return e instanceof HTMLLabelElement&&e.attributes.for})&&!a.some(function(e){return e instanceof HTMLInputElement||e instanceof HTMLSelectElement}))){var o=Date.now();o-r<=gt?(i++,i===2&&n(ht(e))):i=1,r=o}}}return e.addEventListener(`click`,a),{dblclick:n,simDblclick:a}}function vt(e,n){e.removeEventListener(`dblclick`,n.dblclick),e.removeEventListener(`click`,n.simDblclick)}var yt=jt([`transform`,`webkitTransform`,`OTransform`,`MozTransform`,`msTransform`]),bt=jt([`webkitTransition`,`transition`,`OTransition`,`MozTransition`,`msTransition`]),xt=bt===`webkitTransition`||bt===`OTransition`?bt+`End`:`transitionend`;function St(e){return typeof e==`string`?document.getElementById(e):e}function Ct(e,n){var r=e.style[n]||e.currentStyle&&e.currentStyle[n];if((!r||r===`auto`)&&document.defaultView){var i=document.defaultView.getComputedStyle(e,null);r=i?i[n]:null}return r===`auto`?null:r}function z(e,n,r){var i=document.createElement(e);return i.className=n||``,r&&r.appendChild(i),i}function B(e){var n=e.parentNode;n&&n.removeChild(e)}function wt(e){for(;e.firstChild;)e.removeChild(e.firstChild)}function Tt(e){var n=e.parentNode;n&&n.lastChild!==e&&n.appendChild(e)}function Et(e){var n=e.parentNode;n&&n.firstChild!==e&&n.insertBefore(e,n.firstChild)}function Dt(e,n){if(e.classList!==void 0)return e.classList.contains(n);var r=kt(e);return r.length>0&&RegExp(`(^|\\s)`+n+`(\\s|$)`).test(r)}function V(e,n){if(e.classList!==void 0)for(var r=p(n),i=0,a=r.length;i0?2*window.devicePixelRatio:1;function nn(e){return R.edge?e.wheelDeltaY/2:e.deltaY&&e.deltaMode===0?-e.deltaY/tn:e.deltaY&&e.deltaMode===1?-e.deltaY*20:e.deltaY&&e.deltaMode===2?-e.deltaY*60:e.deltaX||e.deltaZ?0:e.wheelDelta?(e.wheelDeltaY||e.wheelDelta)/2:e.detail&&Math.abs(e.detail)<32765?-e.detail*20:e.detail?e.detail/-32765*60:0}function rn(e,n){var r=n.relatedTarget;if(!r)return!0;try{for(;r&&r!==e;)r=r.parentNode}catch{return!1}return r!==e}var an={__proto__:null,on:q,off:Y,stopPropagation:Yt,disableScrollPropagation:Xt,disableClickPropagation:Zt,preventDefault:X,stop:Qt,getPropagationPath:$t,getMousePosition:en,getWheelDelta:nn,isExternalTarget:rn,addListener:q,removeListener:Y},on=ce.extend({run:function(e,n,r,i){this.stop(),this._el=e,this._inProgress=!0,this._duration=r||.25,this._easeOutPower=1/Math.max(i||.5,.2),this._startPos=Nt(e),this._offset=n.subtract(this._startPos),this._startTime=+new Date,this.fire(`start`),this._animate()},stop:function(){this._inProgress&&(this._step(!0),this._complete())},_animate:function(){this._animId=b(this._animate,this),this._step()},_step:function(e){var n=+new Date-this._startTime,r=this._duration*1e3;nthis.options.maxZoom)?this.setZoom(e):this},panInsideBounds:function(e,n){this._enforcingBounds=!0;var r=this.getCenter(),i=this._limitCenter(r,this._zoom,A(e));return r.equals(i)||this.panTo(i,n),this._enforcingBounds=!1,this},panInside:function(e,n){n||={};var r=E(n.paddingTopLeft||n.padding||[0,0]),i=E(n.paddingBottomRight||n.padding||[0,0]),a=this.project(this.getCenter()),o=this.project(e),s=this.getPixelBounds(),c=O([s.min.add(r),s.max.subtract(i)]),l=c.getSize();if(!c.contains(o)){this._enforcingBounds=!0;var u=o.subtract(c.getCenter()),d=c.extend(o).getSize().subtract(l);a.x+=u.x<0?-d.x:d.x,a.y+=u.y<0?-d.y:d.y,this.panTo(this.unproject(a),n),this._enforcingBounds=!1}return this},invalidateSize:function(e){if(!this._loaded)return this;e=r({animate:!1,pan:!0},e===!0?{animate:!0}:e);var n=this.getSize();this._sizeChanged=!0,this._lastCenter=null;var i=this.getSize(),o=n.divideBy(2).round(),s=i.divideBy(2).round(),c=o.subtract(s);return!c.x&&!c.y?this:(e.animate&&e.pan?this.panBy(c):(e.pan&&this._rawPanBy(c),this.fire(`move`),e.debounceMoveend?(clearTimeout(this._sizeTimer),this._sizeTimer=setTimeout(a(this.fire,this,`moveend`),200)):this.fire(`moveend`)),this.fire(`resize`,{oldSize:n,newSize:i}))},stop:function(){return this.setZoom(this._limitZoom(this._zoom)),this.options.zoomSnap||this.fire(`viewreset`),this._stop()},locate:function(e){if(e=this._locateOptions=r({timeout:1e4,watch:!1},e),!(`geolocation`in navigator))return this._handleGeolocationError({code:0,message:`Geolocation not supported.`}),this;var n=a(this._handleGeolocationResponse,this),i=a(this._handleGeolocationError,this);return e.watch?this._locationWatchId=navigator.geolocation.watchPosition(n,i,e):navigator.geolocation.getCurrentPosition(n,i,e),this},stopLocate:function(){return navigator.geolocation&&navigator.geolocation.clearWatch&&navigator.geolocation.clearWatch(this._locationWatchId),this._locateOptions&&(this._locateOptions.setView=!1),this},_handleGeolocationError:function(e){if(this._container._leaflet_id){var n=e.code,r=e.message||(n===1?`permission denied`:n===2?`position unavailable`:`timeout`);this._locateOptions.setView&&!this._loaded&&this.fitWorld(),this.fire(`locationerror`,{code:n,message:`Geolocation error: `+r+`.`})}},_handleGeolocationResponse:function(e){if(this._container._leaflet_id){var n=e.coords.latitude,r=e.coords.longitude,i=new j(n,r),a=i.toBounds(e.coords.accuracy*2),o=this._locateOptions;if(o.setView){var s=this.getBoundsZoom(a);this.setView(i,o.maxZoom?Math.min(s,o.maxZoom):s)}var c={latlng:i,bounds:a,timestamp:e.timestamp};for(var l in e.coords)typeof e.coords[l]==`number`&&(c[l]=e.coords[l]);this.fire(`locationfound`,c)}},addHandler:function(e,n){if(!n)return this;var r=this[e]=new n(this);return this._handlers.push(r),this.options[e]&&r.enable(),this},remove:function(){if(this._initEvents(!0),this.options.maxBounds&&this.off(`moveend`,this._panInsideMaxBounds),this._containerId!==this._container._leaflet_id)throw Error(`Map container is being reused by another instance`);try{delete this._container._leaflet_id,delete this._containerId}catch{this._container._leaflet_id=void 0,this._containerId=void 0}for(var e in this._locationWatchId!==void 0&&this.stopLocate(),this._stop(),B(this._mapPane),this._clearControlPos&&this._clearControlPos(),this._resizeRequest&&=(x(this._resizeRequest),null),this._clearHandlers(),this._loaded&&this.fire(`unload`),this._layers)this._layers[e].remove();for(e in this._panes)B(this._panes[e]);return this._layers=[],this._panes=[],delete this._mapPane,delete this._renderer,this},createPane:function(e,n){var r=z(`div`,`leaflet-pane`+(e?` leaflet-`+e.replace(`Pane`,``)+`-pane`:``),n||this._mapPane);return e&&(this._panes[e]=r),r},getCenter:function(){return this._checkIfLoaded(),this._lastCenter&&!this._moved()?this._lastCenter.clone():this.layerPointToLatLng(this._getCenterLayerPoint())},getZoom:function(){return this._zoom},getBounds:function(){var e=this.getPixelBounds();return new k(this.unproject(e.getBottomLeft()),this.unproject(e.getTopRight()))},getMinZoom:function(){return this.options.minZoom===void 0?this._layersMinZoom||0:this.options.minZoom},getMaxZoom:function(){return this.options.maxZoom===void 0?this._layersMaxZoom===void 0?1/0:this._layersMaxZoom:this.options.maxZoom},getBoundsZoom:function(e,n,r){e=A(e),r=E(r||[0,0]);var i=this.getZoom()||0,a=this.getMinZoom(),o=this.getMaxZoom(),s=e.getNorthWest(),c=e.getSouthEast(),l=this.getSize().subtract(r),u=O(this.project(c,i),this.project(s,i)).getSize(),d=R.any3d?this.options.zoomSnap:1,f=l.x/u.x,p=l.y/u.y,m=n?Math.max(f,p):Math.min(f,p);return i=this.getScaleZoom(m,i),d&&(i=Math.round(i/(d/100))*(d/100),i=n?Math.ceil(i/d)*d:Math.floor(i/d)*d),Math.max(a,Math.min(o,i))},getSize:function(){return(!this._size||this._sizeChanged)&&(this._size=new w(this._container.clientWidth||0,this._container.clientHeight||0),this._sizeChanged=!1),this._size.clone()},getPixelBounds:function(e,n){var r=this._getTopLeftPoint(e,n);return new D(r,r.add(this.getSize()))},getPixelOrigin:function(){return this._checkIfLoaded(),this._pixelOrigin},getPixelWorldBounds:function(e){return this.options.crs.getProjectedBounds(e===void 0?this.getZoom():e)},getPane:function(e){return typeof e==`string`?this._panes[e]:e},getPanes:function(){return this._panes},getContainer:function(){return this._container},getZoomScale:function(e,n){var r=this.options.crs;return n=n===void 0?this._zoom:n,r.scale(e)/r.scale(n)},getScaleZoom:function(e,n){var r=this.options.crs;n=n===void 0?this._zoom:n;var i=r.zoom(e*r.scale(n));return isNaN(i)?1/0:i},project:function(e,n){return n=n===void 0?this._zoom:n,this.options.crs.latLngToPoint(M(e),n)},unproject:function(e,n){return n=n===void 0?this._zoom:n,this.options.crs.pointToLatLng(E(e),n)},layerPointToLatLng:function(e){var n=E(e).add(this.getPixelOrigin());return this.unproject(n)},latLngToLayerPoint:function(e){return this.project(M(e))._round()._subtract(this.getPixelOrigin())},wrapLatLng:function(e){return this.options.crs.wrapLatLng(M(e))},wrapLatLngBounds:function(e){return this.options.crs.wrapLatLngBounds(A(e))},distance:function(e,n){return this.options.crs.distance(M(e),M(n))},containerPointToLayerPoint:function(e){return E(e).subtract(this._getMapPanePos())},layerPointToContainerPoint:function(e){return E(e).add(this._getMapPanePos())},containerPointToLatLng:function(e){var n=this.containerPointToLayerPoint(E(e));return this.layerPointToLatLng(n)},latLngToContainerPoint:function(e){return this.layerPointToContainerPoint(this.latLngToLayerPoint(M(e)))},mouseEventToContainerPoint:function(e){return en(e,this._container)},mouseEventToLayerPoint:function(e){return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(e))},mouseEventToLatLng:function(e){return this.layerPointToLatLng(this.mouseEventToLayerPoint(e))},_initContainer:function(e){var n=this._container=St(e);if(!n)throw Error(`Map container not found.`);if(n._leaflet_id)throw Error(`Map container is already initialized.`);q(n,`scroll`,this._onScroll,this),this._containerId=s(n)},_initLayout:function(){var e=this._container;this._fadeAnimated=this.options.fadeAnimation&&R.any3d,V(e,`leaflet-container`+(R.touch?` leaflet-touch`:``)+(R.retina?` leaflet-retina`:``)+(R.ielt9?` leaflet-oldie`:``)+(R.safari?` leaflet-safari`:``)+(this._fadeAnimated?` leaflet-fade-anim`:``));var n=Ct(e,`position`);n!==`absolute`&&n!==`relative`&&n!==`fixed`&&n!==`sticky`&&(e.style.position=`relative`),this._initPanes(),this._initControlPos&&this._initControlPos()},_initPanes:function(){var e=this._panes={};this._paneRenderers={},this._mapPane=this.createPane(`mapPane`,this._container),W(this._mapPane,new w(0,0)),this.createPane(`tilePane`),this.createPane(`overlayPane`),this.createPane(`shadowPane`),this.createPane(`markerPane`),this.createPane(`tooltipPane`),this.createPane(`popupPane`),this.options.markerZoomAnimation||(V(e.markerPane,`leaflet-zoom-hide`),V(e.shadowPane,`leaflet-zoom-hide`))},_resetView:function(e,n,r){W(this._mapPane,new w(0,0));var i=!this._loaded;this._loaded=!0,n=this._limitZoom(n),this.fire(`viewprereset`);var a=this._zoom!==n;this._moveStart(a,r)._move(e,n)._moveEnd(a),this.fire(`viewreset`),i&&this.fire(`load`)},_moveStart:function(e,n){return e&&this.fire(`zoomstart`),n||this.fire(`movestart`),this},_move:function(e,n,r,i){n===void 0&&(n=this._zoom);var a=this._zoom!==n;return this._zoom=n,this._lastCenter=e,this._pixelOrigin=this._getNewPixelOrigin(e),i?r&&r.pinch&&this.fire(`zoom`,r):((a||r&&r.pinch)&&this.fire(`zoom`,r),this.fire(`move`,r)),this},_moveEnd:function(e){return e&&this.fire(`zoomend`),this.fire(`moveend`)},_stop:function(){return x(this._flyToFrame),this._panAnim&&this._panAnim.stop(),this},_rawPanBy:function(e){W(this._mapPane,this._getMapPanePos().subtract(e))},_getZoomSpan:function(){return this.getMaxZoom()-this.getMinZoom()},_panInsideMaxBounds:function(){this._enforcingBounds||this.panInsideBounds(this.options.maxBounds)},_checkIfLoaded:function(){if(!this._loaded)throw Error(`Set map center and zoom first.`)},_initEvents:function(e){this._targets={},this._targets[s(this._container)]=this;var n=e?Y:q;n(this._container,`click dblclick mousedown mouseup mouseover mouseout mousemove contextmenu keypress keydown keyup`,this._handleDOMEvent,this),this.options.trackResize&&n(window,`resize`,this._onResize,this),R.any3d&&this.options.transform3DLimit&&(e?this.off:this.on).call(this,`moveend`,this._onMoveEnd)},_onResize:function(){x(this._resizeRequest),this._resizeRequest=b(function(){this.invalidateSize({debounceMoveend:!0})},this)},_onScroll:function(){this._container.scrollTop=0,this._container.scrollLeft=0},_onMoveEnd:function(){var e=this._getMapPanePos();Math.max(Math.abs(e.x),Math.abs(e.y))>=this.options.transform3DLimit&&this._resetView(this.getCenter(),this.getZoom())},_findEventTargets:function(e,n){for(var r=[],i,a=n===`mouseout`||n===`mouseover`,o=e.target||e.srcElement,c=!1;o;){if(i=this._targets[s(o)],i&&(n===`click`||n===`preclick`)&&this._draggableMoved(i)){c=!0;break}if(i&&i.listens(n,!0)&&(a&&!rn(o,e)||(r.push(i),a))||o===this._container)break;o=o.parentNode}return!r.length&&!c&&!a&&this.listens(n,!0)&&(r=[this]),r},_isClickDisabled:function(e){for(;e&&e!==this._container;){if(e._leaflet_disable_click)return!0;e=e.parentNode}},_handleDOMEvent:function(e){var n=e.target||e.srcElement;if(!(!this._loaded||n._leaflet_disable_events||e.type===`click`&&this._isClickDisabled(n))){var r=e.type;r===`mousedown`&&K(n),this._fireDOMEvent(e,r)}},_mouseEvents:[`click`,`dblclick`,`mouseover`,`mouseout`,`contextmenu`],_fireDOMEvent:function(e,n,i){if(e.type===`click`){var a=r({},e);a.type=`preclick`,this._fireDOMEvent(a,a.type,i)}var o=this._findEventTargets(e,n);if(i){for(var s=[],c=0;c0?Math.round(e-n)/2:Math.max(0,Math.ceil(e))-Math.max(0,Math.floor(n))},_limitZoom:function(e){var n=this.getMinZoom(),r=this.getMaxZoom(),i=R.any3d?this.options.zoomSnap:1;return i&&(e=Math.round(e/i)*i),Math.max(n,Math.min(r,e))},_onPanTransitionStep:function(){this.fire(`move`)},_onPanTransitionEnd:function(){H(this._mapPane,`leaflet-pan-anim`),this.fire(`moveend`)},_tryAnimatedPan:function(e,n){var r=this._getCenterOffset(e)._trunc();return(n&&n.animate)!==!0&&!this.getSize().contains(r)?!1:(this.panBy(r,n),!0)},_createAnimProxy:function(){var e=this._proxy=z(`div`,`leaflet-proxy leaflet-zoom-animated`);this._panes.mapPane.appendChild(e),this.on(`zoomanim`,function(e){var n=yt,r=this._proxy.style[n];Mt(this._proxy,this.project(e.center,e.zoom),this.getZoomScale(e.zoom,1)),r===this._proxy.style[n]&&this._animatingZoom&&this._onZoomTransitionEnd()},this),this.on(`load moveend`,this._animMoveEnd,this),this._on(`unload`,this._destroyAnimProxy,this)},_destroyAnimProxy:function(){B(this._proxy),this.off(`load moveend`,this._animMoveEnd,this),delete this._proxy},_animMoveEnd:function(){var e=this.getCenter(),n=this.getZoom();Mt(this._proxy,this.project(e,n),this.getZoomScale(n,1))},_catchTransitionEnd:function(e){this._animatingZoom&&e.propertyName.indexOf(`transform`)>=0&&this._onZoomTransitionEnd()},_nothingToAnimate:function(){return!this._container.getElementsByClassName(`leaflet-zoom-animated`).length},_tryAnimatedZoom:function(e,n,r){if(this._animatingZoom)return!0;if(r||={},!this._zoomAnimated||r.animate===!1||this._nothingToAnimate()||Math.abs(n-this._zoom)>this.options.zoomAnimationThreshold)return!1;var i=this.getZoomScale(n),a=this._getCenterOffset(e)._divideBy(1-1/i);return r.animate!==!0&&!this.getSize().contains(a)?!1:(b(function(){this._moveStart(!0,r.noMoveStart||!1)._animateZoom(e,n,!0)},this),!0)},_animateZoom:function(e,n,r,i){this._mapPane&&(r&&(this._animatingZoom=!0,this._animateToCenter=e,this._animateToZoom=n,V(this._mapPane,`leaflet-zoom-anim`)),this.fire(`zoomanim`,{center:e,zoom:n,noUpdate:i}),this._tempFireZoomEvent||=this._zoom!==this._animateToZoom,this._move(this._animateToCenter,this._animateToZoom,void 0,!0),setTimeout(a(this._onZoomTransitionEnd,this),250))},_onZoomTransitionEnd:function(){this._animatingZoom&&(this._mapPane&&H(this._mapPane,`leaflet-zoom-anim`),this._animatingZoom=!1,this._move(this._animateToCenter,this._animateToZoom,void 0,!0),this._tempFireZoomEvent&&this.fire(`zoom`),delete this._tempFireZoomEvent,this.fire(`move`),this._moveEnd(!0))}});function sn(e,n){return new Z(e,n)}var Q=S.extend({options:{position:`topright`},initialize:function(e){m(this,e)},getPosition:function(){return this.options.position},setPosition:function(e){var n=this._map;return n&&n.removeControl(this),this.options.position=e,n&&n.addControl(this),this},getContainer:function(){return this._container},addTo:function(e){this.remove(),this._map=e;var n=this._container=this.onAdd(e),r=this.getPosition(),i=e._controlCorners[r];return V(n,`leaflet-control`),r.indexOf(`bottom`)===-1?i.appendChild(n):i.insertBefore(n,i.firstChild),this._map.on(`unload`,this.remove,this),this},remove:function(){return this._map?(B(this._container),this.onRemove&&this.onRemove(this._map),this._map.off(`unload`,this.remove,this),this._map=null,this):this},_refocusOnMap:function(e){this._map&&e&&e.screenX>0&&e.screenY>0&&this._map.getContainer().focus()}}),cn=function(e){return new Q(e)};Z.include({addControl:function(e){return e.addTo(this),this},removeControl:function(e){return e.remove(),this},_initControlPos:function(){var e=this._controlCorners={},n=`leaflet-`,r=this._controlContainer=z(`div`,n+`control-container`,this._container);function i(i,a){var o=n+i+` `+n+a;e[i+a]=z(`div`,o,r)}i(`top`,`left`),i(`top`,`right`),i(`bottom`,`left`),i(`bottom`,`right`)},_clearControlPos:function(){for(var e in this._controlCorners)B(this._controlCorners[e]);B(this._controlContainer),delete this._controlCorners,delete this._controlContainer}});var ln=Q.extend({options:{collapsed:!0,position:`topright`,autoZIndex:!0,hideSingleBase:!1,sortLayers:!1,sortFunction:function(e,n,r,i){return r1,this._baseLayersList.style.display=e?``:`none`),this._separator.style.display=n&&e?``:`none`,this},_onLayerChange:function(e){this._handlingClick||this._update();var n=this._getLayer(s(e.target)),r=n.overlay?e.type===`add`?`overlayadd`:`overlayremove`:e.type===`add`?`baselayerchange`:null;r&&this._map.fire(r,n)},_createRadioElement:function(e,n){var r=``,i=document.createElement(`div`);return i.innerHTML=r,i.firstChild},_addItem:function(e){var n=document.createElement(`label`),r=this._map.hasLayer(e.layer),i;e.overlay?(i=document.createElement(`input`),i.type=`checkbox`,i.className=`leaflet-control-layers-selector`,i.defaultChecked=r):i=this._createRadioElement(`leaflet-base-layers_`+s(this),r),this._layerControlInputs.push(i),i.layerId=s(e.layer),q(i,`click`,this._onInputClick,this);var a=document.createElement(`span`);a.innerHTML=` `+e.name;var o=document.createElement(`span`);return n.appendChild(o),o.appendChild(i),o.appendChild(a),(e.overlay?this._overlaysList:this._baseLayersList).appendChild(n),this._checkDisabledLayers(),n},_onInputClick:function(){if(!this._preventClick){var e=this._layerControlInputs,n,r,i=[],a=[];this._handlingClick=!0;for(var o=e.length-1;o>=0;o--)n=e[o],r=this._getLayer(n.layerId).layer,n.checked?i.push(r):n.checked||a.push(r);for(o=0;o=0;a--)n=e[a],r=this._getLayer(n.layerId).layer,n.disabled=r.options.minZoom!==void 0&&ir.options.maxZoom},_expandIfNotCollapsed:function(){return this._map&&!this.options.collapsed&&this.expand(),this},_expandSafely:function(){var e=this._section;this._preventClick=!0,q(e,`click`,X),this.expand();var n=this;setTimeout(function(){Y(e,`click`,X),n._preventClick=!1})}}),un=function(e,n,r){return new ln(e,n,r)},dn=Q.extend({options:{position:`topleft`,zoomInText:``,zoomInTitle:`Zoom in`,zoomOutText:``,zoomOutTitle:`Zoom out`},onAdd:function(e){var n=`leaflet-control-zoom`,r=z(`div`,n+` leaflet-bar`),i=this.options;return this._zoomInButton=this._createButton(i.zoomInText,i.zoomInTitle,n+`-in`,r,this._zoomIn),this._zoomOutButton=this._createButton(i.zoomOutText,i.zoomOutTitle,n+`-out`,r,this._zoomOut),this._updateDisabled(),e.on(`zoomend zoomlevelschange`,this._updateDisabled,this),r},onRemove:function(e){e.off(`zoomend zoomlevelschange`,this._updateDisabled,this)},disable:function(){return this._disabled=!0,this._updateDisabled(),this},enable:function(){return this._disabled=!1,this._updateDisabled(),this},_zoomIn:function(e){!this._disabled&&this._map._zoomthis._map.getMinZoom()&&this._map.zoomOut(this._map.options.zoomDelta*(e.shiftKey?3:1))},_createButton:function(e,n,r,i,a){var o=z(`a`,r,i);return o.innerHTML=e,o.href=`#`,o.title=n,o.setAttribute(`role`,`button`),o.setAttribute(`aria-label`,n),Zt(o),q(o,`click`,Qt),q(o,`click`,a,this),q(o,`click`,this._refocusOnMap,this),o},_updateDisabled:function(){var e=this._map,n=`leaflet-disabled`;H(this._zoomInButton,n),H(this._zoomOutButton,n),this._zoomInButton.setAttribute(`aria-disabled`,`false`),this._zoomOutButton.setAttribute(`aria-disabled`,`false`),(this._disabled||e._zoom===e.getMinZoom())&&(V(this._zoomOutButton,n),this._zoomOutButton.setAttribute(`aria-disabled`,`true`)),(this._disabled||e._zoom===e.getMaxZoom())&&(V(this._zoomInButton,n),this._zoomInButton.setAttribute(`aria-disabled`,`true`))}});Z.mergeOptions({zoomControl:!0}),Z.addInitHook(function(){this.options.zoomControl&&(this.zoomControl=new dn,this.addControl(this.zoomControl))});var fn=function(e){return new dn(e)},pn=Q.extend({options:{position:`bottomleft`,maxWidth:100,metric:!0,imperial:!0},onAdd:function(e){var n=`leaflet-control-scale`,r=z(`div`,n),i=this.options;return this._addScales(i,n+`-line`,r),e.on(i.updateWhenIdle?`moveend`:`move`,this._update,this),e.whenReady(this._update,this),r},onRemove:function(e){e.off(this.options.updateWhenIdle?`moveend`:`move`,this._update,this)},_addScales:function(e,n,r){e.metric&&(this._mScale=z(`div`,n,r)),e.imperial&&(this._iScale=z(`div`,n,r))},_update:function(){var e=this._map,n=e.getSize().y/2,r=e.distance(e.containerPointToLatLng([0,n]),e.containerPointToLatLng([this.options.maxWidth,n]));this._updateScales(r)},_updateScales:function(e){this.options.metric&&e&&this._updateMetric(e),this.options.imperial&&e&&this._updateImperial(e)},_updateMetric:function(e){var n=this._getRoundNum(e),r=n<1e3?n+` m`:n/1e3+` km`;this._updateScale(this._mScale,r,n/e)},_updateImperial:function(e){var n=e*3.2808399,r,i,a;n>5280?(r=n/5280,i=this._getRoundNum(r),this._updateScale(this._iScale,i+` mi`,i/r)):(a=this._getRoundNum(n),this._updateScale(this._iScale,a+` ft`,a/n))},_updateScale:function(e,n,r){e.style.width=Math.round(this.options.maxWidth*r)+`px`,e.innerHTML=n},_getRoundNum:function(e){var n=10**((Math.floor(e)+``).length-1),r=e/n;return r=r>=10?10:r>=5?5:r>=3?3:r>=2?2:1,n*r}}),mn=function(e){return new pn(e)},hn=Q.extend({options:{position:`bottomright`,prefix:``+(R.inlineSvg?` `:``)+`Leaflet`},initialize:function(e){m(this,e),this._attributions={}},onAdd:function(e){for(var n in e.attributionControl=this,this._container=z(`div`,`leaflet-control-attribution`),Zt(this._container),e._layers)e._layers[n].getAttribution&&this.addAttribution(e._layers[n].getAttribution());return this._update(),e.on(`layeradd`,this._addAttribution,this),this._container},onRemove:function(e){e.off(`layeradd`,this._addAttribution,this)},_addAttribution:function(e){e.layer.getAttribution&&(this.addAttribution(e.layer.getAttribution()),e.layer.once(`remove`,function(){this.removeAttribution(e.layer.getAttribution())},this))},setPrefix:function(e){return this.options.prefix=e,this._update(),this},addAttribution:function(e){return e?(this._attributions[e]||(this._attributions[e]=0),this._attributions[e]++,this._update(),this):this},removeAttribution:function(e){return e&&this._attributions[e]&&(this._attributions[e]--,this._update()),this},_update:function(){if(this._map){var e=[];for(var n in this._attributions)this._attributions[n]&&e.push(n);var r=[];this.options.prefix&&r.push(this.options.prefix),e.length&&r.push(e.join(`, `)),this._container.innerHTML=r.join(` `)}}});Z.mergeOptions({attributionControl:!0}),Z.addInitHook(function(){this.options.attributionControl&&new hn().addTo(this)}),Q.Layers=ln,Q.Zoom=dn,Q.Scale=pn,Q.Attribution=hn,cn.layers=un,cn.zoom=fn,cn.scale=mn,cn.attribution=function(e){return new hn(e)};var gn=S.extend({initialize:function(e){this._map=e},enable:function(){return this._enabled?this:(this._enabled=!0,this.addHooks(),this)},disable:function(){return this._enabled?(this._enabled=!1,this.removeHooks(),this):this},enabled:function(){return!!this._enabled}});gn.addTo=function(e,n){return e.addHandler(n,this),this};var _n={Events:C},vn=R.touch?`touchstart mousedown`:`mousedown`,yn=ce.extend({options:{clickTolerance:3},initialize:function(e,n,r,i){m(this,i),this._element=e,this._dragStartTarget=n||e,this._preventOutline=r},enable:function(){this._enabled||=(q(this._dragStartTarget,vn,this._onDown,this),!0)},disable:function(){this._enabled&&(yn._dragging===this&&this.finishDrag(!0),Y(this._dragStartTarget,vn,this._onDown,this),this._enabled=!1,this._moved=!1)},_onDown:function(e){if(this._enabled&&(this._moved=!1,!Dt(this._element,`leaflet-zoom-anim`))){if(e.touches&&e.touches.length!==1){yn._dragging===this&&this.finishDrag();return}if(!(yn._dragging||e.shiftKey||e.which!==1&&e.button!==1&&!e.touches)&&(yn._dragging=this,this._preventOutline&&K(this._element),Lt(),G(),!this._moving)){this.fire(`down`);var n=e.touches?e.touches[0]:e,r=Ht(this._element);this._startPoint=new w(n.clientX,n.clientY),this._startPos=Nt(this._element),this._parentScale=Ut(r);var i=e.type===`mousedown`;q(document,i?`mousemove`:`touchmove`,this._onMove,this),q(document,i?`mouseup`:`touchend touchcancel`,this._onUp,this)}}},_onMove:function(e){if(this._enabled){if(e.touches&&e.touches.length>1){this._moved=!0;return}var n=e.touches&&e.touches.length===1?e.touches[0]:e,r=new w(n.clientX,n.clientY)._subtract(this._startPoint);!r.x&&!r.y||Math.abs(r.x)+Math.abs(r.y)o&&(s=c,o=l);o>r&&(n[s]=1,On(e,n,r,i,s),On(e,n,r,s,a))}function kn(e,n){for(var r=[e[0]],i=1,a=0,o=e.length;in&&(r.push(e[i]),a=i);return an.max.x&&(r|=2),e.yn.max.y&&(r|=8),r}function Pn(e,n){var r=n.x-e.x,i=n.y-e.y;return r*r+i*i}function Fn(e,n,r,i){var a=n.x,o=n.y,s=r.x-a,c=r.y-o,l=s*s+c*c,u;return l>0&&(u=((e.x-a)*s+(e.y-o)*c)/l,u>1?(a=r.x,o=r.y):u>0&&(a+=s*u,o+=c*u)),s=e.x-a,c=e.y-o,i?s*s+c*c:new w(a,o)}function $(e){return!v(e[0])||typeof e[0][0]!=`object`&&e[0][0]!==void 0}function In(e){return console.warn(`Deprecated use of _flat, please use L.LineUtil.isFlat instead.`),$(e)}function Ln(e,n){var r,i,a,o,s,c,l,u;if(!e||e.length===0)throw Error(`latlngs not passed`);$(e)||(console.warn(`latlngs are not flat! Only the first ring will be used`),e=e[0]);var d=M([0,0]),f=A(e);f.getNorthWest().distanceTo(f.getSouthWest())*f.getNorthEast().distanceTo(f.getNorthWest())<1700&&(d=Sn(e));var p=e.length,m=[];for(r=0;ri){l=(o-i)/a,u=[c.x-l*(c.x-s.x),c.y-l*(c.y-s.y)];break}var g=n.unproject(E(u));return M([g.lat+d.lat,g.lng+d.lng])}var Rn={__proto__:null,simplify:wn,pointToSegmentDistance:Tn,closestPointOnSegment:En,clipSegment:jn,_getEdgeIntersection:Mn,_getBitCode:Nn,_sqClosestPointOnSegment:Fn,isFlat:$,_flat:In,polylineCenter:Ln},zn={project:function(e){return new w(e.lng,e.lat)},unproject:function(e){return new j(e.y,e.x)},bounds:new D([-180,-90],[180,90])},Bn={R:6378137,R_MINOR:6356752.314245179,bounds:new D([-20037508.34279,-15496570.73972],[20037508.34279,18764656.23138]),project:function(e){var n=Math.PI/180,r=this.R,i=e.lat*n,a=this.R_MINOR/r,o=Math.sqrt(1-a*a),s=o*Math.sin(i),c=Math.tan(Math.PI/4-i/2)/((1-s)/(1+s))**(o/2);return i=-r*Math.log(Math.max(c,1e-10)),new w(e.lng*n*r,i)},unproject:function(e){for(var n=180/Math.PI,r=this.R,i=this.R_MINOR/r,a=Math.sqrt(1-i*i),o=Math.exp(-e.y/r),s=Math.PI/2-2*Math.atan(o),c=0,l=.1,u;c<15&&Math.abs(l)>1e-7;c++)u=a*Math.sin(s),u=((1-u)/(1+u))**(a/2),l=Math.PI/2-2*Math.atan(o*u)-s,s+=l;return new j(s*n,e.x*n/r)}},Vn={__proto__:null,LonLat:zn,Mercator:Bn,SphericalMercator:de},Hn=r({},le,{code:`EPSG:3395`,projection:Bn,transformation:function(){var e=.5/(Math.PI*Bn.R);return pe(e,.5,-e,.5)}()}),Un=r({},le,{code:`EPSG:4326`,projection:zn,transformation:pe(1/180,1,-1/180,.5)}),Wn=r({},N,{projection:zn,transformation:pe(1,0,-1,0),scale:function(e){return 2**e},zoom:function(e){return Math.log(e)/Math.LN2},distance:function(e,n){var r=n.lng-e.lng,i=n.lat-e.lat;return Math.sqrt(r*r+i*i)},infinite:!0});N.Earth=le,N.EPSG3395=Hn,N.EPSG3857=me,N.EPSG900913=he,N.EPSG4326=Un,N.Simple=Wn;var Gn=ce.extend({options:{pane:`overlayPane`,attribution:null,bubblingMouseEvents:!0},addTo:function(e){return e.addLayer(this),this},remove:function(){return this.removeFrom(this._map||this._mapToAdd)},removeFrom:function(e){return e&&e.removeLayer(this),this},getPane:function(e){return this._map.getPane(e?this.options[e]||e:this.options.pane)},addInteractiveTarget:function(e){return this._map._targets[s(e)]=this,this},removeInteractiveTarget:function(e){return delete this._map._targets[s(e)],this},getAttribution:function(){return this.options.attribution},_layerAdd:function(e){var n=e.target;if(n.hasLayer(this)){if(this._map=n,this._zoomAnimated=n._zoomAnimated,this.getEvents){var r=this.getEvents();n.on(r,this),this.once(`remove`,function(){n.off(r,this)},this)}this.onAdd(n),this.fire(`add`),n.fire(`layeradd`,{layer:this})}}});Z.include({addLayer:function(e){if(!e._layerAdd)throw Error(`The provided object is not a Layer.`);var n=s(e);return this._layers[n]?this:(this._layers[n]=e,e._mapToAdd=this,e.beforeAdd&&e.beforeAdd(this),this.whenReady(e._layerAdd,e),this)},removeLayer:function(e){var n=s(e);return this._layers[n]?(this._loaded&&e.onRemove(this),delete this._layers[n],this._loaded&&(this.fire(`layerremove`,{layer:e}),e.fire(`remove`)),e._map=e._mapToAdd=null,this):this},hasLayer:function(e){return s(e)in this._layers},eachLayer:function(e,n){for(var r in this._layers)e.call(n,this._layers[r]);return this},_addLayers:function(e){e=e?v(e)?e:[e]:[];for(var n=0,r=e.length;nthis._layersMaxZoom&&this.setZoom(this._layersMaxZoom),this.options.minZoom===void 0&&this._layersMinZoom&&this.getZoom()=2&&n[0]instanceof j&&n[0].equals(n[r-1])&&n.pop(),n},_setLatLngs:function(e){sr.prototype._setLatLngs.call(this,e),$(this._latlngs)&&(this._latlngs=[this._latlngs])},_defaultShape:function(){return $(this._latlngs[0])?this._latlngs[0]:this._latlngs[0][0]},_clipPoints:function(){var e=this._renderer._bounds,n=this.options.weight,r=new w(n,n);if(e=new D(e.min.subtract(r),e.max.add(r)),this._parts=[],!(!this._pxBounds||!this._pxBounds.intersects(e))){if(this.options.noClip){this._parts=this._rings;return}for(var i=0,a=this._rings.length,o;ie.y!=a.y>e.y&&e.x<(a.x-i.x)*(e.y-i.y)/(a.y-i.y)+i.x&&(n=!n);return n||sr.prototype._containsPoint.call(this,e,!0)}});function ur(e,n){return new lr(e,n)}var dr=Jn.extend({initialize:function(e,n){m(this,n),this._layers={},e&&this.addData(e)},addData:function(e){var n=v(e)?e:e.features,r,i,a;if(n){for(r=0,i=n.length;r0&&a.push(a[0].slice()),a}function vr(e,n){return e.feature?r({},e.feature,{geometry:n}):yr(n)}function yr(e){return e.type===`Feature`||e.type===`FeatureCollection`?e:{type:`Feature`,properties:{},geometry:e}}var br={toGeoJSON:function(e){return vr(this,{type:`Point`,coordinates:gr(this.getLatLng(),e)})}};er.include(br),ar.include(br),rr.include(br),sr.include({toGeoJSON:function(e){var n=!$(this._latlngs),r=_r(this._latlngs,+!!n,!1,e);return vr(this,{type:(n?`Multi`:``)+`LineString`,coordinates:r})}}),lr.include({toGeoJSON:function(e){var n=!$(this._latlngs),r=n&&!$(this._latlngs[0]),i=_r(this._latlngs,r?2:+!!n,!0,e);return n||(i=[i]),vr(this,{type:(r?`Multi`:``)+`Polygon`,coordinates:i})}}),Kn.include({toMultiPoint:function(e){var n=[];return this.eachLayer(function(r){n.push(r.toGeoJSON(e).geometry.coordinates)}),vr(this,{type:`MultiPoint`,coordinates:n})},toGeoJSON:function(e){var n=this.feature&&this.feature.geometry&&this.feature.geometry.type;if(n===`MultiPoint`)return this.toMultiPoint(e);var r=n===`GeometryCollection`,i=[];return this.eachLayer(function(n){if(n.toGeoJSON){var a=n.toGeoJSON(e);if(r)i.push(a.geometry);else{var o=yr(a);o.type===`FeatureCollection`?i.push.apply(i,o.features):i.push(o)}}}),r?vr(this,{geometries:i,type:`GeometryCollection`}):{type:`FeatureCollection`,features:i}}});function xr(e,n){return new dr(e,n)}var Sr=xr,Cr=Gn.extend({options:{opacity:1,alt:``,interactive:!1,crossOrigin:!1,errorOverlayUrl:``,zIndex:1,className:``},initialize:function(e,n,r){this._url=e,this._bounds=A(n),m(this,r)},onAdd:function(){this._image||(this._initImage(),this.options.opacity<1&&this._updateOpacity()),this.options.interactive&&(V(this._image,`leaflet-interactive`),this.addInteractiveTarget(this._image)),this.getPane().appendChild(this._image),this._reset()},onRemove:function(){B(this._image),this.options.interactive&&this.removeInteractiveTarget(this._image)},setOpacity:function(e){return this.options.opacity=e,this._image&&this._updateOpacity(),this},setStyle:function(e){return e.opacity&&this.setOpacity(e.opacity),this},bringToFront:function(){return this._map&&Tt(this._image),this},bringToBack:function(){return this._map&&Et(this._image),this},setUrl:function(e){return this._url=e,this._image&&(this._image.src=e),this},setBounds:function(e){return this._bounds=A(e),this._map&&this._reset(),this},getEvents:function(){var e={zoom:this._reset,viewreset:this._reset};return this._zoomAnimated&&(e.zoomanim=this._animateZoom),e},setZIndex:function(e){return this.options.zIndex=e,this._updateZIndex(),this},getBounds:function(){return this._bounds},getElement:function(){return this._image},_initImage:function(){var e=this._url.tagName===`IMG`,n=this._image=e?this._url:z(`img`);if(V(n,`leaflet-image-layer`),this._zoomAnimated&&V(n,`leaflet-zoom-animated`),this.options.className&&V(n,this.options.className),n.onselectstart=u,n.onmousemove=u,n.onload=a(this.fire,this,`load`),n.onerror=a(this._overlayOnError,this,`error`),(this.options.crossOrigin||this.options.crossOrigin===``)&&(n.crossOrigin=this.options.crossOrigin===!0?``:this.options.crossOrigin),this.options.zIndex&&this._updateZIndex(),e){this._url=n.src;return}n.src=this._url,n.alt=this.options.alt},_animateZoom:function(e){var n=this._map.getZoomScale(e.zoom),r=this._map._latLngBoundsToNewLayerBounds(this._bounds,e.zoom,e.center).min;Mt(this._image,r,n)},_reset:function(){var e=this._image,n=new D(this._map.latLngToLayerPoint(this._bounds.getNorthWest()),this._map.latLngToLayerPoint(this._bounds.getSouthEast())),r=n.getSize();W(e,n.min),e.style.width=r.x+`px`,e.style.height=r.y+`px`},_updateOpacity:function(){U(this._image,this.options.opacity)},_updateZIndex:function(){this._image&&this.options.zIndex!==void 0&&this.options.zIndex!==null&&(this._image.style.zIndex=this.options.zIndex)},_overlayOnError:function(){this.fire(`error`);var e=this.options.errorOverlayUrl;e&&this._url!==e&&(this._url=e,this._image.src=e)},getCenter:function(){return this._bounds.getCenter()}}),wr=function(e,n,r){return new Cr(e,n,r)},Tr=Cr.extend({options:{autoplay:!0,loop:!0,keepAspectRatio:!0,muted:!1,playsInline:!0},_initImage:function(){var e=this._url.tagName===`VIDEO`,n=this._image=e?this._url:z(`video`);if(V(n,`leaflet-image-layer`),this._zoomAnimated&&V(n,`leaflet-zoom-animated`),this.options.className&&V(n,this.options.className),n.onselectstart=u,n.onmousemove=u,n.onloadeddata=a(this.fire,this,`load`),e){for(var r=n.getElementsByTagName(`source`),i=[],o=0;o0?i:[n.src];return}v(this._url)||(this._url=[this._url]),!this.options.keepAspectRatio&&Object.prototype.hasOwnProperty.call(n.style,`objectFit`)&&(n.style.objectFit=`fill`),n.autoplay=!!this.options.autoplay,n.loop=!!this.options.loop,n.muted=!!this.options.muted,n.playsInline=!!this.options.playsInline;for(var s=0;s