@brandup/ui-ajax 1.0.44 → 2.0.2

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.
@@ -0,0 +1,106 @@
1
+ import { addQuery } from './helpers.js';
2
+ import internals from './internals.js';
3
+
4
+ /**
5
+ * Performs an AJAX request using the Fetch API.
6
+ *
7
+ * The response body is parsed according to its `Content-Type`: JSON, `text/html`,
8
+ * `text/plain`, otherwise a `Blob`. `disableCache` maps to `cache: "no-store"`.
9
+ * The request is aborted when its `timeout` elapses (defaults to 30000 ms), or when
10
+ * `options.abort` or the `abortSignal` argument signals.
11
+ *
12
+ * @param options Request options. `GET`/`HEAD` requests must not carry `data`.
13
+ * @param abortSignal Optional additional signal used to cancel the request.
14
+ * @returns The parsed response. `options.success` is also invoked before resolving.
15
+ * @throws On network/abort/timeout errors, or for unsupported (opaque) response types; `options.error` is invoked before re-throwing.
16
+ */
17
+ async function request(options, abortSignal) {
18
+ let { mode, credentials = "include" } = options;
19
+ let url = options.url || location.href;
20
+ url = addQuery(url, options.query);
21
+ const method = options.method ? options.method.toUpperCase() : "GET";
22
+ let body = options.data;
23
+ if (body && (method === "GET" || method === "HEAD"))
24
+ throw new Error(`${method} method does not support a request body.`);
25
+ internals.detectRequestType(options);
26
+ const prepared = internals.prepareRequest(options, body);
27
+ const abortSignals = [AbortSignal.timeout(options.timeout ?? internals.DEFAULT_TIMEOUT)];
28
+ if (options.abort)
29
+ abortSignals.push(options.abort);
30
+ if (abortSignal)
31
+ abortSignals.push(abortSignal);
32
+ try {
33
+ const response = await fetch(url, {
34
+ method,
35
+ headers: new Headers(prepared.headers),
36
+ cache: options.disableCache ? "no-store" : "default",
37
+ mode,
38
+ credentials,
39
+ redirect: "follow",
40
+ signal: AbortSignal.any(abortSignals),
41
+ body: prepared.body
42
+ });
43
+ let result;
44
+ switch (response.type) {
45
+ case "basic":
46
+ case "default":
47
+ case "cors": {
48
+ let responseData = null;
49
+ let responseType = "none";
50
+ let contentType = response.headers.get("content-type");
51
+ if (!response.redirected && response.body) {
52
+ if (contentType) {
53
+ const ctSplitIndex = contentType.indexOf(";");
54
+ if (ctSplitIndex > 0)
55
+ contentType = contentType.substring(0, ctSplitIndex);
56
+ if (contentType.includes("json")) {
57
+ responseType = "json";
58
+ responseData = await response.json();
59
+ }
60
+ else if (contentType.includes("text/html")) {
61
+ responseType = "html";
62
+ responseData = await response.text();
63
+ }
64
+ else if (contentType.includes("text/plain")) {
65
+ responseType = "text";
66
+ responseData = await response.text();
67
+ }
68
+ else {
69
+ responseType = "blob";
70
+ responseData = await response.blob();
71
+ }
72
+ }
73
+ }
74
+ result = {
75
+ status: response.status,
76
+ url: response.url,
77
+ redirected: response.redirected,
78
+ type: responseType,
79
+ contentType,
80
+ headers: response.headers,
81
+ data: responseData,
82
+ state: options.state
83
+ };
84
+ break;
85
+ }
86
+ case "opaqueredirect":
87
+ case "opaque":
88
+ throw new Error(`Not supported response type: ${response.type}`);
89
+ case "error":
90
+ throw new Error("Response error.");
91
+ default:
92
+ throw new Error(`Unknown response type: ${response.type}`);
93
+ }
94
+ if (options.success)
95
+ options.success(result);
96
+ return result;
97
+ }
98
+ catch (error) {
99
+ if (options.error)
100
+ options.error(options, error);
101
+ throw error;
102
+ }
103
+ }
104
+
105
+ export { request };
106
+ //# sourceMappingURL=request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.js","sources":["../../../source/request.ts"],"sourcesContent":[null],"names":["helpers.addQuery"],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -1,75 +1,189 @@
1
+ /** HTTP method for an AJAX request. Common verbs are suggested, but any custom string is allowed. */
1
2
  type AJAXMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | string;
