skapi-js 2.2.5 → 2.2.6-beta.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.mts CHANGED
@@ -296,6 +296,13 @@ type Newsletter = {
296
296
  * A number for the 0 ~ 99 groups, the group name for a named newsletter group.
297
297
  */
298
298
  group: number | string;
299
+ /**
300
+ * true: mailed to the group's dry address, so it is stored and was sent to nobody. The
301
+ * Newsletters page's Send button, or a ticket's Send newsletter action, sends it later.
302
+ */
303
+ dry?: boolean;
304
+ /** When the Send button or a ticket's Send newsletter action sent it, in ms. Absent on a newsletter that went out by e-mail. */
305
+ sent?: number;
299
306
  };
300
307
  type NewsletterGroup = {
301
308
  /** Name of the newsletter group. */
@@ -864,43 +871,55 @@ type TicketResponseCondition = Pick<TicketCondition, 'headers' | 'data' | 'user'
864
871
  * | `${user}`, `${user[key]}` | The signed-in user's attributes. Signed requests only. |
865
872
  * | `${ip}`, `${user_agent}`, `${method}` | The caller's IP address, User-Agent and HTTP method. |
866
873
  * | `${record_access}` | The record ID the condition's `record_access` names. Signed requests only. |
867
- * | `${response}`, `${response[key]}` | The parsed body of the enclosing req action's response. Only in that req's nested `actions` and their `err` chains. |
868
- * | `${result}`, `${result[key]}` | The result of the previous action in the same chain. A nested chain and an `err` chain start without one. |
874
+ * | `${response}`, `${response[key]}` | The answer of the enclosing action, in its Then chain (`actions`) and the `err` chains inside it: the record a pstr posted, the parsed body of a req's response, the SUCCESS text of acsg and acsr. |
869
875
  * | `${error}`, `${error[key]}` | In an `err` chain, the failure: `code`, `message`, `detail`, `action` (the act) and `path`. |
870
- * | `${ticket}`, `${ticket[key]}` | This consumption: `id`, `service`, `owner`, `consume_id` and `timestamp`. |
876
+ * | `${ticket}`, `${ticket[key]}` | This consumption: `id`, `service`, `owner`, `consume_id`, `timestamp` and `hash`. |
871
877
  * | `${CLIENT_SECRET}` | Reserved. See `secretName` on the req action. |
872
878
  *
873
879
  * Registration refuses anything else inside `${ }` (an unknown root such as `${id}`, keys under
874
880
  * a root that takes none such as `${ip[x]}`, `${placeholder}` or `${headers}` without a key,
875
- * broken brackets) with a message listing these forms, and a reference written where it can
876
- * never resolve (`${response}` outside a req's nested actions, `${error}` outside an `err`
881
+ * broken brackets) with a message listing these forms, `${result}` (gone: an answer is read as
882
+ * `${response}` in the action's Then chain, or captured there by a Condition action), and a reference written
883
+ * where it can never resolve (`${response}` outside a Then chain, `${error}` outside an `err`
877
884
  * chain, `${record_access}` when the condition names no record). When the action runs, a
878
885
  * reference that does not resolve fails it before it does anything: PATH_NOT_FOUND,
879
886
  * PLACEHOLDER_MISSING for a placeholder that was never captured, or AUTH_REQUIRED for `${user}`
880
887
  * on a request that is not signed in. Its `err` chain runs and the consumption stops.
888
+ *
889
+ * Every action but resp and cond answers something (the record, the response body, a SUCCESS
890
+ * text) and may carry a Then chain (`actions`, reading the answer as `${response}`). A Condition
891
+ * action in that chain checks the answer: its `response` rows read it whole (key "") or by key,
892
+ * whatever its shape. `retry: true` on acsg, acsr, pstr, req, mail and nlsd tries a failure again,
893
+ * up to 3 more times, 1, 2 and 4 seconds apart, while the time budget holds them; never for a
894
+ * failure inside Then.
881
895
  */
882
896
  type TicketAction = {
883
- /** Set the access group of a user. */
897
+ /** Set the access group of a user. Answers the SUCCESS text the grant returns. */
884
898
  act: 'acsg';
885
899
  exe: {
886
900
  /** 1 ~ 99, or "admin", or a reference that gives one when the action runs, such as "${placeholder[GROUP]}". */
887
901
  group: number | 'admin' | `${string}\${${string}}${string}`;
888
902
  /** Blank = the consumer (signed-in consumption only). The project owner cannot be a target. */
889
903
  user_id?: string;
904
+ /** The Then chain, reading the answer as `${response}`. */
905
+ actions?: TicketAction[];
890
906
  };
891
907
  err?: TicketAction[];
908
+ retry?: boolean;
892
909
  } | {
893
- /** Grant private access to a record. */
910
+ /** Grant private access to a record. Answers the SUCCESS text the grant returns. */
894
911
  act: 'acsr';
895
912
  exe: {
896
913
  /** A record ID, not a unique ID. */
897
914
  record_id: string;
898
915
  /** Blank = the consumer. */
899
916
  user_id?: string | string[];
917
+ actions?: TicketAction[];
900
918
  };
901
919
  err?: TicketAction[];
920
+ retry?: boolean;
902
921
  } | {
903
- /** Post a record. Everything but `user_id` is the payload postRecord() sends, so the same rules apply. A `unique_id` makes a retried webhook update the same record instead of adding one. */
922
+ /** Post a record. Everything but `user_id` is the payload postRecord() sends, so the same rules apply. A `unique_id` makes a retried webhook update the same record instead of adding one. Answers the record (RecordData). */
904
923
  act: 'pstr';
905
924
  exe: {
906
925
  table: string | {
@@ -922,10 +941,13 @@ type TicketAction = {
922
941
  source?: PostRecordConfig['source'];
923
942
  /** Post as this user instead of the project owner. */
924
943
  user_id?: string;
944
+ /** The Then chain, reading the record as `${response}` (`${response[record_id]}`). */
945
+ actions?: TicketAction[];
925
946
  };
926
947
  err?: TicketAction[];
948
+ retry?: boolean;
927
949
  } | {
928
- /** HTTP request with its own response condition and nested chain. Result: the parsed response body. */
950
+ /** HTTP request with its own response condition and nested chain. Answers the parsed response body. */
929
951
  act: 'req';
930
952
  exe: {
931
953
  /**
@@ -990,7 +1012,7 @@ type TicketAction = {
990
1012
  };
991
1013
  /** Legacy. Registration moves these rows to the end of `condition.data`. */
992
1014
  match?: TicketConditionRow[];
993
- /** Checked against the response. Captures land in the shared placeholder pool. See TicketResponseCondition. */
1015
+ /** Skapi's own billing rows only. A response check is a Condition action in `actions`, whose `response` rows read the answer. */
994
1016
  condition?: TicketResponseCondition;
995
1017
  /**
996
1018
  * Nested chain, run when the response passes `condition`. It reads the response body
@@ -1000,6 +1022,112 @@ type TicketAction = {
1000
1022
  actions?: TicketAction[];
1001
1023
  };
1002
1024
  err?: TicketAction[];
1025
+ retry?: boolean;
1026
+ } | {
1027
+ /**
1028
+ * Send e-mail: one e-mail from a CUSTOM template of the project (the Custom tab of the
1029
+ * Automated Emails page) to one address, from the project's alias. Counts as one e-mail
1030
+ * send (the plan's monthly sends, the Free owner cap and the complaint shutoff apply; a
1031
+ * refusal is QUOTA_EXCEEDED). Answers "SUCCESS: E-mail sent to <address>."
1032
+ */
1033
+ act: 'mail';
1034
+ exe: {
1035
+ /** The template's ID, as the Custom tab and the upload reply show it. Literal; it must be stored when the ticket is registered. */
1036
+ template: string;
1037
+ /** The recipient: one address, or a reference that gives one, such as "${user[email]}" or "${data[email]}". */
1038
+ to: string;
1039
+ /**
1040
+ * Values for the placeholders the template carries, by name: { "order": "${data[order][id]}" } fills
1041
+ * ${order}. Templated. "service_name" and "email" (the recipient) are filled by default and may be
1042
+ * overwritten here. Up to 30.
1043
+ */
1044
+ placeholders?: {
1045
+ [name: string]: string | number | boolean;
1046
+ };
1047
+ actions?: TicketAction[];
1048
+ };
1049
+ err?: TicketAction[];
1050
+ retry?: boolean;
1051
+ } | {
1052
+ /**
1053
+ * Send newsletter: a stored newsletter of a group, dry or already sent, to every subscriber of the
1054
+ * group, the way an e-mailed newsletter goes out (one e-mail send per subscriber, same gates).
1055
+ * Answers "SUCCESS: Newsletter sent to the subscribers of <group>."
1056
+ */
1057
+ act: 'nlsd';
1058
+ exe: {
1059
+ /** "public", "authorized", a number from 2 to 99, or a named group. Literal. */
1060
+ group: 'public' | 'authorized' | number | string;
1061
+ /** The newsletter's message_id (getNewsletters()). Literal; it must be stored under the group when the ticket is registered. */
1062
+ newsletter: string;
1063
+ actions?: TicketAction[];
1064
+ };
1065
+ err?: TicketAction[];
1066
+ retry?: boolean;
1067
+ } | {
1068
+ /**
1069
+ * Respond: answers the consumer now, then stops or goes on. One per run: a second Respond
1070
+ * on a path that already answered is refused at registration, and ALREADY_RESPONDED when
1071
+ * it runs. consumeTicket() resolves with the body (or the receipt), whatever the status.
1072
+ */
1073
+ act: 'resp';
1074
+ exe: {
1075
+ /** The HTTP status, 100 to 599, or a reference. Default 200. An error status is still an answer, not a failure. */
1076
+ status?: number | string;
1077
+ /** Any JSON, templated; absent: the receipt { tkid, hash }. A `stage` key is refused (that is how an error is told apart). */
1078
+ body?: any;
1079
+ /**
1080
+ * What happens after the answer. Absent or "stop": the rest of the chain does not run.
1081
+ * "0m": goes on at once, in the background. "<n>m" | "<n>h" | "<n>d" (n >= 1): goes on
1082
+ * after that delay, to the minute. A number: a time in ms since the epoch, to the second
1083
+ * (a literal in the past is refused at registration; a templated one goes on at once).
1084
+ * A run that goes on counts toward the plan's queued ticket runs for the month; Free and
1085
+ * Standard stop at theirs (QUOTA_EXCEEDED), Premium is billed past it.
1086
+ */
1087
+ resume?: 'stop' | '0m' | `${number}m` | `${number}h` | `${number}d` | number | string;
1088
+ };
1089
+ err?: TicketAction[];
1090
+ } | {
1091
+ /**
1092
+ * Condition: rows inside a chain, under the rules of the ticket's own condition. A part
1093
+ * that fails fails the chain here with CONDITION_FAILED (the action's `err` chain runs).
1094
+ * Answers nothing. `response` rows only inside a Then chain, `error` rows only inside an
1095
+ * `err` chain, `placeholder` rows name placeholders (and may compare with null).
1096
+ */
1097
+ act: 'cond';
1098
+ exe: {
1099
+ data?: TicketConditionRow[];
1100
+ params?: TicketConditionRow[];
1101
+ headers?: TicketCondition['headers'];
1102
+ ip?: TicketCondition['ip'];
1103
+ user_agent?: TicketCondition['user_agent'];
1104
+ user?: TicketCondition['user'];
1105
+ record_access?: string;
1106
+ placeholder?: {
1107
+ key: string;
1108
+ operator: TicketConditionOperator;
1109
+ value: any;
1110
+ }[];
1111
+ /** Rows on the enclosing action's answer, inside a Then chain only: a key reads a field, "" the whole answer as text. */
1112
+ response?: TicketConditionRow[];
1113
+ /** Rows on the failure, inside an err chain only: code, message, detail, action, path, or "" for the whole error as text. */
1114
+ error?: TicketConditionRow[];
1115
+ };
1116
+ err?: TicketAction[];
1117
+ };
1118
+ /** What a consumption answers when no Respond action composes the answer. */
1119
+ type TicketReceipt = {
1120
+ ticket_id: string;
1121
+ /** Id of this consumption: base62 of the timestamp in milliseconds, followed by 4 random characters. */
1122
+ consume_id: string;
1123
+ /** The consumer. The user id on the signed-in endpoint, else "<ip>(<user agent>)". */
1124
+ user_id: string;
1125
+ /** Always false here: dry runs go through the check URL, which consumeTicket() never calls. */
1126
+ is_test: boolean;
1127
+ /** When the consumption happened, in milliseconds. Decoded from consume_id. */
1128
+ timestamp: number;
1129
+ /** Proof string of the consumption. */
1130
+ hash: string;
1003
1131
  };
1004
1132
  /** An issued ticket as getTickets() and registerTicket() return it. */
1005
1133
  type Ticket = {
@@ -1026,7 +1154,7 @@ type Ticket = {
1026
1154
  */
1027
1155
  legacy?: boolean;
1028
1156
  };
1029
- 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';
1157
+ 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' | 'QUOTA_EXCEEDED' | 'ALREADY_RESPONDED' | 'INTERNAL_ERROR';
1030
1158
  /**
1031
1159
  * The body a consume endpoint answers with when the consumption fails, and the `cause` of the
1032
1160
  * SkapiError consumeTicket() rejects with. A success body never has `stage`; an error body
@@ -1095,6 +1223,7 @@ type Types_TicketConditionOperator = TicketConditionOperator;
1095
1223
  type Types_TicketConditionRow = TicketConditionRow;
1096
1224
  type Types_TicketError = TicketError;
1097
1225
  type Types_TicketErrorCode = TicketErrorCode;
1226
+ type Types_TicketReceipt = TicketReceipt;
1098
1227
  type Types_TicketResponseCondition = TicketResponseCondition;
1099
1228
  type Types_TicketSignatureCondition = TicketSignatureCondition;
1100
1229
  type Types_UniqueId = UniqueId;
@@ -1103,7 +1232,7 @@ type Types_UserProfile = UserProfile;
1103
1232
  type Types_UserPublic = UserPublic;
1104
1233
  type Types_WebSocketMessage = WebSocketMessage;
1105
1234
  declare namespace Types {
1106
- 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 };
1235
+ 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_TicketReceipt as TicketReceipt, 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 };
1107
1236
  }
1108
1237
 
1109
1238
  declare function terminatePendingRequests(): void;
@@ -1818,13 +1947,16 @@ declare class Skapi {
1818
1947
  * its actions run. An anonymous POST goes to `/tp/`, an anonymous GET to `/tg/` with `data`
1819
1948
  * as the query string, and a signed-in consumption (`auth: true`) to `/tpa/`, which is POST only.
1820
1949
  *
1950
+ * Resolves with the receipt (TicketReceipt: ticket_id, consume_id, user_id, is_test, timestamp, hash),
1951
+ * or with the body a Respond action of the ticket answered, as sent and whatever its status. `T` names that body.
1952
+ *
1821
1953
  * A failed consumption rejects with a SkapiError: `err.code` is the ticket error code and
1822
1954
  * `err.cause` the flat TicketError body (`err.cause.stage`, `err.cause.action`, `err.cause.detail`).
1823
1955
  * This holds when the ticket answers HTTP 200 as well (`return200`): the body is inspected, not the status.
1824
1956
  * @param params Request parameters.
1825
- * @returns A promise that resolves to Promise<{ ticket_id: string; consume_id: string; user_id: string; is_test: boolean; timestamp: number; hash: string; }>.
1957
+ * @returns A promise that resolves to Promise<T>, the receipt or the Respond body.
1826
1958
  */
1827
- consumeTicket(params: {
1959
+ consumeTicket<T = TicketReceipt>(params: {
1828
1960
  /** ID of the ticket to consume. */
1829
1961
  ticket_id: string;
1830
1962
  /** "GET" or "POST". */
@@ -1835,14 +1967,7 @@ declare class Skapi {
1835
1967
  data?: {
1836
1968
  [key: string]: any;
1837
1969
  };
1838
- }): Promise<{
1839
- ticket_id: string;
1840
- consume_id: string;
1841
- user_id: string;
1842
- is_test: boolean;
1843
- timestamp: number;
1844
- hash: string;
1845
- }>;
1970
+ }): Promise<T>;
1846
1971
  /**
1847
1972
  * Lists the tickets the signed-in user has consumed, with optional filters and pagination.
1848
1973
  * @param params Request parameters.
@@ -1861,9 +1986,29 @@ declare class Skapi {
1861
1986
  * @returns A promise that resolves to Promise<DatabaseResponse<any>>.
1862
1987
  */
1863
1988
  getTickets(params: {
1864
- /** Absent = every ticket. "<id>" = that ticket. "#<id>#" = the consumption log of that ticket (project owner only). */
1989
+ /** Absent = every ticket. "<id>" = that ticket. "#<id>#" = the consumption log of that ticket, "@<id>#<consume id>#" the action rows of one consumption (project owner only). */
1865
1990
  ticket_id?: string;
1991
+ /** A log listing only: rows from this time on, in milliseconds since the epoch. */
1992
+ from?: number;
1993
+ /** A log listing only: rows up to this time, in milliseconds since the epoch. */
1994
+ to?: number;
1866
1995
  }, fetchOptions?: FetchOptions): Promise<DatabaseResponse<any>>;
1996
+ /**
1997
+ * Deletes a ticket's log rows before a time, in the background over the next minutes. The ticket's
1998
+ * remaining count and its per-user limits are unchanged. Project owner only.
1999
+ * @param params Request parameters.
2000
+ * @returns A promise that resolves to Promise<{ message: string; ticket_id: string; before: number }>, `before` being the time applied (later than now is clipped to now).
2001
+ */
2002
+ clearTicketLog(params: {
2003
+ /** The ticket whose log rows go. */
2004
+ ticket_id: string;
2005
+ /** Rows before this time, in milliseconds since the epoch. Default: now. */
2006
+ before?: number;
2007
+ }): Promise<{
2008
+ message: string;
2009
+ ticket_id: string;
2010
+ before: number;
2011
+ }>;
1867
2012
  /**
1868
2013
  * Closes the active realtime WebSocket connection.
1869
2014
  * @returns A promise that resolves to Promise<void>.
@@ -3010,4 +3155,4 @@ declare class SkapiError extends Error {
3010
3155
  });
3011
3156
  }
3012
3157
 
3013
- 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 };
3158
+ 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 TicketReceipt, type TicketResponseCondition, type TicketSignatureCondition, Types, type UniqueId, type UserAttributes, type UserProfile, type UserPublic, type WebSocketMessage };
package/dist/skapi.d.ts CHANGED
@@ -296,6 +296,13 @@ type Newsletter = {
296
296
  * A number for the 0 ~ 99 groups, the group name for a named newsletter group.
297
297
  */
298
298
  group: number | string;
299
+ /**
300
+ * true: mailed to the group's dry address, so it is stored and was sent to nobody. The
301
+ * Newsletters page's Send button, or a ticket's Send newsletter action, sends it later.
302
+ */
303
+ dry?: boolean;
304
+ /** When the Send button or a ticket's Send newsletter action sent it, in ms. Absent on a newsletter that went out by e-mail. */
305
+ sent?: number;
299
306
  };
300
307
  type NewsletterGroup = {
301
308
  /** Name of the newsletter group. */
@@ -864,43 +871,55 @@ type TicketResponseCondition = Pick<TicketCondition, 'headers' | 'data' | 'user'
864
871
  * | `${user}`, `${user[key]}` | The signed-in user's attributes. Signed requests only. |
865
872
  * | `${ip}`, `${user_agent}`, `${method}` | The caller's IP address, User-Agent and HTTP method. |
866
873
  * | `${record_access}` | The record ID the condition's `record_access` names. Signed requests only. |
867
- * | `${response}`, `${response[key]}` | The parsed body of the enclosing req action's response. Only in that req's nested `actions` and their `err` chains. |
868
- * | `${result}`, `${result[key]}` | The result of the previous action in the same chain. A nested chain and an `err` chain start without one. |
874
+ * | `${response}`, `${response[key]}` | The answer of the enclosing action, in its Then chain (`actions`) and the `err` chains inside it: the record a pstr posted, the parsed body of a req's response, the SUCCESS text of acsg and acsr. |
869
875
  * | `${error}`, `${error[key]}` | In an `err` chain, the failure: `code`, `message`, `detail`, `action` (the act) and `path`. |
870
- * | `${ticket}`, `${ticket[key]}` | This consumption: `id`, `service`, `owner`, `consume_id` and `timestamp`. |
876
+ * | `${ticket}`, `${ticket[key]}` | This consumption: `id`, `service`, `owner`, `consume_id`, `timestamp` and `hash`. |
871
877
  * | `${CLIENT_SECRET}` | Reserved. See `secretName` on the req action. |
872
878
  *
873
879
  * Registration refuses anything else inside `${ }` (an unknown root such as `${id}`, keys under
874
880
  * a root that takes none such as `${ip[x]}`, `${placeholder}` or `${headers}` without a key,
875
- * broken brackets) with a message listing these forms, and a reference written where it can
876
- * never resolve (`${response}` outside a req's nested actions, `${error}` outside an `err`
881
+ * broken brackets) with a message listing these forms, `${result}` (gone: an answer is read as
882
+ * `${response}` in the action's Then chain, or captured there by a Condition action), and a reference written
883
+ * where it can never resolve (`${response}` outside a Then chain, `${error}` outside an `err`
877
884
  * chain, `${record_access}` when the condition names no record). When the action runs, a
878
885
  * reference that does not resolve fails it before it does anything: PATH_NOT_FOUND,
879
886
  * PLACEHOLDER_MISSING for a placeholder that was never captured, or AUTH_REQUIRED for `${user}`
880
887
  * on a request that is not signed in. Its `err` chain runs and the consumption stops.
888
+ *
889
+ * Every action but resp and cond answers something (the record, the response body, a SUCCESS
890
+ * text) and may carry a Then chain (`actions`, reading the answer as `${response}`). A Condition
891
+ * action in that chain checks the answer: its `response` rows read it whole (key "") or by key,
892
+ * whatever its shape. `retry: true` on acsg, acsr, pstr, req, mail and nlsd tries a failure again,
893
+ * up to 3 more times, 1, 2 and 4 seconds apart, while the time budget holds them; never for a
894
+ * failure inside Then.
881
895
  */
882
896
  type TicketAction = {
883
- /** Set the access group of a user. */
897
+ /** Set the access group of a user. Answers the SUCCESS text the grant returns. */
884
898
  act: 'acsg';
885
899
  exe: {
886
900
  /** 1 ~ 99, or "admin", or a reference that gives one when the action runs, such as "${placeholder[GROUP]}". */
887
901
  group: number | 'admin' | `${string}\${${string}}${string}`;
888
902
  /** Blank = the consumer (signed-in consumption only). The project owner cannot be a target. */
889
903
  user_id?: string;
904
+ /** The Then chain, reading the answer as `${response}`. */
905
+ actions?: TicketAction[];
890
906
  };
891
907
  err?: TicketAction[];
908
+ retry?: boolean;
892
909
  } | {
893
- /** Grant private access to a record. */
910
+ /** Grant private access to a record. Answers the SUCCESS text the grant returns. */
894
911
  act: 'acsr';
895
912
  exe: {
896
913
  /** A record ID, not a unique ID. */
897
914
  record_id: string;
898
915
  /** Blank = the consumer. */
899
916
  user_id?: string | string[];
917
+ actions?: TicketAction[];
900
918
  };
901
919
  err?: TicketAction[];
920
+ retry?: boolean;
902
921
  } | {
903
- /** Post a record. Everything but `user_id` is the payload postRecord() sends, so the same rules apply. A `unique_id` makes a retried webhook update the same record instead of adding one. */
922
+ /** Post a record. Everything but `user_id` is the payload postRecord() sends, so the same rules apply. A `unique_id` makes a retried webhook update the same record instead of adding one. Answers the record (RecordData). */
904
923
  act: 'pstr';
905
924
  exe: {
906
925
  table: string | {
@@ -922,10 +941,13 @@ type TicketAction = {
922
941
  source?: PostRecordConfig['source'];
923
942
  /** Post as this user instead of the project owner. */
924
943
  user_id?: string;
944
+ /** The Then chain, reading the record as `${response}` (`${response[record_id]}`). */
945
+ actions?: TicketAction[];
925
946
  };
926
947
  err?: TicketAction[];
948
+ retry?: boolean;
927
949
  } | {
928
- /** HTTP request with its own response condition and nested chain. Result: the parsed response body. */
950
+ /** HTTP request with its own response condition and nested chain. Answers the parsed response body. */
929
951
  act: 'req';
930
952
  exe: {
931
953
  /**
@@ -990,7 +1012,7 @@ type TicketAction = {
990
1012
  };
991
1013
  /** Legacy. Registration moves these rows to the end of `condition.data`. */
992
1014
  match?: TicketConditionRow[];
993
- /** Checked against the response. Captures land in the shared placeholder pool. See TicketResponseCondition. */
1015
+ /** Skapi's own billing rows only. A response check is a Condition action in `actions`, whose `response` rows read the answer. */
994
1016
  condition?: TicketResponseCondition;
995
1017
  /**
996
1018
  * Nested chain, run when the response passes `condition`. It reads the response body
@@ -1000,6 +1022,112 @@ type TicketAction = {
1000
1022
  actions?: TicketAction[];
1001
1023
  };
1002
1024
  err?: TicketAction[];
1025
+ retry?: boolean;
1026
+ } | {
1027
+ /**
1028
+ * Send e-mail: one e-mail from a CUSTOM template of the project (the Custom tab of the
1029
+ * Automated Emails page) to one address, from the project's alias. Counts as one e-mail
1030
+ * send (the plan's monthly sends, the Free owner cap and the complaint shutoff apply; a
1031
+ * refusal is QUOTA_EXCEEDED). Answers "SUCCESS: E-mail sent to <address>."
1032
+ */
1033
+ act: 'mail';
1034
+ exe: {
1035
+ /** The template's ID, as the Custom tab and the upload reply show it. Literal; it must be stored when the ticket is registered. */
1036
+ template: string;
1037
+ /** The recipient: one address, or a reference that gives one, such as "${user[email]}" or "${data[email]}". */
1038
+ to: string;
1039
+ /**
1040
+ * Values for the placeholders the template carries, by name: { "order": "${data[order][id]}" } fills
1041
+ * ${order}. Templated. "service_name" and "email" (the recipient) are filled by default and may be
1042
+ * overwritten here. Up to 30.
1043
+ */
1044
+ placeholders?: {
1045
+ [name: string]: string | number | boolean;
1046
+ };
1047
+ actions?: TicketAction[];
1048
+ };
1049
+ err?: TicketAction[];
1050
+ retry?: boolean;
1051
+ } | {
1052
+ /**
1053
+ * Send newsletter: a stored newsletter of a group, dry or already sent, to every subscriber of the
1054
+ * group, the way an e-mailed newsletter goes out (one e-mail send per subscriber, same gates).
1055
+ * Answers "SUCCESS: Newsletter sent to the subscribers of <group>."
1056
+ */
1057
+ act: 'nlsd';
1058
+ exe: {
1059
+ /** "public", "authorized", a number from 2 to 99, or a named group. Literal. */
1060
+ group: 'public' | 'authorized' | number | string;
1061
+ /** The newsletter's message_id (getNewsletters()). Literal; it must be stored under the group when the ticket is registered. */
1062
+ newsletter: string;
1063
+ actions?: TicketAction[];
1064
+ };
1065
+ err?: TicketAction[];
1066
+ retry?: boolean;
1067
+ } | {
1068
+ /**
1069
+ * Respond: answers the consumer now, then stops or goes on. One per run: a second Respond
1070
+ * on a path that already answered is refused at registration, and ALREADY_RESPONDED when
1071
+ * it runs. consumeTicket() resolves with the body (or the receipt), whatever the status.
1072
+ */
1073
+ act: 'resp';
1074
+ exe: {
1075
+ /** The HTTP status, 100 to 599, or a reference. Default 200. An error status is still an answer, not a failure. */
1076
+ status?: number | string;
1077
+ /** Any JSON, templated; absent: the receipt { tkid, hash }. A `stage` key is refused (that is how an error is told apart). */
1078
+ body?: any;
1079
+ /**
1080
+ * What happens after the answer. Absent or "stop": the rest of the chain does not run.
1081
+ * "0m": goes on at once, in the background. "<n>m" | "<n>h" | "<n>d" (n >= 1): goes on
1082
+ * after that delay, to the minute. A number: a time in ms since the epoch, to the second
1083
+ * (a literal in the past is refused at registration; a templated one goes on at once).
1084
+ * A run that goes on counts toward the plan's queued ticket runs for the month; Free and
1085
+ * Standard stop at theirs (QUOTA_EXCEEDED), Premium is billed past it.
1086
+ */
1087
+ resume?: 'stop' | '0m' | `${number}m` | `${number}h` | `${number}d` | number | string;
1088
+ };
1089
+ err?: TicketAction[];
1090
+ } | {
1091
+ /**
1092
+ * Condition: rows inside a chain, under the rules of the ticket's own condition. A part
1093
+ * that fails fails the chain here with CONDITION_FAILED (the action's `err` chain runs).
1094
+ * Answers nothing. `response` rows only inside a Then chain, `error` rows only inside an
1095
+ * `err` chain, `placeholder` rows name placeholders (and may compare with null).
1096
+ */
1097
+ act: 'cond';
1098
+ exe: {
1099
+ data?: TicketConditionRow[];
1100
+ params?: TicketConditionRow[];
1101
+ headers?: TicketCondition['headers'];
1102
+ ip?: TicketCondition['ip'];
1103
+ user_agent?: TicketCondition['user_agent'];
1104
+ user?: TicketCondition['user'];
1105
+ record_access?: string;
1106
+ placeholder?: {
1107
+ key: string;
1108
+ operator: TicketConditionOperator;
1109
+ value: any;
1110
+ }[];
1111
+ /** Rows on the enclosing action's answer, inside a Then chain only: a key reads a field, "" the whole answer as text. */
1112
+ response?: TicketConditionRow[];
1113
+ /** Rows on the failure, inside an err chain only: code, message, detail, action, path, or "" for the whole error as text. */
1114
+ error?: TicketConditionRow[];
1115
+ };
1116
+ err?: TicketAction[];
1117
+ };
1118
+ /** What a consumption answers when no Respond action composes the answer. */
1119
+ type TicketReceipt = {
1120
+ ticket_id: string;
1121
+ /** Id of this consumption: base62 of the timestamp in milliseconds, followed by 4 random characters. */
1122
+ consume_id: string;
1123
+ /** The consumer. The user id on the signed-in endpoint, else "<ip>(<user agent>)". */
1124
+ user_id: string;
1125
+ /** Always false here: dry runs go through the check URL, which consumeTicket() never calls. */
1126
+ is_test: boolean;
1127
+ /** When the consumption happened, in milliseconds. Decoded from consume_id. */
1128
+ timestamp: number;
1129
+ /** Proof string of the consumption. */
1130
+ hash: string;
1003
1131
  };
1004
1132
  /** An issued ticket as getTickets() and registerTicket() return it. */
1005
1133
  type Ticket = {
@@ -1026,7 +1154,7 @@ type Ticket = {
1026
1154
  */
1027
1155
  legacy?: boolean;
1028
1156
  };
1029
- 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';
1157
+ 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' | 'QUOTA_EXCEEDED' | 'ALREADY_RESPONDED' | 'INTERNAL_ERROR';
1030
1158
  /**
1031
1159
  * The body a consume endpoint answers with when the consumption fails, and the `cause` of the
1032
1160
  * SkapiError consumeTicket() rejects with. A success body never has `stage`; an error body
@@ -1095,6 +1223,7 @@ type Types_TicketConditionOperator = TicketConditionOperator;
1095
1223
  type Types_TicketConditionRow = TicketConditionRow;
1096
1224
  type Types_TicketError = TicketError;
1097
1225
  type Types_TicketErrorCode = TicketErrorCode;
1226
+ type Types_TicketReceipt = TicketReceipt;
1098
1227
  type Types_TicketResponseCondition = TicketResponseCondition;
1099
1228
  type Types_TicketSignatureCondition = TicketSignatureCondition;
1100
1229
  type Types_UniqueId = UniqueId;
@@ -1103,7 +1232,7 @@ type Types_UserProfile = UserProfile;
1103
1232
  type Types_UserPublic = UserPublic;
1104
1233
  type Types_WebSocketMessage = WebSocketMessage;
1105
1234
  declare namespace Types {
1106
- 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 };
1235
+ 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_TicketReceipt as TicketReceipt, 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 };
1107
1236
  }
1108
1237
 
1109
1238
  declare function terminatePendingRequests(): void;
@@ -1818,13 +1947,16 @@ declare class Skapi {
1818
1947
  * its actions run. An anonymous POST goes to `/tp/`, an anonymous GET to `/tg/` with `data`
1819
1948
  * as the query string, and a signed-in consumption (`auth: true`) to `/tpa/`, which is POST only.
1820
1949
  *
1950
+ * Resolves with the receipt (TicketReceipt: ticket_id, consume_id, user_id, is_test, timestamp, hash),
1951
+ * or with the body a Respond action of the ticket answered, as sent and whatever its status. `T` names that body.
1952
+ *
1821
1953
  * A failed consumption rejects with a SkapiError: `err.code` is the ticket error code and
1822
1954
  * `err.cause` the flat TicketError body (`err.cause.stage`, `err.cause.action`, `err.cause.detail`).
1823
1955
  * This holds when the ticket answers HTTP 200 as well (`return200`): the body is inspected, not the status.
1824
1956
  * @param params Request parameters.
1825
- * @returns A promise that resolves to Promise<{ ticket_id: string; consume_id: string; user_id: string; is_test: boolean; timestamp: number; hash: string; }>.
1957
+ * @returns A promise that resolves to Promise<T>, the receipt or the Respond body.
1826
1958
  */
1827
- consumeTicket(params: {
1959
+ consumeTicket<T = TicketReceipt>(params: {
1828
1960
  /** ID of the ticket to consume. */
1829
1961
  ticket_id: string;
1830
1962
  /** "GET" or "POST". */
@@ -1835,14 +1967,7 @@ declare class Skapi {
1835
1967
  data?: {
1836
1968
  [key: string]: any;
1837
1969
  };
1838
- }): Promise<{
1839
- ticket_id: string;
1840
- consume_id: string;
1841
- user_id: string;
1842
- is_test: boolean;
1843
- timestamp: number;
1844
- hash: string;
1845
- }>;
1970
+ }): Promise<T>;
1846
1971
  /**
1847
1972
  * Lists the tickets the signed-in user has consumed, with optional filters and pagination.
1848
1973
  * @param params Request parameters.
@@ -1861,9 +1986,29 @@ declare class Skapi {
1861
1986
  * @returns A promise that resolves to Promise<DatabaseResponse<any>>.
1862
1987
  */
1863
1988
  getTickets(params: {
1864
- /** Absent = every ticket. "<id>" = that ticket. "#<id>#" = the consumption log of that ticket (project owner only). */
1989
+ /** Absent = every ticket. "<id>" = that ticket. "#<id>#" = the consumption log of that ticket, "@<id>#<consume id>#" the action rows of one consumption (project owner only). */
1865
1990
  ticket_id?: string;
1991
+ /** A log listing only: rows from this time on, in milliseconds since the epoch. */
1992
+ from?: number;
1993
+ /** A log listing only: rows up to this time, in milliseconds since the epoch. */
1994
+ to?: number;
1866
1995
  }, fetchOptions?: FetchOptions): Promise<DatabaseResponse<any>>;
1996
+ /**
1997
+ * Deletes a ticket's log rows before a time, in the background over the next minutes. The ticket's
1998
+ * remaining count and its per-user limits are unchanged. Project owner only.
1999
+ * @param params Request parameters.
2000
+ * @returns A promise that resolves to Promise<{ message: string; ticket_id: string; before: number }>, `before` being the time applied (later than now is clipped to now).
2001
+ */
2002
+ clearTicketLog(params: {
2003
+ /** The ticket whose log rows go. */
2004
+ ticket_id: string;
2005
+ /** Rows before this time, in milliseconds since the epoch. Default: now. */
2006
+ before?: number;
2007
+ }): Promise<{
2008
+ message: string;
2009
+ ticket_id: string;
2010
+ before: number;
2011
+ }>;
1867
2012
  /**
1868
2013
  * Closes the active realtime WebSocket connection.
1869
2014
  * @returns A promise that resolves to Promise<void>.
@@ -3010,4 +3155,4 @@ declare class SkapiError extends Error {
3010
3155
  });
3011
3156
  }
3012
3157
 
3013
- 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 };
3158
+ 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 TicketReceipt, type TicketResponseCondition, type TicketSignatureCondition, Types, type UniqueId, type UserAttributes, type UserProfile, type UserPublic, type WebSocketMessage };