skapi-js 2.1.0 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/skapi.d.ts CHANGED
@@ -85,7 +85,7 @@ type PostRecordConfig = {
85
85
  name?: string;
86
86
  /** Number range: 0 ~ 99. 'public' = 0, 'authorized' = 1, 'admin' = 99. '*' is shorthand for 'private'. Default: 'public' */
87
87
  access_group?: number | 'private' | '*' | 'public' | 'authorized' | 'admin';
88
- /** When true, Record will be only accessible for subscribed users. */
88
+ /** How the record reaches the uploader's subscribers. Signed-in users only. */
89
89
  subscription?: {
90
90
  is_subscription_record?: boolean;
91
91
  upload_to_feed?: boolean;
@@ -94,6 +94,16 @@ type PostRecordConfig = {
94
94
  notify_referencing_records?: boolean;
95
95
  } | null;
96
96
  };
97
+ /**
98
+ * Title and body of the push notification the record's creation sends to the uploader's
99
+ * subscribers with table.subscription.notify_subscribers. Both are required, and together
100
+ * they must fit 3072 bytes. Without it, subscribers get a default text. Ignored on updates
101
+ * and without notify_subscribers.
102
+ */
103
+ notification?: {
104
+ title: string;
105
+ body: string;
106
+ } | null;
97
107
  source?: {
98
108
  referencing_limit?: number;
99
109
  prevent_multiple_referencing?: boolean;
@@ -186,8 +196,9 @@ type RecordData = {
186
196
  name: string;
187
197
  /** Number range: 0 ~ 99 */
188
198
  access_group: number | 'private' | 'public' | 'authorized' | 'admin';
189
- /** User ID of subscription */
199
+ /** Subscription settings of the record. See PostRecordConfig.table.subscription. */
190
200
  subscription?: {
201
+ is_subscription_record: boolean;
191
202
  upload_to_feed: boolean;
192
203
  notify_subscribers: boolean;
193
204
  feed_referencing_records: boolean;
@@ -660,45 +671,75 @@ type Subscription = {
660
671
  get_notified: boolean;
661
672
  get_email: boolean;
662
673
  };
663
- /** Comparison operator of a ticket condition row. The word forms are normalized to the symbols on registration. For a string value, '>=' means "starts with". */
674
+ /**
675
+ * Comparison operator of a ticket condition row, and of `ip` and `user_agent`. The word forms
676
+ * are normalized to the symbols on registration.
677
+ *
678
+ * - '=' and '!=' compare the way JavaScript's === does: true is not 1 and "1" is not 1.
679
+ * - On two numbers, '>', '>=', '<' and '<=' compare numerically.
680
+ * - On two strings, '>=' means "starts with" and '<=' means "ends with". '>' and '<' use plain string order.
681
+ * - A string against a number (or the reverse), a boolean, null or undefined never passes '>', '>=', '<' or '<='.
682
+ * - With a list value, '=' and the ordering operators pass when any member passes. '!=' passes when the value is none of them.
683
+ */
664
684
  type TicketConditionOperator = '=' | '!=' | '>' | '>=' | '<' | '<=' | 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte';
665
685
  /**
666
- * One row of a ticket condition list (`headers`, `data`, `params`, `user`, `match`).
667
- * Rows with the same key are alternatives (any one matching satisfies the key), rows with
668
- * different keys must all match. A comparison between incompatible types is a mismatch.
686
+ * One row of a ticket condition list: `headers`, `data`, `params` or `user` of a ticket's
687
+ * condition, or `headers`, `data` or `user` of a req action's response condition.
688
+ *
689
+ * How a list decides:
690
+ * - Rows on the same key are alternatives: the key passes when any one of them matches.
691
+ * - Every different key that has a match row (a row with an `operator`) must pass. The first key
692
+ * that does not fails the consumption with CONDITION_FAILED, `detail: { field, keys }`.
693
+ * - A field missing from the request is a mismatch for its key, '!=' included, not an error.
694
+ * The only rows that pass on a missing field are `= undefined` and `!= null`.
695
+ * - Every row is read, in order. For each key the FIRST matching row wins: its `setValueWhenMatch`
696
+ * applies and its `placeholder` captures, and later rows on that key are skipped. A row that
697
+ * does not match captures nothing, so several rows on one key, each with its own
698
+ * `setValueWhenMatch`, followed by a catch-all row, work as a lookup table.
699
+ * - A capture-only row (a `placeholder` and no `operator`) never counts toward passing. It
700
+ * captures whenever its field exists.
701
+ * - Header names ignore case, and header values are always strings. Query string values are
702
+ * JSON-parsed when they parse, otherwise they stay strings: `?qty=2` is the number 2 and
703
+ * `?code=LAUNCH24` the string "LAUNCH24". '=' is strict, so it compares the parsed value: a
704
+ * `params` row needs `value: 2`, not "2", to match `?qty=2`.
705
+ *
706
+ * null and undefined (`data` and `params` rows only, in a response condition too):
707
+ * - `= null` passes when the field is present and null. `!= null` passes otherwise, a missing field included.
708
+ * - `= undefined` passes when the field is missing. `!= undefined` passes when it is present, null included.
709
+ * - '>', '>=', '<' and '<=' never pass with null or undefined.
710
+ * - undefined is a row with an `operator` and no `value` key, which is what `value: undefined` sends.
711
+ * A value list may contain null. undefined is only ever a single value.
669
712
  */
670
713
  type TicketConditionRow = {
671
714
  /**
672
- * `data` and `params` rows: a path into the request, such as "data[object][id]" (the leading
673
- * "data" there is the request's own key, not the row list). `headers` rows: the header name,
674
- * matched case-insensitively. `user` rows: the consumer attribute name. Never templated.
715
+ * Where the row looks, relative to its own list and written without `${ }`:
716
+ * - `data` rows: a path into the request body. "id" is the body's `id`, "order[id]" is `order.id`.
717
+ * - `params` rows: a path into the query string, read the same way.
718
+ * - `data` rows of a req action's response condition: a path into the response body ("status" is the response's `status`).
719
+ * - `headers` rows: the header name, matched case-insensitively.
720
+ * - `user` rows: the consumer attribute name.
721
+ *
722
+ * Never templated.
675
723
  */
676
724
  key: string;
677
- /** Absent, with no `value`, on a capture-only row: it never fails and only fills `placeholder`. */
725
+ /** Absent on a capture-only row, which has a `placeholder` and no `value`. */
678
726
  operator?: TicketConditionOperator;
679
- /** A literal, never templated. A list passes when any member matches. */
680
- value?: any;
681
- /** `data` and `params` rows only. When the row matches, the value at `key` in the request data is replaced by this before anything else reads it. */
727
+ /**
728
+ * A literal, never templated. A list is read as described in TicketConditionOperator.
729
+ * null, a list containing null, and undefined (an `operator` with no `value` key) are for
730
+ * `data` and `params` rows only.
731
+ */
732
+ value?: string | number | boolean | null | undefined | Array<string | number | boolean | null>;
733
+ /** `data` and `params` rows only. When this row is the first matching row of its key, the value at `key` in the request data is replaced by this before anything else reads it. null replaces nothing. */
682
734
  setValueWhenMatch?: any;
683
- /** `data` and `params` rows only. Remembers the value at `key` under this name for the actions ("placeholder[NAME]"). Must match ^[A-Za-z_][A-Za-z0-9_]*$. */
735
+ /**
736
+ * `data` and `params` rows only. Remembers the value at `key` under this name, and the
737
+ * actions read it as `${placeholder[NAME]}`. A match row captures only when it is the first
738
+ * matching row of its key. A field that is missing captures nothing. Must match
739
+ * ^[A-Za-z_][A-Za-z0-9_]*$.
740
+ */
684
741
  placeholder?: string;
685
742
  };
686
- /** An HTTP call whose response must match. `url`, `headers`, `data` and `params` are templated like an action's `exe`; `match` rows are not. */
687
- type TicketRequestCondition = {
688
- /** http:// or https:// with a hostname. No IP literal, no userinfo, never under the api domain. */
689
- url: string;
690
- method?: 'GET' | 'POST';
691
- headers?: {
692
- [name: string]: string;
693
- };
694
- /** Sent as JSON when a content-type header says application/json, else form encoded. */
695
- data?: any;
696
- params?: {
697
- [key: string]: any;
698
- };
699
- /** Rows matched against the response body. */
700
- match?: TicketConditionRow[];
701
- };
702
743
  /**
703
744
  * An HMAC signature over the request, computed with a secret shared with the sender. Verified
704
745
  * before anything else runs: the `timestamp` (when set) must be an integer within `tolerance` of
@@ -709,13 +750,18 @@ type TicketRequestCondition = {
709
750
  * Templates (`signed`, `timestamp`) are literal text with these tokens: `${body}` (the raw request
710
751
  * body exactly as received), `${method}` (the HTTP method, upper case), `${header:Name}` (a request
711
752
  * header, case-insensitive; an absent header fails verification) and any capture from `parts` other
712
- * than `${signature}`. An unknown token is refused at registration.
753
+ * than `${signature}`. An unknown token is refused at registration. These tokens exist only in
754
+ * the signature templates: they are not the references actions use (see TicketAction).
713
755
  *
714
756
  * Public-key signature schemes (RSA, ECDSA, Ed25519) are not supported.
715
757
  */
716
758
  type TicketSignatureCondition = {
717
- /** The name of a Secret Key of the project, never the secret itself. Must exist at registration. */
718
- secret: string;
759
+ /**
760
+ * The name of a Secret Key of the project, never the secret itself. Must exist at
761
+ * registration. It is only used to verify the signature: no action sends it, and its
762
+ * Destinations do not limit the ticket's req actions.
763
+ */
764
+ secretName: string;
719
765
  /** The request header carrying the signature. Case-insensitive. Up to 256 characters. */
720
766
  header: string;
721
767
  /** Default 'sha256'. */
@@ -744,55 +790,100 @@ type TicketSignatureCondition = {
744
790
  /** Removed from the start of the stored secret before decoding. Up to 64 characters. */
745
791
  secret_prefix?: string;
746
792
  };
747
- /** What a consumption request must look like before the ticket's actions run. Evaluated in the order the keys are listed here; the first failure is the reported one. */
793
+ /**
794
+ * What a consumption request must look like before the ticket's actions run. The parts are
795
+ * checked in the order listed here and the first part that fails is the reported one. An absent
796
+ * or empty part checks nothing.
797
+ */
748
798
  type TicketCondition = {
749
- /** Answer HTTP 200 even when the consumption fails. For webhooks that retry on errors. */
799
+ /** Answer HTTP 200 even when the consumption fails. For webhooks that retry on errors. It only changes the status: a failing request still fails. */
750
800
  return200?: boolean;
751
801
  /** Absent = both allowed. */
752
802
  method?: 'GET' | 'POST';
753
803
  /** Verified first, over the raw request body. See TicketSignatureCondition. */
754
804
  signature?: TicketSignatureCondition;
805
+ /**
806
+ * The caller's IP address. Fails only when none of the listed values passes ('!=': when it
807
+ * is one of them). A value that is empty ("" or []), null or missing checks nothing, and
808
+ * registration drops it.
809
+ */
755
810
  ip?: {
756
811
  operator: TicketConditionOperator;
757
812
  value: string | string[];
758
813
  };
814
+ /** The User-Agent header, decided like `ip`. */
759
815
  user_agent?: {
760
816
  operator: TicketConditionOperator;
761
817
  value: string | string[];
762
818
  };
819
+ /** Rows against the request headers. See TicketConditionRow. Every row compares with a value: null, or no `value`, is refused. */
763
820
  headers?: TicketConditionRow[];
764
- /** Rows against the POST body. On a GET the body root is {}. */
821
+ /** Rows against the request body. Refused when `method` is 'GET': a GET request has no body. */
765
822
  data?: TicketConditionRow[];
766
- /** Rows against the GET query string. On a POST the query root is {}. */
823
+ /** Rows against the query string, read on GET and on POST. */
767
824
  params?: TicketConditionRow[];
768
- /** Rows against the consumer's attributes (user_id, email, access_group, ...). Signed-in consumption only. */
825
+ /**
826
+ * Rows against the consumer's attributes (user_id, email, access_group, ...). Signed requests
827
+ * only: an app user of this project calling consumeTicket() with `auth: true`. A third-party
828
+ * webhook has no session, so a ticket using this always fails for webhooks (AUTH_REQUIRED).
829
+ * The actions read the same attributes as `${user[key]}`. Every row compares with a value:
830
+ * null, or no `value`, is refused.
831
+ */
769
832
  user?: TicketConditionRow[];
770
- /** Record ID the consumer must own or have been granted. Signed-in consumption only. */
833
+ /**
834
+ * Record ID the consumer must own or have been granted. Signed requests only, like `user`:
835
+ * a ticket using this always fails for webhooks. The actions read it as `${record_access}`.
836
+ */
771
837
  record_access?: string;
772
- request?: TicketRequestCondition;
773
838
  };
774
- /** The subset of a condition a `req` action can evaluate against its response. A response has no method, query string or status policy. */
775
- type TicketResponseCondition = Pick<TicketCondition, 'headers' | 'data' | 'user' | 'record_access' | 'request'>;
776
839
  /**
777
- * One step of a ticket's action chain. Actions run in order; each one's result is readable by
778
- * the next as "result[...]". `exe` is templated right before the action runs: a string that is
779
- * a whole path ("data[object][id]", "placeholder[NAME]") keeps the value's type, "${...}" inside
780
- * text becomes a string, bare words are literal. When an action fails its `err` chain runs
781
- * (with "error[code]", "error[message]", ...) and the consumption stops. Nothing is rolled back.
840
+ * What a `req` action checks on the response before its nested actions run: `headers` and
841
+ * `data` rows work as in the ticket's condition (captures and `setValueWhenMatch` included).
842
+ * `headers` rows read the response headers and `data` row keys are paths into the parsed
843
+ * response body. `user` and `record_access` still check the consumer, so they only work for
844
+ * signed requests. A response that is not 2xx fails before this is checked.
845
+ */
846
+ type TicketResponseCondition = Pick<TicketCondition, 'headers' | 'data' | 'user' | 'record_access'>;
847
+ /**
848
+ * One step of a ticket's action chain. Actions run in order. When an action fails its `err`
849
+ * chain runs and the consumption stops. Nothing is rolled back.
850
+ *
851
+ * `exe` values are templated right before the action runs. Every reference is written inside
852
+ * `${ }`, and text outside `${ }` is always literal, whatever it looks like: "order[id]" is just
853
+ * that text. A value that is exactly one `${...}` keeps the type of what it reads; inside longer
854
+ * text it becomes text (JSON for anything but a string). `$${...}` writes a literal `${...}`.
855
+ * Object keys, condition rows and `setValueWhenMatch` are never templated.
856
+ *
857
+ * | Reference | Reads |
858
+ * |---|---|
859
+ * | `${data}`, `${data[key]}` | The incoming request body (a text body too), or one key of it: `${data[id]}` is the body's `id`, `${data[order][id]}` its `order.id`. Always the incoming body, also in nested actions. |
860
+ * | `${params}`, `${params[key]}` | The incoming query string, or one key of it. |
861
+ * | `${headers[name]}` | An incoming header, name case-insensitive. Authorization and Cookie read "<redacted>". |
862
+ * | `${placeholder[NAME]}` | A value a condition row captured with `placeholder`. |
863
+ * | `${user}`, `${user[key]}` | The signed-in user's attributes. Signed requests only. |
864
+ * | `${ip}`, `${user_agent}`, `${method}` | The caller's IP address, User-Agent and HTTP method. |
865
+ * | `${record_access}` | The record ID the condition's `record_access` names. Signed requests only. |
866
+ * | `${response}`, `${response[key]}` | The parsed body of the enclosing req action's response. Only in that req's nested `actions` and their `err` chains. |
867
+ * | `${result}`, `${result[key]}` | The result of the previous action in the same chain. A nested chain and an `err` chain start without one. |
868
+ * | `${error}`, `${error[key]}` | In an `err` chain, the failure: `code`, `message`, `detail`, `action` (the act) and `path`. |
869
+ * | `${ticket}`, `${ticket[key]}` | This consumption: `id`, `service`, `owner`, `consume_id` and `timestamp`. |
870
+ * | `${CLIENT_SECRET}` | Reserved. See `secretName` on the req action. |
871
+ *
872
+ * Registration refuses anything else inside `${ }` (an unknown root such as `${id}`, keys under
873
+ * a root that takes none such as `${ip[x]}`, `${placeholder}` or `${headers}` without a key,
874
+ * broken brackets) with a message listing these forms, and a reference written where it can
875
+ * never resolve (`${response}` outside a req's nested actions, `${error}` outside an `err`
876
+ * chain, `${record_access}` when the condition names no record). When the action runs, a
877
+ * reference that does not resolve fails it before it does anything: PATH_NOT_FOUND,
878
+ * PLACEHOLDER_MISSING for a placeholder that was never captured, or AUTH_REQUIRED for `${user}`
879
+ * on a request that is not signed in. Its `err` chain runs and the consumption stops.
782
880
  */
783
881
  type TicketAction = {
784
- /** Update a Skapi service. Internal: registration refuses it unless the caller is a Skapi super master. */
785
- act: 'srvc';
786
- exe: {
787
- [key: string]: any;
788
- };
789
- err?: TicketAction[];
790
- } | {
791
882
  /** Set the access group of a user. */
792
883
  act: 'acsg';
793
884
  exe: {
794
- /** 1 ~ 99, or "admin". */
795
- group: number | 'admin';
885
+ /** 1 ~ 99, or "admin", or a reference that gives one when the action runs, such as "${placeholder[GROUP]}". */
886
+ group: number | 'admin' | `${string}\${${string}}${string}`;
796
887
  /** Blank = the consumer (signed-in consumption only). The project owner cannot be a target. */
797
888
  user_id?: string;
798
889
  };
@@ -836,10 +927,57 @@ type TicketAction = {
836
927
  /** HTTP request with its own response condition and nested chain. Result: the parsed response body. */
837
928
  act: 'req';
838
929
  exe: {
839
- /** http:// or https:// with a hostname. No IP literal, no userinfo, never under the api domain. Redirects are not followed. */
930
+ /**
931
+ * http:// or https:// with a hostname, such as "https://api.example.com/orders/${data[id]}".
932
+ * The scheme is always written out, so a URL that is one whole reference is refused.
933
+ * No IP literal, no userinfo, never under the api domain. Redirects are not followed.
934
+ * A value put into the URL with `${...}` is percent-encoded, so it cannot add path
935
+ * segments or query parameters ("." and ".." are refused). `${CLIENT_SECRET}` is
936
+ * never allowed here. Sent as a browser sends it: a hostname outside ASCII is
937
+ * IDNA-encoded, a tab or line break is removed, and in the path and query a space,
938
+ * any other control character and every character outside ASCII is percent-encoded.
939
+ */
840
940
  url: string;
841
941
  /** Default GET. */
842
942
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
943
+ /**
944
+ * The name of a Secret Key of the project, never the secret itself. Must exist at
945
+ * registration. Never templated.
946
+ *
947
+ * - `${CLIENT_SECRET}` in this action's `headers`, `data` and `params` values is
948
+ * replaced by the key's value, server side, when the call is sent. It is refused
949
+ * anywhere else: in the url, in other actions, in a req without `secretName`, in
950
+ * header names or object keys, and in condition rows. Text in the incoming request
951
+ * that reads "${CLIENT_SECRET}" is never expanded.
952
+ * - The url's scheme and host must be written out: no "${...}" before the path.
953
+ * - When the key has Destinations, the call must go to one of them, or it fails with
954
+ * REQUEST_FAILED, `detail: { reason: 'refused_address' }`. A req without
955
+ * `secretName` is not limited.
956
+ * - The value is never logged. A copy in the answer or an error, as sent or escaped
957
+ * up to three times over (percent, backslash or HTML escapes; each level in one
958
+ * notation), reads "${CLIENT_SECRET}" instead. An answer of any size is read whole
959
+ * and still parses as JSON; reading a very long answer can run out of the
960
+ * ticket's time, which fails with REQUEST_FAILED, `detail: { reason: 'timeout' }`.
961
+ * A key that no longer exists fails with
962
+ * REQUEST_FAILED, `detail: { reason: 'secret_missing', secretName }`.
963
+ */
964
+ secretName?: string;
965
+ /**
966
+ * Request headers, values templated. Two headers are the engine's own, and
967
+ * registration refuses either one, in any case and with any surrounding spaces:
968
+ * Host (always the url's host) and X-Skapi-Ticket (every call carries
969
+ * `X-Skapi-Ticket: <service id>/<ticket id>`).
970
+ *
971
+ * A name must be ASCII, with no ":", line break or NUL. A value cannot hold a line
972
+ * break, NUL or a character outside Latin-1 (send such values in the body).
973
+ * - Registration refuses a name that breaks this rule, and a value whose text outside
974
+ * its `${...}` references breaks it, so a header the call could never send is not
975
+ * saved.
976
+ * - A value that breaks it only once templated fails the call with REQUEST_FAILED,
977
+ * `detail: { reason: 'invalid_header', header }`, before anything is sent.
978
+ *
979
+ * Each message names the header, never its value.
980
+ */
843
981
  headers?: {
844
982
  [name: string]: string;
845
983
  };
@@ -849,11 +987,15 @@ type TicketAction = {
849
987
  params?: {
850
988
  [key: string]: any;
851
989
  };
852
- /** Legacy. Rows matched against the response body like `condition.data`. */
990
+ /** Legacy. Registration moves these rows to the end of `condition.data`. */
853
991
  match?: TicketConditionRow[];
854
- /** Evaluated against the response. Captures land in the shared placeholder pool. */
992
+ /** Checked against the response. Captures land in the shared placeholder pool. See TicketResponseCondition. */
855
993
  condition?: TicketResponseCondition;
856
- /** Nested chain. Its paths read the response body. */
994
+ /**
995
+ * Nested chain, run when the response passes `condition`. It reads the response body
996
+ * as `${response}` and `${response[key]}`, while `${data}` is still the incoming
997
+ * request body. Any action can nest, including another req with its own `secretName`.
998
+ */
857
999
  actions?: TicketAction[];
858
1000
  };
859
1001
  err?: TicketAction[];
@@ -874,6 +1016,14 @@ type Ticket = {
874
1016
  updated?: number;
875
1017
  condition?: TicketCondition;
876
1018
  actions?: TicketAction[];
1019
+ /**
1020
+ * true on a ticket saved before this release (the dashboard marks it "previous rules"). It
1021
+ * keeps running by the rules it was saved with until it is registered again, which applies
1022
+ * the current rules. `condition` and `actions` are shown converted to the current format.
1023
+ * Returned to the project owner only. See
1024
+ * https://docs.skapi.com/deprecated/deprecated.html#tickets-saved-before-this-release
1025
+ */
1026
+ legacy?: boolean;
877
1027
  };
878
1028
  type TicketErrorCode = 'INVALID_SERVICE' | 'SERVICE_DISABLED' | 'TICKET_NOT_FOUND' | 'TICKET_EXPIRED' | 'TICKET_EXHAUSTED' | 'USER_LIMIT_REACHED' | 'ISSUER_CANNOT_CONSUME' | 'AUTH_REQUIRED' | 'METHOD_NOT_ALLOWED' | 'CONDITION_FAILED' | 'PATH_NOT_FOUND' | 'PLACEHOLDER_MISSING' | 'REQUEST_FAILED' | 'TIMEOUT' | 'ACTION_FAILED' | 'ACTION_FORBIDDEN' | 'INTERNAL_ERROR';
879
1029
  /**
@@ -891,7 +1041,18 @@ type TicketError = {
891
1041
  act: TicketAction['act'];
892
1042
  path: string;
893
1043
  };
894
- /** Code specific, JSON safe. For example { expired_at } on TICKET_EXPIRED, { field, keys } on CONDITION_FAILED, { status, body } on REQUEST_FAILED. */
1044
+ /**
1045
+ * Code specific, JSON safe. For example { expired_at } on TICKET_EXPIRED, and { field, keys }
1046
+ * on CONDITION_FAILED, where `field` is the part that failed ("data", "headers", ...) and
1047
+ * `keys` the row keys that did not pass. `field` is "loop" when the request was sent by a
1048
+ * ticket's own req action (a ticket cannot consume a ticket).
1049
+ *
1050
+ * REQUEST_FAILED carries { status, body } for an answer of 300 or above (`body` is the parsed
1051
+ * answer, or the first 4 KB of its text when longer, compact JSON for a JSON answer, with a
1052
+ * Secret Key the req sent replaced by the text "${CLIENT_SECRET}"), { reason } with reason
1053
+ * "timeout", "refused_address" or "connection", { reason: "invalid_header", header } for a
1054
+ * header that cannot be sent, or { reason: "secret_missing", secretName }.
1055
+ */
895
1056
  detail?: {
896
1057
  [key: string]: any;
897
1058
  };
@@ -933,7 +1094,6 @@ type Types_TicketConditionOperator = TicketConditionOperator;
933
1094
  type Types_TicketConditionRow = TicketConditionRow;
934
1095
  type Types_TicketError = TicketError;
935
1096
  type Types_TicketErrorCode = TicketErrorCode;
936
- type Types_TicketRequestCondition = TicketRequestCondition;
937
1097
  type Types_TicketResponseCondition = TicketResponseCondition;
938
1098
  type Types_TicketSignatureCondition = TicketSignatureCondition;
939
1099
  type Types_UniqueId = UniqueId;
@@ -942,7 +1102,7 @@ type Types_UserProfile = UserProfile;
942
1102
  type Types_UserPublic = UserPublic;
943
1103
  type Types_WebSocketMessage = WebSocketMessage;
944
1104
  declare namespace Types {
945
- export type { Types_BinaryFile as BinaryFile, Types_Condition as Condition, Types_Connection as Connection, Types_ConnectionInfo as ConnectionInfo, Types_DatabaseResponse as DatabaseResponse, Types_DelRecordQuery as DelRecordQuery, Types_EncryptionOptions as EncryptionOptions, Types_FetchOptions as FetchOptions, Types_FileInfo as FileInfo, Types_Form as Form, Types_GetRecordQuery as GetRecordQuery, Types_Index as Index, Types_Newsletter as Newsletter, Types_NewsletterGroup as NewsletterGroup, Types_PostRecordConfig as PostRecordConfig, Types_ProgressCallback as ProgressCallback, Types_RTCConnector as RTCConnector, Types_RTCConnectorParams as RTCConnectorParams, Types_RTCEvent as RTCEvent, Types_RTCReceiverParams as RTCReceiverParams, Types_RTCResolved as RTCResolved, Types_RealtimeCallback as RealtimeCallback, Types_RecordData as RecordData, Types_RecordEncryptionInfo as RecordEncryptionInfo, Types_RequestHistory as RequestHistory, Types_Subscription as Subscription, Types_Table as Table, Types_Tag as Tag, Types_Ticket as Ticket, Types_TicketAction as TicketAction, Types_TicketCondition as TicketCondition, Types_TicketConditionOperator as TicketConditionOperator, Types_TicketConditionRow as TicketConditionRow, Types_TicketError as TicketError, Types_TicketErrorCode as TicketErrorCode, Types_TicketRequestCondition as TicketRequestCondition, Types_TicketResponseCondition as TicketResponseCondition, Types_TicketSignatureCondition as TicketSignatureCondition, Types_UniqueId as UniqueId, Types_UserAttributes as UserAttributes, Types_UserProfile as UserProfile, Types_UserPublic as UserPublic, Types_WebSocketMessage as WebSocketMessage };
1105
+ export type { Types_BinaryFile as BinaryFile, Types_Condition as Condition, Types_Connection as Connection, Types_ConnectionInfo as ConnectionInfo, Types_DatabaseResponse as DatabaseResponse, Types_DelRecordQuery as DelRecordQuery, Types_EncryptionOptions as EncryptionOptions, Types_FetchOptions as FetchOptions, Types_FileInfo as FileInfo, Types_Form as Form, Types_GetRecordQuery as GetRecordQuery, Types_Index as Index, Types_Newsletter as Newsletter, Types_NewsletterGroup as NewsletterGroup, Types_PostRecordConfig as PostRecordConfig, Types_ProgressCallback as ProgressCallback, Types_RTCConnector as RTCConnector, Types_RTCConnectorParams as RTCConnectorParams, Types_RTCEvent as RTCEvent, Types_RTCReceiverParams as RTCReceiverParams, Types_RTCResolved as RTCResolved, Types_RealtimeCallback as RealtimeCallback, Types_RecordData as RecordData, Types_RecordEncryptionInfo as RecordEncryptionInfo, Types_RequestHistory as RequestHistory, Types_Subscription as Subscription, Types_Table as Table, Types_Tag as Tag, Types_Ticket as Ticket, Types_TicketAction as TicketAction, Types_TicketCondition as TicketCondition, Types_TicketConditionOperator as TicketConditionOperator, Types_TicketConditionRow as TicketConditionRow, Types_TicketError as TicketError, Types_TicketErrorCode as TicketErrorCode, Types_TicketResponseCondition as TicketResponseCondition, Types_TicketSignatureCondition as TicketSignatureCondition, Types_UniqueId as UniqueId, Types_UserAttributes as UserAttributes, Types_UserProfile as UserProfile, Types_UserPublic as UserPublic, Types_WebSocketMessage as WebSocketMessage };
946
1106
  }
947
1107
 
948
1108
  declare function terminatePendingRequests(): void;
@@ -1106,12 +1266,16 @@ declare class Skapi {
1106
1266
  };
1107
1267
  private __connection;
1108
1268
  private __authConnection;
1269
+ private __projectIdInput;
1109
1270
  private __network_logs;
1110
1271
  private __endpoint_version;
1111
1272
  private __public_identifier;
1112
1273
  private bearerToken;
1113
1274
  private _alert;
1114
1275
  constructor(service: string, owner?: string | Options, options?: Options | any, __etc?: any);
1276
+ private _resolveProject;
1277
+ private _startAfterProjectIdInput;
1278
+ private _start;
1115
1279
  /**
1116
1280
  * Returns current connection metadata such as service name, client IP, user agent, locale, and SDK version.
1117
1281
  * @param params Request parameters. When `refresh` is true, the cached connection metadata is re-fetched before returning; otherwise the cached connection is returned.
@@ -2304,10 +2468,10 @@ declare class Skapi {
2304
2468
  VAPIDPublicKey: string;
2305
2469
  }>;
2306
2470
  /**
2307
- * Sends push notifications to one or more users.
2308
- * @param params Payload for the request.
2309
- * @param user_ids Parameter for this operation.
2310
- * @returns A promise that resolves to Promise<"SUCCESS: Notification sent.">.
2471
+ * Sends push notifications to one or more users. Admins only.
2472
+ * @param params Title and body of the push. Together at most 3072 bytes.
2473
+ * @param user_ids Users to push to, up to 1000. Every device each of them registered with subscribeNotification() gets it. Without it, every registered device of the project gets it.
2474
+ * @returns A promise that resolves to Promise<"SUCCESS: Notification sent.">. The pushes are sent right after it resolves.
2311
2475
  */
2312
2476
  pushNotification(params: {
2313
2477
  title: string;
@@ -2344,7 +2508,7 @@ declare class Skapi {
2344
2508
  * An admin in access groups 90 ~ 98 gets the subscriber list too, but reads it through a privacy layer:
2345
2509
  * "subscribed_email" is masked ("j**@**.com") and the mask is lossy, so two different subscribers can read the same;
2346
2510
  * "subscriber_token" comes with each masked row as an opaque, stable, per address key, and it is the only value that tells such rows apart, so key lists and selections on it, never on the masked address;
2347
- * the token is not a readable address and is scoped to this service, owner and group, so it cannot be matched against a token from another group or project;
2511
+ * the token is not a readable address and is scoped to this service, owner and group, so it cannot be matched against a token from another group or project, and it is a key for working with a listing, not an id to store: the platform can reissue tokens;
2348
2512
  * "startKey" is sealed by the server and has to be handed back verbatim, which fetchMore already does;
2349
2513
  * and "email" is refused with "No access.".
2350
2514
  * @param params Request parameters.
@@ -2744,7 +2908,9 @@ declare class Skapi {
2744
2908
  }, fetchOptions?: FetchOptions): Promise<DatabaseResponse<Subscription>>;
2745
2909
  /**
2746
2910
  * Subscribes to another user with optional feed/notification/email preferences.
2747
- * @param params Request parameters.
2911
+ * Calling it again on the same user changes only the options given and keeps the rest,
2912
+ * so `get_notified` can be turned on or off without touching `get_feed`.
2913
+ * @param params Request parameters. `get_feed`: the user's records posted with `upload_to_feed` appear in getFeed(). `get_notified`: push notifications for the user's records posted with `notify_subscribers`, and for new references to their records with `notify_referencing_records` (the device also needs subscribeNotification()). A new subscription starts with every option off.
2748
2914
  * @returns A promise that resolves to Promise<Subscription>.
2749
2915
  */
2750
2916
  subscribe(params: {
@@ -2808,4 +2974,4 @@ declare class SkapiError extends Error {
2808
2974
  });
2809
2975
  }
2810
2976
 
2811
- export { type BinaryFile, type Condition, type Connection, type ConnectionInfo, type DatabaseResponse, type DelRecordQuery, type FetchOptions, type FileInfo, type Form, type GetRecordQuery, type Index, type Newsletter, type NewsletterGroup, type PostRecordConfig, type ProgressCallback, type RTCConnector, type RTCConnectorParams, type RTCEvent, type RTCReceiverParams, type RTCResolved, type RealtimeCallback, type RecordData, Skapi, SkapiError, type Subscription, type Table, type Tag, type Ticket, type TicketAction, type TicketCondition, type TicketConditionOperator, type TicketConditionRow, type TicketError, type TicketErrorCode, type TicketRequestCondition, type TicketResponseCondition, type TicketSignatureCondition, Types, type UniqueId, type UserAttributes, type UserProfile, type UserPublic, type WebSocketMessage };
2977
+ export { type BinaryFile, type Condition, type Connection, type ConnectionInfo, type DatabaseResponse, type DelRecordQuery, type FetchOptions, type FileInfo, type Form, type GetRecordQuery, type Index, type Newsletter, type NewsletterGroup, type PostRecordConfig, type ProgressCallback, type RTCConnector, type RTCConnectorParams, type RTCEvent, type RTCReceiverParams, type RTCResolved, type RealtimeCallback, type RecordData, Skapi, SkapiError, type Subscription, type Table, type Tag, type Ticket, type TicketAction, type TicketCondition, type TicketConditionOperator, type TicketConditionRow, type TicketError, type TicketErrorCode, type TicketResponseCondition, type TicketSignatureCondition, Types, type UniqueId, type UserAttributes, type UserProfile, type UserPublic, type WebSocketMessage };