2
- type AJAXReqestType = "NONE" | "JSON" | "XML" | "FORM" | "FORMDATA" | "TEXT" | "BLOB";
3
+ /** Request body kind. Controls the `Content-Type`/`Accept` headers and how `data` is serialized. When omitted it is auto-detected from `data`. */
4
+ type AJAXRequestType = "NONE" | "JSON" | "XML" | "FORM" | "FORMDATA" | "TEXT" | "BLOB";
5
+ /** @deprecated Renamed to {@link AJAXRequestType}. */
6
+ type AJAXReqestType = AJAXRequestType;
7
+ /** Resolved kind of the response body, derived from the response `Content-Type`. `"blob"` only occurs for the fetch-based {@link request}; `ajaxRequest` (XHR) never returns blob. */
3
8
  type ResponseType = "none" | "json" | "blob" | "text" | "html";
9
+ /** Callback invoked with the parsed response on success. */
4
10
  type ResponseDelegate = (response: AjaxResponse) => void;
11
+ /** Callback invoked when a request fails or is aborted. `reason` is the thrown error or an abort/timeout message. */
5
12
  type ErrorDelegate = (request: AjaxRequest, reason?: any) => void;
13
+ /** Query string parameters. Each value may be a single string or an array (repeated key). */
6
14
  type QueryData = {
7
15
  [key: string]: string | string[];
8
16
  };
17
+ /** Options describing an AJAX request. */
9
18
  interface AjaxRequest<TState = any> {
19
+ /** Target URL. Defaults to the current `location.href` when omitted. */
10
20
  url?: string | null;
21
+ /** Query string parameters appended to the URL. */
11
22
  query?: QueryData | null;
23
+ /** HTTP method. Defaults to `"GET"`; normalized to upper-case. */
12
24
  method?: AJAXMethod | null;
25
+ /** Fetch request mode (e.g. `"cors"`). Only honored by the fetch-based {@link request}. */
13
26
  mode?: RequestMode;
27
+ /** Fetch credentials policy. Defaults to `"include"` in {@link request}; XHR always sends credentials. */
14
28
  credentials?: RequestCredentials;
29
+ /** Timeout in milliseconds. {@link request} defaults to 30000 ms when omitted; `0` disables the XHR timeout. */
15
30
  timeout?: number | null;
31
+ /** Additional request headers. Entries with empty values are skipped. */
16
32
  headers?: {
17
33
  [key: string]: string;
18
34
  } | null;
19
- type?: AJAXReqestType | null;
35
+ /** Body serialization kind. Auto-detected from `data` when omitted. */
36
+ type?: AJAXRequestType | null;
37
+ /** Request body. Not allowed for `GET` (and `HEAD` in {@link request}). */
20
38
  data?: string | object | Blob | FormData | HTMLFormElement | null;
39
+ /** Signal used to abort the request. */
21
40
  abort?: AbortSignal;
41
+ /** Called with the response on success. */
22
42
  success?: ResponseDelegate | null;
43
+ /** Called on failure, abort or timeout. */
23
44
  error?: ErrorDelegate | null;
45
+ /** When `true`, bypasses caching. {@link request} sends `cache: "no-store"`; `ajaxRequest` appends a `_=<timestamp>` cache-busting query param. */
24
46
  disableCache?: boolean | null;
47
+ /** Arbitrary state passed through to the response unchanged. */
25
48
  state?: TState | null;
26
49
  }
50
+ /** Parsed result of an AJAX request. */
27
51
  interface AjaxResponse<TData = any, TState = any> {
52
+ /** HTTP status code. */
28
53
  status: number;
54
+ /** Whether the request was redirected. Always `false` for `ajaxRequest` (XHR). */
29
55
  redirected: boolean;
56
+ /** Final response URL. */
30
57
  url: string | null;
58
+ /** Resolved body kind derived from the response `Content-Type`. */
31
59
  type: ResponseType;
60
+ /** Raw `Content-Type` header value. */
32
61
  contentType: string | null;
62
+ /** Accessor over the response headers. */
33
63
  headers: ResponseHeaders;
64
+ /** Parsed response body, or `null` when there is no body. */
34
65
  data: TData | null;
66
+ /** State value carried over from the originating request. */
35
67
  state?: TState | null;
36
68
  }
