@inertiajs/core 2.1.0 → 2.1.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.
package/dist/index.js CHANGED
@@ -34,8 +34,10 @@ __export(index_exports, {
34
34
  formDataToObject: () => formDataToObject,
35
35
  hideProgress: () => hide,
36
36
  hrefToUrl: () => hrefToUrl,
37
+ isUrlMethodPair: () => isUrlMethodPair,
37
38
  mergeDataIntoQueryString: () => mergeDataIntoQueryString,
38
39
  objectToFormData: () => objectToFormData,
40
+ resetFormFields: () => resetFormFields,
39
41
  revealProgress: () => reveal,
40
42
  router: () => router,
41
43
  setupProgress: () => setupProgress,
@@ -388,14 +390,15 @@ var transformUrlAndData = (href, data, method, forceFormData, queryStringArrayFo
388
390
  return [hrefToUrl(_href), _data];
389
391
  };
390
392
  function mergeDataIntoQueryString(method, href, data, qsArrayFormat = "brackets") {
393
+ const hasDataForQueryString = method === "get" && !isFormData(data) && Object.keys(data).length > 0;
391
394
  const hasHost = /^[a-z][a-z0-9+.-]*:\/\//i.test(href.toString());
392
- const hasAbsolutePath = hasHost || href.toString().startsWith("/");
395
+ const hasAbsolutePath = hasHost || href.toString().startsWith("/") || href.toString() === "";
393
396
  const hasRelativePath = !hasAbsolutePath && !href.toString().startsWith("#") && !href.toString().startsWith("?");
394
397
  const hasRelativePathWithDotPrefix = /^[.]{1,2}([/]|$)/.test(href.toString());
395
- const hasSearch = href.toString().includes("?") || method === "get" && Object.keys(data).length;
398
+ const hasSearch = href.toString().includes("?") || hasDataForQueryString;
396
399
  const hasHash = href.toString().includes("#");
397
400
  const url = new URL(href.toString(), typeof window === "undefined" ? "http://localhost" : window.location.toString());
398
- if (method === "get" && Object.keys(data).length) {
401
+ if (hasDataForQueryString) {
399
402
  const parseOptions = { ignoreQueryPrefix: true, parseArrays: false };
400
403
  url.search = qs.stringify(
401
404
  { ...qs.parse(url.search, parseOptions), ...data },
@@ -404,7 +407,6 @@ function mergeDataIntoQueryString(method, href, data, qsArrayFormat = "brackets"
404
407
  arrayFormat: qsArrayFormat
405
408
  }
406
409
  );
407
- data = {};
408
410
  }
409
411
  return [
410
412
  [
@@ -414,7 +416,7 @@ function mergeDataIntoQueryString(method, href, data, qsArrayFormat = "brackets"
414
416
  hasSearch ? url.search : "",
415
417
  hasHash ? url.hash : ""
416
418
  ].join(""),
417
- data
419
+ hasDataForQueryString ? {} : data
418
420
  ];
419
421
  }
420
422
  function urlWithoutHash(url) {
@@ -430,6 +432,9 @@ var setHashIfSameUrl = (originUrl, destinationUrl) => {
430
432
  var isSameUrlWithoutHash = (url1, url2) => {
431
433
  return urlWithoutHash(url1).href === urlWithoutHash(url2).href;
432
434
  };
435
+ function isUrlMethodPair(href) {
436
+ return href !== null && typeof href === "object" && href !== void 0 && "url" in href && "method" in href;
437
+ }
433
438
 
434
439
  // src/page.ts
435
440
  var CurrentPage = class {
@@ -1051,7 +1056,7 @@ var PrefetchedRequests = class {
1051
1056
  this.removalTimers = [];
1052
1057
  this.currentUseId = null;
1053
1058
  }
1054
- add(params, sendFunc, { cacheFor }) {
1059
+ add(params, sendFunc, { cacheFor, cacheTags }) {
1055
1060
  const inFlight = this.findInFlight(params);
1056
1061
  if (inFlight) {
1057
1062
  return Promise.resolve();
@@ -1082,6 +1087,10 @@ var PrefetchedRequests = class {
1082
1087
  },
1083
1088
  onPrefetchResponse(response) {
1084
1089
  resolve(response);
1090
+ },
1091
+ onPrefetchError(error) {
1092
+ prefetchedRequests.removeFromInFlight(params);
1093
+ reject(error);
1085
1094
  }
1086
1095
  });
1087
1096
  }).then((response) => {
@@ -1092,12 +1101,11 @@ var PrefetchedRequests = class {
1092
1101
  response: promise,
1093
1102
  singleUse: expires === 0,
1094
1103
  timestamp: Date.now(),
1095
- inFlight: false
1104
+ inFlight: false,
1105
+ tags: Array.isArray(cacheTags) ? cacheTags : [cacheTags]
1096
1106
  });
1097
1107
  this.scheduleForRemoval(params, expires);
1098
- this.inFlightRequests = this.inFlightRequests.filter((prefetching) => {
1099
- return !this.paramsAreEqual(prefetching.params, params);
1100
- });
1108
+ this.removeFromInFlight(params);
1101
1109
  response.handlePrefetch();
1102
1110
  return response;
1103
1111
  });
@@ -1116,12 +1124,22 @@ var PrefetchedRequests = class {
1116
1124
  });
1117
1125
  this.removalTimers = [];
1118
1126
  }
1127
+ removeByTags(tags) {
1128
+ this.cached = this.cached.filter((prefetched) => {
1129
+ return !prefetched.tags.some((tag) => tags.includes(tag));
1130
+ });
1131
+ }
1119
1132
  remove(params) {
1120
1133
  this.cached = this.cached.filter((prefetched) => {
1121
1134
  return !this.paramsAreEqual(prefetched.params, params);
1122
1135
  });
1123
1136
  this.clearTimer(params);
1124
1137
  }
1138
+ removeFromInFlight(params) {
1139
+ this.inFlightRequests = this.inFlightRequests.filter((prefetching) => {
1140
+ return !this.paramsAreEqual(prefetching.params, params);
1141
+ });
1142
+ }
1125
1143
  extractStaleValues(cacheFor) {
1126
1144
  const [stale, expires] = this.cacheForToStaleAndExpires(cacheFor);
1127
1145
  return [timeToMs(stale), timeToMs(expires)];
@@ -1253,6 +1271,8 @@ var RequestParams = class _RequestParams {
1253
1271
  ...params,
1254
1272
  ...wrappedCallbacks,
1255
1273
  onPrefetchResponse: params.onPrefetchResponse || (() => {
1274
+ }),
1275
+ onPrefetchError: params.onPrefetchError || (() => {
1256
1276
  })
1257
1277
  };
1258
1278
  }
@@ -1302,6 +1322,11 @@ var RequestParams = class _RequestParams {
1302
1322
  this.params.onPrefetchResponse(response);
1303
1323
  }
1304
1324
  }
1325
+ onPrefetchError(error) {
1326
+ if (this.params.onPrefetchError) {
1327
+ this.params.onPrefetchError(error);
1328
+ }
1329
+ }
1305
1330
  all() {
1306
1331
  return this.params;
1307
1332
  }
@@ -1453,6 +1478,7 @@ var Response = class _Response {
1453
1478
  fireErrorEvent(scopedErrors);
1454
1479
  return this.requestParams.all().onError(scopedErrors);
1455
1480
  }
1481
+ router.flushByCacheTags(this.requestParams.all().invalidateCacheTags || []);
1456
1482
  fireSuccessEvent(page.get());
1457
1483
  await this.requestParams.all().onSuccess(page.get());
1458
1484
  history.preserveUrl = false;
@@ -1684,6 +1710,9 @@ var Request = class _Request {
1684
1710
  return;
1685
1711
  }
1686
1712
  if (fireExceptionEvent(error)) {
1713
+ if (originallyPrefetch) {
1714
+ this.requestParams.onPrefetchError(error);
1715
+ }
1687
1716
  return Promise.reject(error);
1688
1717
  }
1689
1718
  }).finally(() => {
@@ -1892,11 +1921,15 @@ var Router = class {
1892
1921
  flushAll() {
1893
1922
  prefetchedRequests.removeAll();
1894
1923
  }
1924
+ flushByCacheTags(tags) {
1925
+ prefetchedRequests.removeByTags(Array.isArray(tags) ? tags : [tags]);
1926
+ }
1895
1927
  getPrefetching(href, options = {}) {
1896
1928
  return prefetchedRequests.findInFlight(this.getPrefetchParams(href, options));
1897
1929
  }
1898
- prefetch(href, options = {}, { cacheFor = 3e4 }) {
1899
- if (options.method !== "get") {
1930
+ prefetch(href, options = {}, prefetchOptions = {}) {
1931
+ const method = options.method ?? (isUrlMethodPair(href) ? href.method : "get");
1932
+ if (method !== "get") {
1900
1933
  throw new Error("Prefetch requests must use the GET method");
1901
1934
  }
1902
1935
  const visit = this.getPendingVisit(href, {
@@ -1938,7 +1971,11 @@ var Router = class {
1938
1971
  (params) => {
1939
1972
  this.asyncRequestStream.send(Request.create(params, page.get()));
1940
1973
  },
1941
- { cacheFor }
1974
+ {
1975
+ cacheFor: 3e4,
1976
+ cacheTags: [],
1977
+ ...prefetchOptions
1978
+ }
1942
1979
  );
1943
1980
  });
1944
1981
  }
@@ -1993,6 +2030,11 @@ var Router = class {
1993
2030
  };
1994
2031
  }
1995
2032
  getPendingVisit(href, options, pendingVisitOptions = {}) {
2033
+ if (isUrlMethodPair(href)) {
2034
+ const urlMethodPair = href;
2035
+ href = urlMethodPair.url;
2036
+ options.method = options.method ?? urlMethodPair.method;
2037
+ }
1996
2038
  const mergedOptions = {
1997
2039
  method: "get",
1998
2040
  data: {},
@@ -2011,6 +2053,7 @@ var Router = class {
2011
2053
  reset: [],
2012
2054
  preserveUrl: false,
2013
2055
  prefetch: false,
2056
+ invalidateCacheTags: [],
2014
2057
  ...options
2015
2058
  };
2016
2059
  const [url, _data] = transformUrlAndData(
@@ -2117,6 +2160,140 @@ function formDataToObject(source) {
2117
2160
  return form;
2118
2161
  }
2119
2162
 
2163
+ // src/resetFormFields.ts
2164
+ function isFormElement(element) {
2165
+ return element instanceof HTMLInputElement || element instanceof HTMLSelectElement || element instanceof HTMLTextAreaElement;
2166
+ }
2167
+ function resetInputElement(input, defaultValues) {
2168
+ const oldValue = input.value;
2169
+ const oldChecked = input.checked;
2170
+ switch (input.type.toLowerCase()) {
2171
+ case "checkbox":
2172
+ input.checked = defaultValues.includes(input.value);
2173
+ break;
2174
+ case "radio":
2175
+ input.checked = defaultValues[0] === input.value;
2176
+ break;
2177
+ case "file":
2178
+ input.value = "";
2179
+ break;
2180
+ case "button":
2181
+ case "submit":
2182
+ case "reset":
2183
+ case "image":
2184
+ break;
2185
+ default:
2186
+ input.value = defaultValues[0] !== null && defaultValues[0] !== void 0 ? String(defaultValues[0]) : "";
2187
+ }
2188
+ return input.value !== oldValue || input.checked !== oldChecked;
2189
+ }
2190
+ function resetSelectElement(select, defaultValues) {
2191
+ const oldValue = select.value;
2192
+ const oldSelectedOptions = Array.from(select.selectedOptions).map((opt) => opt.value);
2193
+ if (select.multiple) {
2194
+ const defaultStrings = defaultValues.map((value) => String(value));
2195
+ Array.from(select.options).forEach((option) => {
2196
+ option.selected = defaultStrings.includes(option.value);
2197
+ });
2198
+ } else {
2199
+ select.value = defaultValues[0] !== void 0 ? String(defaultValues[0]) : "";
2200
+ }
2201
+ const newSelectedOptions = Array.from(select.selectedOptions).map((opt) => opt.value);
2202
+ const hasChanged = select.multiple ? JSON.stringify(oldSelectedOptions.sort()) !== JSON.stringify(newSelectedOptions.sort()) : select.value !== oldValue;
2203
+ return hasChanged;
2204
+ }
2205
+ function resetFormElement(element, defaultValues) {
2206
+ if (element.disabled) {
2207
+ if (element instanceof HTMLInputElement) {
2208
+ const oldValue = element.value;
2209
+ const oldChecked = element.checked;
2210
+ switch (element.type.toLowerCase()) {
2211
+ case "checkbox":
2212
+ case "radio":
2213
+ element.checked = element.defaultChecked;
2214
+ return element.checked !== oldChecked;
2215
+ case "file":
2216
+ element.value = "";
2217
+ return oldValue !== "";
2218
+ case "button":
2219
+ case "submit":
2220
+ case "reset":
2221
+ case "image":
2222
+ return false;
2223
+ default:
2224
+ element.value = element.defaultValue;
2225
+ return element.value !== oldValue;
2226
+ }
2227
+ } else if (element instanceof HTMLSelectElement) {
2228
+ const oldSelectedOptions = Array.from(element.selectedOptions).map((opt) => opt.value);
2229
+ Array.from(element.options).forEach((option) => {
2230
+ option.selected = option.defaultSelected;
2231
+ });
2232
+ const newSelectedOptions = Array.from(element.selectedOptions).map((opt) => opt.value);
2233
+ return JSON.stringify(oldSelectedOptions.sort()) !== JSON.stringify(newSelectedOptions.sort());
2234
+ } else if (element instanceof HTMLTextAreaElement) {
2235
+ const oldValue = element.value;
2236
+ element.value = element.defaultValue;
2237
+ return element.value !== oldValue;
2238
+ }
2239
+ return false;
2240
+ }
2241
+ if (element instanceof HTMLInputElement) {
2242
+ return resetInputElement(element, defaultValues);
2243
+ } else if (element instanceof HTMLSelectElement) {
2244
+ return resetSelectElement(element, defaultValues);
2245
+ } else if (element instanceof HTMLTextAreaElement) {
2246
+ const oldValue = element.value;
2247
+ element.value = defaultValues[0] !== void 0 ? String(defaultValues[0]) : "";
2248
+ return element.value !== oldValue;
2249
+ }
2250
+ return false;
2251
+ }
2252
+ function resetFieldElements(elements, defaultValues) {
2253
+ let hasChanged = false;
2254
+ if (elements instanceof RadioNodeList || elements instanceof HTMLCollection) {
2255
+ Array.from(elements).forEach((node, index) => {
2256
+ if (node instanceof Element && isFormElement(node)) {
2257
+ if (node instanceof HTMLInputElement && ["checkbox", "radio"].includes(node.type.toLowerCase())) {
2258
+ if (resetFormElement(node, defaultValues)) {
2259
+ hasChanged = true;
2260
+ }
2261
+ } else {
2262
+ const indexedDefaultValues = defaultValues[index] !== void 0 ? [defaultValues[index]] : [defaultValues[0] ?? null].filter(Boolean);
2263
+ if (resetFormElement(node, indexedDefaultValues)) {
2264
+ hasChanged = true;
2265
+ }
2266
+ }
2267
+ }
2268
+ });
2269
+ } else if (isFormElement(elements)) {
2270
+ hasChanged = resetFormElement(elements, defaultValues);
2271
+ }
2272
+ return hasChanged;
2273
+ }
2274
+ function resetFormFields(formElement, defaults, fieldNames) {
2275
+ if (!formElement) {
2276
+ return;
2277
+ }
2278
+ if (!fieldNames || fieldNames.length === 0) {
2279
+ const formData = new FormData(formElement);
2280
+ const formElementNames = Array.from(formElement.elements).map((el) => isFormElement(el) ? el.name : "").filter(Boolean);
2281
+ fieldNames = [.../* @__PURE__ */ new Set([...defaults.keys(), ...formData.keys(), ...formElementNames])];
2282
+ }
2283
+ let hasChanged = false;
2284
+ fieldNames.forEach((fieldName) => {
2285
+ const elements = formElement.elements.namedItem(fieldName);
2286
+ if (elements) {
2287
+ if (resetFieldElements(elements, defaults.getAll(fieldName))) {
2288
+ hasChanged = true;
2289
+ }
2290
+ }
2291
+ });
2292
+ if (hasChanged) {
2293
+ formElement.dispatchEvent(new Event("reset", { bubbles: true }));
2294
+ }
2295
+ }
2296
+
2120
2297
  // src/head.ts
2121
2298
  var Renderer = {
2122
2299
  buildDOMElement(tag) {