@inertiajs/core 3.0.0-beta.1 → 3.0.0-beta.3

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
@@ -1,5 +1,5 @@
1
1
  // src/router.ts
2
- import { cloneDeep as cloneDeep3, get as get7, isEqual as isEqual3, set as set5 } from "lodash-es";
2
+ import { cloneDeep as cloneDeep4, get as get7, isEqual as isEqual3, set as set5 } from "lodash-es";
3
3
 
4
4
  // src/config.ts
5
5
  import { get, has, set } from "lodash-es";
@@ -99,7 +99,7 @@ var fireFlashEvent = (flash) => {
99
99
  };
100
100
 
101
101
  // src/history.ts
102
- import { cloneDeep as cloneDeep2, isEqual } from "lodash-es";
102
+ import { cloneDeep as cloneDeep3, isEqual } from "lodash-es";
103
103
 
104
104
  // src/sessionStorage.ts
105
105
  var SessionStorage = class {
@@ -271,7 +271,7 @@ var getKeyFromSessionStorage = async () => {
271
271
  };
272
272
 
273
273
  // src/page.ts
274
- import { get as get3, set as set3 } from "lodash-es";
274
+ import { cloneDeep as cloneDeep2, get as get3, set as set3 } from "lodash-es";
275
275
 
276
276
  // src/prefetched.ts
277
277
  import { cloneDeep, get as get2 } from "lodash-es";
@@ -976,9 +976,9 @@ function resolveUrlMethodPairComponent(pair) {
976
976
  if (!pair.component) {
977
977
  return null;
978
978
  }
979
- if (Array.isArray(pair.component)) {
979
+ if (typeof pair.component !== "string") {
980
980
  console.error(
981
- `The "component" property on the URL method pair received an array of components (${pair.component.join(", ")}), but only a single component string is supported for instant visits. Pass an explicit component name instead.`
981
+ `The "component" property on the URL method pair received multiple components (${Object.keys(pair.component).join(", ")}), but only a single component string is supported for instant visits. Use the withComponent() method to specify which component to use.`
982
982
  );
983
983
  return null;
984
984
  }
@@ -1001,6 +1001,9 @@ var CurrentPage = class {
1001
1001
  this.cleared = false;
1002
1002
  this.pendingDeferredProps = null;
1003
1003
  this.historyQuotaExceeded = false;
1004
+ this.optimisticBaseline = {};
1005
+ this.pendingOptimistics = [];
1006
+ this.optimisticCounter = 0;
1004
1007
  }
1005
1008
  init({
1006
1009
  initialPage,
@@ -1048,7 +1051,6 @@ var CurrentPage = class {
1048
1051
  const scrollRegions = !isServer3 && preserveScroll ? Scroll.getScrollRegions() : [];
1049
1052
  replace = replace || isSameUrlWithoutHash(hrefToUrl(page2.url), location);
1050
1053
  const pageForHistory = { ...page2, flash: {} };
1051
- delete pageForHistory.optimisticUpdatedAt;
1052
1054
  return new Promise(
1053
1055
  (resolve) => replace ? history.replaceState(pageForHistory, resolve) : history.pushState(pageForHistory, resolve)
1054
1056
  ).then(() => {
@@ -1147,7 +1149,7 @@ var CurrentPage = class {
1147
1149
  viewTransition
1148
1150
  }) {
1149
1151
  const doSwap = () => this.swapComponent({ component, page: page2, preserveState });
1150
- if (!viewTransition || !document?.startViewTransition) {
1152
+ if (!viewTransition || !document?.startViewTransition || document.visibilityState === "hidden") {
1151
1153
  return doSwap();
1152
1154
  }
1153
1155
  const viewTransitionCallback = typeof viewTransition === "boolean" ? () => null : viewTransition;
@@ -1159,19 +1161,55 @@ var CurrentPage = class {
1159
1161
  resolve(component, page2) {
1160
1162
  return Promise.resolve(this.resolveComponent(component, page2));
1161
1163
  }
1162
- recordOptimisticUpdate(keys, updatedAt) {
1163
- if (!this.page.optimisticUpdatedAt) {
1164
- this.page.optimisticUpdatedAt = {};
1164
+ nextOptimisticId() {
1165
+ return ++this.optimisticCounter;
1166
+ }
1167
+ setBaseline(key, value) {
1168
+ if (!(key in this.optimisticBaseline)) {
1169
+ this.optimisticBaseline[key] = value;
1170
+ }
1171
+ }
1172
+ updateBaseline(key, value) {
1173
+ if (key in this.optimisticBaseline) {
1174
+ this.optimisticBaseline[key] = value;
1175
+ }
1176
+ }
1177
+ hasBaseline(key) {
1178
+ return key in this.optimisticBaseline;
1179
+ }
1180
+ registerOptimistic(id, callback) {
1181
+ this.pendingOptimistics.push({ id, callback });
1182
+ }
1183
+ unregisterOptimistic(id) {
1184
+ this.pendingOptimistics = this.pendingOptimistics.filter((entry) => entry.id !== id);
1185
+ }
1186
+ replayOptimistics() {
1187
+ const baselineKeys = Object.keys(this.optimisticBaseline);
1188
+ if (baselineKeys.length === 0) {
1189
+ return {};
1190
+ }
1191
+ const props = cloneDeep2(this.page.props);
1192
+ for (const key of baselineKeys) {
1193
+ props[key] = cloneDeep2(this.optimisticBaseline[key]);
1165
1194
  }
1166
- for (const key of keys) {
1167
- if (updatedAt > (this.page.optimisticUpdatedAt[key] || 0)) {
1168
- this.page.optimisticUpdatedAt[key] = updatedAt;
1195
+ for (const { callback } of this.pendingOptimistics) {
1196
+ const result = callback(cloneDeep2(props));
1197
+ if (result) {
1198
+ Object.assign(props, result);
1169
1199
  }
1170
1200
  }
1201
+ const replayedProps = {};
1202
+ for (const key of baselineKeys) {
1203
+ replayedProps[key] = props[key];
1204
+ }
1205
+ return replayedProps;
1206
+ }
1207
+ pendingOptimisticCount() {
1208
+ return this.pendingOptimistics.length;
1171
1209
  }
1172
- shouldPreserveOptimistic(key, updatedAt) {
1173
- const lastUpdatedAt = this.page.optimisticUpdatedAt?.[key];
1174
- return lastUpdatedAt !== void 0 && updatedAt < lastUpdatedAt;
1210
+ clearOptimisticState() {
1211
+ this.optimisticBaseline = {};
1212
+ this.pendingOptimistics = [];
1175
1213
  }
1176
1214
  isTheSame(page2) {
1177
1215
  return this.page.component === page2.component;
@@ -1280,7 +1318,7 @@ var History = class {
1280
1318
  } catch {
1281
1319
  return {
1282
1320
  ...page2,
1283
- props: cloneDeep2(page2.props)
1321
+ props: cloneDeep3(page2.props)
1284
1322
  };
1285
1323
  }
1286
1324
  }
@@ -2217,9 +2255,20 @@ var Response = class _Response {
2217
2255
  if (!this.isInertiaResponse()) {
2218
2256
  return this.handleNonInertiaResponse();
2219
2257
  }
2258
+ if (this.isHttpException()) {
2259
+ const response = {
2260
+ ...this.response,
2261
+ data: this.getDataFromResponse(this.response.data)
2262
+ };
2263
+ if (this.requestParams.all().onHttpException(response) === false) {
2264
+ return;
2265
+ }
2266
+ if (!fireHttpExceptionEvent(response)) {
2267
+ return;
2268
+ }
2269
+ }
2220
2270
  await history.processQueue();
2221
2271
  history.preserveUrl = this.requestParams.all().preserveUrl;
2222
- const previousFlash = page.get().flash;
2223
2272
  await this.setPage();
2224
2273
  const errors = page.get().props.errors || {};
2225
2274
  if (Object.keys(errors).length > 0) {
@@ -2232,7 +2281,7 @@ var Response = class _Response {
2232
2281
  router.flush(page.get().url);
2233
2282
  }
2234
2283
  const { flash } = page.get();
2235
- if (Object.keys(flash).length > 0 && (!this.requestParams.isPartial() || !isEqual2(flash, previousFlash))) {
2284
+ if (Object.keys(flash).length > 0 && !this.requestParams.isDeferredPropsRequest()) {
2236
2285
  fireFlashEvent(flash);
2237
2286
  this.requestParams.all().onFlash(flash);
2238
2287
  }
@@ -2278,6 +2327,9 @@ var Response = class _Response {
2278
2327
  isInertiaResponse() {
2279
2328
  return this.hasHeader("x-inertia");
2280
2329
  }
2330
+ isHttpException() {
2331
+ return this.response.status >= 400;
2332
+ }
2281
2333
  hasStatus(status2) {
2282
2334
  return this.response.status === status2;
2283
2335
  }
@@ -2368,16 +2420,15 @@ var Response = class _Response {
2368
2420
  return responseUrl.pathname + responseUrl.search + responseUrl.hash;
2369
2421
  }
2370
2422
  preserveOptimisticProps(pageResponse) {
2371
- const optimisticUpdatedAt = page.get().optimisticUpdatedAt;
2372
- if (!optimisticUpdatedAt || !router.hasPendingOptimistic()) {
2423
+ if (!router.hasPendingOptimistic()) {
2373
2424
  return;
2374
2425
  }
2375
2426
  for (const key of Object.keys(pageResponse.props)) {
2376
- if (key in optimisticUpdatedAt) {
2427
+ if (page.hasBaseline(key)) {
2428
+ page.updateBaseline(key, pageResponse.props[key]);
2377
2429
  pageResponse.props[key] = page.get().props[key];
2378
2430
  }
2379
2431
  }
2380
- pageResponse.optimisticUpdatedAt = { ...optimisticUpdatedAt };
2381
2432
  }
2382
2433
  preserveEqualProps(pageResponse) {
2383
2434
  if (pageResponse.component !== page.get().component) {
@@ -2700,7 +2751,7 @@ var RequestStream = class {
2700
2751
  }
2701
2752
  send(request) {
2702
2753
  this.requests.push(request);
2703
- request.send().then(() => {
2754
+ request.send().finally(() => {
2704
2755
  this.requests = this.requests.filter((r) => r !== request);
2705
2756
  });
2706
2757
  }
@@ -2989,7 +3040,7 @@ var Router = class {
2989
3040
  preserveState: true,
2990
3041
  props(currentProps) {
2991
3042
  const newValue = typeof value === "function" ? value(get7(currentProps, name), currentProps) : value;
2992
- return set5(cloneDeep3(currentProps), name, newValue);
3043
+ return set5(cloneDeep4(currentProps), name, newValue);
2993
3044
  },
2994
3045
  ...options || {}
2995
3046
  });
@@ -3087,7 +3138,7 @@ var Router = class {
3087
3138
  const sharedProps = Object.fromEntries(
3088
3139
  (current.sharedProps ?? []).filter((key) => key in current.props).map((key) => [key, current.props[key]])
3089
3140
  );
3090
- const resolvedPageProps = typeof visit.pageProps === "function" ? visit.pageProps(cloneDeep3(current.props), cloneDeep3(sharedProps)) : visit.pageProps;
3141
+ const resolvedPageProps = typeof visit.pageProps === "function" ? visit.pageProps(cloneDeep4(current.props), cloneDeep4(sharedProps)) : visit.pageProps;
3091
3142
  const intermediateProps = resolvedPageProps !== null ? { ...resolvedPageProps } : { ...sharedProps };
3092
3143
  const intermediatePage = {
3093
3144
  component: visit.component,
@@ -3129,7 +3180,7 @@ var Router = class {
3129
3180
  options.method = options.method ?? urlMethodPair.method;
3130
3181
  }
3131
3182
  const defaultVisitOptionsCallback = config.get("visitOptions");
3132
- const configuredOptions = defaultVisitOptionsCallback ? defaultVisitOptionsCallback(href.toString(), cloneDeep3(options)) || {} : {};
3183
+ const configuredOptions = defaultVisitOptionsCallback ? defaultVisitOptionsCallback(href.toString(), cloneDeep4(options)) || {} : {};
3133
3184
  const mergedOptions = {
3134
3185
  method: "get",
3135
3186
  data: {},
@@ -3196,21 +3247,25 @@ var Router = class {
3196
3247
  }
3197
3248
  applyOptimisticUpdate(optimistic, events) {
3198
3249
  const currentProps = page.get().props;
3199
- const optimisticProps = optimistic(cloneDeep3(currentProps));
3250
+ const optimisticProps = optimistic(cloneDeep4(currentProps));
3200
3251
  if (!optimisticProps) {
3201
3252
  return;
3202
3253
  }
3203
- const propsSnapshot = {};
3254
+ const changedKeys = [];
3204
3255
  for (const key of Object.keys(optimisticProps)) {
3205
3256
  if (!isEqual3(currentProps[key], optimisticProps[key])) {
3206
- propsSnapshot[key] = cloneDeep3(currentProps[key]);
3257
+ changedKeys.push(key);
3207
3258
  }
3208
3259
  }
3209
- if (Object.keys(propsSnapshot).length === 0) {
3260
+ if (changedKeys.length === 0) {
3210
3261
  return;
3211
3262
  }
3212
- const updatedAt = Date.now();
3213
- page.recordOptimisticUpdate(Object.keys(propsSnapshot), updatedAt);
3263
+ const id = page.nextOptimisticId();
3264
+ const component = page.get().component;
3265
+ for (const key of changedKeys) {
3266
+ page.setBaseline(key, cloneDeep4(currentProps[key]));
3267
+ }
3268
+ page.registerOptimistic(id, optimistic);
3214
3269
  page.setPropsQuietly({ ...currentProps, ...optimisticProps });
3215
3270
  let shouldRestore = true;
3216
3271
  const originalOnSuccess = events.onSuccess;
@@ -3220,17 +3275,16 @@ var Router = class {
3220
3275
  };
3221
3276
  const originalOnFinish = events.onFinish;
3222
3277
  events.onFinish = (visit) => {
3223
- if (shouldRestore) {
3224
- const propsToRestore = {};
3225
- for (const [key, value] of Object.entries(propsSnapshot)) {
3226
- if (!page.shouldPreserveOptimistic(key, updatedAt)) {
3227
- propsToRestore[key] = value;
3228
- }
3229
- }
3230
- if (Object.keys(propsToRestore).length > 0) {
3231
- page.setPropsQuietly({ ...page.get().props, ...propsToRestore });
3278
+ page.unregisterOptimistic(id);
3279
+ if (shouldRestore && page.get().component === component) {
3280
+ const replayedProps = page.replayOptimistics();
3281
+ if (Object.keys(replayedProps).length > 0) {
3282
+ page.setPropsQuietly({ ...page.get().props, ...replayedProps });
3232
3283
  }
3233
3284
  }
3285
+ if (page.pendingOptimisticCount() === 0) {
3286
+ page.clearOptimisticState();
3287
+ }
3234
3288
  return originalOnFinish(visit);
3235
3289
  };
3236
3290
  }
@@ -3354,7 +3408,6 @@ var UseFormUtils = class {
3354
3408
  };
3355
3409
 
3356
3410
  // src/axiosHttpClient.ts
3357
- import axios from "axios";
3358
3411
  function normalizeHeaders(headers) {
3359
3412
  if (!headers || typeof headers !== "object") {
3360
3413
  return {};
@@ -3377,15 +3430,22 @@ function toHttpProgressEvent(axiosEvent) {
3377
3430
  total: axiosEvent.total
3378
3431
  };
3379
3432
  }
3433
+ var axiosModulePromise;
3434
+ function loadAxiosModule() {
3435
+ if (!axiosModulePromise) {
3436
+ axiosModulePromise = import("axios").catch((error) => {
3437
+ axiosModulePromise = void 0;
3438
+ throw error;
3439
+ });
3440
+ }
3441
+ return axiosModulePromise;
3442
+ }
3380
3443
  var AxiosHttpClient = class {
3381
3444
  constructor(instance) {
3382
- this.axios = instance;
3445
+ this.axiosInstance = instance ? Promise.resolve(instance) : loadAxiosModule().then((module) => module.default);
3383
3446
  }
3384
3447
  async getAxios() {
3385
- if (!this.axios) {
3386
- return this.axios = axios;
3387
- }
3388
- return this.axios;
3448
+ return this.axiosInstance;
3389
3449
  }
3390
3450
  async request(config2) {
3391
3451
  const processedConfig = await httpHandlers.processRequest(config2);
@@ -3400,9 +3460,9 @@ var AxiosHttpClient = class {
3400
3460
  }
3401
3461
  }
3402
3462
  async doRequest(config2) {
3403
- const axios2 = await this.getAxios();
3463
+ const axios = await this.getAxios();
3404
3464
  try {
3405
- const response = await axios2({
3465
+ const response = await axios({
3406
3466
  method: config2.method,
3407
3467
  url: config2.url,
3408
3468
  data: config2.data,
@@ -3418,7 +3478,7 @@ var AxiosHttpClient = class {
3418
3478
  headers: normalizeHeaders(response.headers)
3419
3479
  };
3420
3480
  } catch (error) {
3421
- const axiosModule = await import("axios");
3481
+ const axiosModule = await loadAxiosModule();
3422
3482
  if (axiosModule.default.isCancel(error)) {
3423
3483
  throw new HttpCancelledError("Request was cancelled", config2.url);
3424
3484
  }