69
+ /** Read-only accessor over response headers, mirroring a subset of the Fetch `Headers` API. */
37
70
  interface ResponseHeaders {
71
+ /** Returns the value of the given header, or `null` if absent. */
38
72
  get(name: string): string | null;
73
+ /** Returns whether the given header is present. */
39
74
  has(name: string): boolean;
75
+ /** Iterates over each header value/name pair. */
40
76
  forEach(callbackfn: (value: string, key: string, parent: ResponseHeaders) => void, thisArg?: any): void;
41
77
  }
42
78
 
43
- /** Request with fetch. */
79
+ /**
80
+ * Performs an AJAX request using the Fetch API.
81
+ *
82
+ * The response body is parsed according to its `Content-Type`: JSON, `text/html`,
83
+ * `text/plain`, otherwise a `Blob`. `disableCache` maps to `cache: "no-store"`.
84
+ * The request is aborted when its `timeout` elapses (defaults to 30000 ms), or when
85
+ * `options.abort` or the `abortSignal` argument signals.
86
+ *
87
+ * @param options Request options. `GET`/`HEAD` requests must not carry `data`.
88
+ * @param abortSignal Optional additional signal used to cancel the request.
89
+ * @returns The parsed response. `options.success` is also invoked before resolving.
90
+ * @throws On network/abort/timeout errors, or for unsupported (opaque) response types; `options.error` is invoked before re-throwing.
91
+ */
44
92
  declare function request<TData = any, TState = any>(options: AjaxRequest<TState>, abortSignal?: AbortSignal): Promise<AjaxResponse<TData, TState>>;
45
93
 
46
- /** Request with XMLHttpRequest. */
94
+ /**
95
+ * Performs an AJAX request using `XMLHttpRequest`, always with credentials.
96
+ *
97
+ * The response body is parsed by `Content-Type` into JSON, `text/plain` or `text/html`;
98
+ * unlike the fetch-based {@link request}, there is no `blob` response type. `disableCache`
99
+ * appends a `_=<timestamp>` cache-busting query parameter (rather than `cache: "no-store"`).
100
+ * Results and errors are delivered through `options.success` / `options.error`; this
101
+ * function does not return a promise.
102
+ *
103
+ * @param options Request options. `GET` requests must not carry `data`. `timeout` of `0` disables the timeout.
104
+ * @returns The underlying `XMLHttpRequest`, which can be used to `abort()` the request.
105
+ */
47
106
  declare const ajaxRequest: (options: AjaxRequest) => XMLHttpRequest;
48
107
 
108
+ /** Queue that executes AJAX requests one at a time, in the order they were added. */
49
109
  declare class AjaxQueue {
50
110
  private _options;
51
111
  private _requests;
52
- private _curent;
112
+ private _current;
53
113
  private _destroyed;
114
+ /** @param options Optional queue-wide hooks. */
54
115
  constructor(options?: AjaxQueueOptions);
116
+ /** Number of requests waiting in the queue (excluding the one currently executing). */
55
117
  get length(): number;
118
+ /** `true` when nothing is queued and no request is currently executing. */
56
119
  get isFree(): boolean;
120
+ /** `true` when no requests are waiting in the queue (a request may still be executing). */
57
121
  get isEmpty(): boolean;
122
+ /**
123
+ * Adds a request to the queue. Starts executing immediately if the queue is idle.
124
+ *
125
+ * @param request Request options; its `success`/`error` callbacks are invoked as usual.
126
+ * @param abortSignal Optional signal used to cancel this specific request.
127
+ * @throws If the queue has been destroyed.
128
+ */
58
129
  push(request: AjaxRequest, abortSignal?: AbortSignal): void;
130
+ /**
131
+ * Adds a request to the queue and returns a promise for its response.
132
+ *
133
+ * Wraps {@link push}; the request's own `success`/`error` callbacks are still invoked,
134
+ * then the promise resolves with the response or rejects with the failure reason.
135
+ *
136
+ * @param request Request options.
137
+ * @param abortSignal Optional signal used to cancel this specific request.
138
+ * @returns A promise resolving with the {@link AjaxResponse}.
139
+ */
140
+ enqueue<TResponse = any>(request: AjaxRequest, abortSignal?: AbortSignal): Promise<AjaxResponse<TResponse, any>>;
141
+ /** @deprecated Renamed to {@link enqueue}. */
59
142
  enque<TResponse = any>(request: AjaxRequest, abortSignal?: AbortSignal): Promise<AjaxResponse<TResponse, any>>;
143
+ /**
144
+ * Clears all queued (not-yet-started) requests.
145
+ *
146
+ * @param cancelCurrentRequest When `true`, also aborts the request currently executing.
147
+ */
60
148
  reset(cancelCurrentRequest?: boolean): void;
149
+ /** Destroys the queue: clears pending requests and aborts the current one. Subsequent {@link push} calls throw. */
61
150
  destroy(): void;
62
151
  private __execute;
63
152
  private __next;
64
153
  }
154
+ /** Queue-wide hooks invoked for every request processed by an {@link AjaxQueue}. */
65
155
  interface AjaxQueueOptions {
66
- canRequest?: (request: AjaxRequest) => void | boolean;
156
+ /** Called before a request is sent; returning `false` skips it (it is dropped without being sent). */
157
+ canRequest?: (request: AjaxRequest) => boolean | void;
158
+ /** Called after a request completes successfully. */
67
159
  successRequest?: (request: AjaxRequest, response: AjaxResponse) => void;
160
+ /** Called when a request fails or is aborted. */
68
161
  errorRequest?: (response: AjaxRequest, reason?: any) => void;
69
162
  }
70
163
 
164
+ /**
165
+ * Builds a `URLSearchParams` from query data or a `FormData`.
166
+ *
167
+ * Array values produce repeated keys; `null` values are skipped.
168
+ *
169
+ * @param query Source parameters.
170
+ * @returns The populated `URLSearchParams` (empty when `query` is nullish).
171
+ */
71
172
  declare const createQuery: (query?: QueryData | FormData | null) => URLSearchParams;
173
+ /**
174
+ * Appends query parameters to a URL, choosing `?` or `&` as appropriate.
175
+ *
176
+ * @param url Base URL.
177
+ * @param query Parameters to append; nothing is added when empty.
178
+ * @returns The resulting URL.
179
+ */
72
180
  declare const addQuery: (url: string, query?: QueryData | FormData | null) => string;
181
+ /**
182
+ * Encodes a `FormData` as an `application/x-www-form-urlencoded` string.
183
+ *
184
+ * @param data Form data to encode.
185
+ * @returns The URL-encoded form string.
186
+ */
73
187
  declare const encodeForm: (data: FormData) => string;
74
188
 
75
189
  declare const helpers_addQuery: typeof addQuery;
@@ -84,4 +198,4 @@ declare namespace helpers {
84
198
  }
85
199
 
86
200
  export { AjaxQueue, helpers as RequestHelper, ajaxRequest, request };
87
- export type { AJAXMethod, AJAXReqestType, AjaxQueueOptions, AjaxRequest, AjaxResponse, ErrorDelegate, QueryData, ResponseDelegate, ResponseHeaders, ResponseType };
201
+ export type { AJAXMethod, AJAXReqestType, AJAXRequestType, AjaxQueueOptions, AjaxRequest, AjaxResponse, ErrorDelegate, QueryData, ResponseDelegate, ResponseHeaders, ResponseType };
package/package.json CHANGED
@@ -21,10 +21,18 @@
21
21
  "email": "it@brandup.online"
22
22
  },
23
23
  "license": "Apache-2.0",
24
- "version": "1.0.44",
24
+ "version": "2.0.2",
25
25
  "main": "dist/cjs/index.js",
26
26
  "module": "dist/mjs/index.js",
27
27
  "types": "dist/types.d.ts",
28
+ "sideEffects": false,
29
+ "exports": {
30
+ ".": {
31
+ "types": "./dist/types.d.ts",
32
+ "import": "./dist/mjs/index.js",
33
+ "require": "./dist/cjs/index.js"
34
+ }
35
+ },
28
36
  "files": [
29
37
  "dist",
30
38
  "README.md"