@orieljs/framework 0.1.0-alpha.6 → 0.1.0-alpha.7

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.
Files changed (86) hide show
  1. package/NOTICE +4 -0
  2. package/README.md +10 -1
  3. package/TRADEMARKS.md +33 -0
  4. package/dist/{chunk-ZOEPKBVF.js → chunk-4MWG3B7G.js} +1347 -428
  5. package/dist/chunk-4MWG3B7G.js.map +1 -0
  6. package/dist/{chunk-POEP4B2M.js → chunk-7ZQZYDOC.js} +745 -105
  7. package/dist/chunk-7ZQZYDOC.js.map +1 -0
  8. package/dist/{chunk-I63ZFMX6.js → chunk-GVNLZZTN.js} +1 -1
  9. package/dist/chunk-GVNLZZTN.js.map +1 -0
  10. package/dist/{chunk-MFTZQMZM.js → chunk-VOYW3R5J.js} +4 -4
  11. package/dist/chunk-VOYW3R5J.js.map +1 -0
  12. package/dist/contracts.d.ts +515 -17
  13. package/dist/contracts.js +1 -1
  14. package/dist/index.d-WQpfdIbG.d.ts +630 -0
  15. package/dist/index.d.ts +964 -152
  16. package/dist/index.js +4279 -866
  17. package/dist/index.js.map +1 -1
  18. package/dist/{jsx-runtime-CBZQYYDS.d.ts → jsx-runtime-6um4Mwfb.d.ts} +96 -5
  19. package/dist/jsx-runtime.d.ts +2 -2
  20. package/dist/jsx-runtime.js +3 -3
  21. package/dist/{testing-BM481Hdz.d.ts → testing-CKwfWJGn.d.ts} +180 -15
  22. package/dist/testing.d.ts +2 -2
  23. package/dist/testing.js +3 -3
  24. package/docs/authentication.md +487 -0
  25. package/docs/authorization.md +435 -0
  26. package/docs/cache.md +647 -0
  27. package/docs/collections.md +2270 -0
  28. package/docs/configuration.md +334 -0
  29. package/docs/console.md +651 -0
  30. package/docs/container.md +430 -0
  31. package/docs/controllers.md +406 -0
  32. package/docs/csrf.md +126 -0
  33. package/docs/database-testing.md +144 -0
  34. package/docs/database.md +236 -0
  35. package/docs/deployment.md +276 -0
  36. package/docs/eloquent-collections.md +218 -0
  37. package/docs/eloquent-factories.md +255 -0
  38. package/docs/eloquent-mutators.md +254 -0
  39. package/docs/eloquent-observers.md +145 -0
  40. package/docs/eloquent-relationships.md +557 -0
  41. package/docs/eloquent.md +494 -0
  42. package/docs/encryption.md +104 -0
  43. package/docs/errors.md +318 -0
  44. package/docs/events.md +336 -0
  45. package/docs/facades.md +278 -0
  46. package/docs/hashing.md +118 -0
  47. package/docs/helpers.md +1281 -0
  48. package/docs/http-tests.md +386 -0
  49. package/docs/inertia.md +485 -0
  50. package/docs/installation.md +209 -0
  51. package/docs/lifecycle.md +234 -0
  52. package/docs/live-tests.md +226 -0
  53. package/docs/live.md +910 -0
  54. package/docs/logging.md +255 -0
  55. package/docs/mail.md +619 -0
  56. package/docs/middleware.md +384 -0
  57. package/docs/migrations.md +416 -0
  58. package/docs/mocking.md +264 -0
  59. package/docs/navigation.json +273 -0
  60. package/docs/notifications.md +225 -0
  61. package/docs/pagination.md +247 -0
  62. package/docs/passwords.md +207 -0
  63. package/docs/providers.md +187 -0
  64. package/docs/queries.md +600 -0
  65. package/docs/queues.md +330 -0
  66. package/docs/requests.md +533 -0
  67. package/docs/responses.md +444 -0
  68. package/docs/routing.md +738 -0
  69. package/docs/scheduling.md +277 -0
  70. package/docs/seeding.md +122 -0
  71. package/docs/session.md +409 -0
  72. package/docs/starter-kits.md +396 -0
  73. package/docs/storage.md +192 -0
  74. package/docs/structure.md +264 -0
  75. package/docs/testing.md +165 -0
  76. package/docs/time-travel.md +138 -0
  77. package/docs/validation.md +1792 -0
  78. package/docs/verification.md +152 -0
  79. package/docs/views.md +566 -0
  80. package/docs/vite.md +322 -0
  81. package/package.json +34 -32
  82. package/dist/chunk-I63ZFMX6.js.map +0 -1
  83. package/dist/chunk-MFTZQMZM.js.map +0 -1
  84. package/dist/chunk-POEP4B2M.js.map +0 -1
  85. package/dist/chunk-ZOEPKBVF.js.map +0 -1
  86. package/dist/index.d-BJyJx6U1.d.ts +0 -319
@@ -1,5 +1,5 @@
1
1
  import { Htmlable, OrielError, ErrorKind, View as View$1, ViewFactory } from './contracts.js';
2
- import { F as Facade, S as ServiceProvider } from './index.d-BJyJx6U1.js';
2
+ import { F as Facade, S as ServiceProvider } from './index.d-WQpfdIbG.js';
3
3
 
4
4
  /** Marks the objects jsx() returns (Symbol.for, so two copies of the package agree). */
5
5
  declare const ELEMENT: unique symbol;
@@ -52,6 +52,93 @@ declare function renderToString(node: Renderable): Promise<string>;
52
52
  /** Renders to a UTF-8 byte stream, sending everything rendered so far each time rendering waits on a promise. */
53
53
  declare function renderToStream(node: Renderable): ReadableStream<Uint8Array>;
54
54
 
55
+ /**
56
+ * The `o:` attributes of Live components, typed for TSX: a directive (`o:model`, `o:loading`, …) or an action on a DOM
57
+ * event (`o:click="save"`), with modifiers joined by `-` (`o:model-live`, `o:keydown-enter`). An `o:` name that is
58
+ * neither doesn't compile (`o:clik`, `o:modle`), and the forms listed here are completed by editors and have their
59
+ * values checked. TypeScript doesn't check JSX attribute names that contain a `-` unless the type lists them, so a
60
+ * form that isn't listed (a duration such as `o:model-live-debounce-500ms`, an event's modifiers) is accepted as
61
+ * written, and so is a misspelt one (`o:model-lvie`).
62
+ */
63
+ type ModelTrigger = 'live' | 'blur' | 'change' | 'lazy';
64
+ type ElementChange = 'remove' | 'class' | 'class-remove' | 'attr';
65
+ /**
66
+ * The directives that aren't DOM events, by name: the value each takes (`boolean` for one that can be written bare,
67
+ * `<a o:navigate>`, or from an expression, `o:navigate={external}`: `false` leaves it out) and its modifier forms, the
68
+ * `-`-joined text after the name (`never` for none). A new directive adds a member here, and its name to the Live
69
+ * client's reserved directives.
70
+ */
71
+ interface LiveDirectives {
72
+ /** o:model="title": binds an input to a public property, sent with the next request unless live, blur, change or lazy. */
73
+ model: {
74
+ value: string;
75
+ modifiers: ModelTrigger | 'number' | 'debounce' | 'live-debounce' | `${ModelTrigger}-number`;
76
+ };
77
+ /** o:loading: shown (or changed) while the component's request runs. */
78
+ loading: {
79
+ value: boolean | string;
80
+ modifiers: ElementChange | 'delay' | `delay-${ElementChange}`;
81
+ };
82
+ /** o:target="save,title": the actions or properties o:loading waits for. */
83
+ target: {
84
+ value: string;
85
+ modifiers: never;
86
+ };
87
+ /** o:poll="refresh": calls the method ($refresh without one) every 2.5 s, or every `o:poll-<n>s`. */
88
+ poll: {
89
+ value: boolean | string;
90
+ modifiers: 'keep-alive' | 'visible';
91
+ };
92
+ /** o:navigate on a link: fetches the page and swaps it in; `-hover` prefetches on hover. */
93
+ navigate: {
94
+ value: boolean;
95
+ modifiers: 'hover';
96
+ };
97
+ /** o:offline: shown (or changed) while the browser is offline. */
98
+ offline: {
99
+ value: boolean | string;
100
+ modifiers: ElementChange;
101
+ };
102
+ /** o:key: keeps an element's identity across re-renders. */
103
+ key: {
104
+ value: string | number;
105
+ modifiers: never;
106
+ };
107
+ /** o:confirm="Delete this tag?": asks before the element's action runs; `-prompt` asks for a typed answer. */
108
+ confirm: {
109
+ value: boolean | string;
110
+ modifiers: 'prompt';
111
+ };
112
+ /** o:announce on a status region: an action that leaves the same message announces it again. */
113
+ announce: {
114
+ value: boolean;
115
+ modifiers: never;
116
+ };
117
+ }
118
+ /**
119
+ * The DOM events `o:<event>` runs an action on. A name with a `-` can't be written in TSX (modifiers are `-`
120
+ * segments), and `offline` is the o:offline directive, not the event. An event this list doesn't have (a custom
121
+ * event a component dispatches) is spread: `<div {...{ 'o:saved': 'refresh' }} />`.
122
+ */
123
+ type LiveEvent = 'click' | 'dblclick' | 'auxclick' | 'contextmenu' | 'mousedown' | 'mouseup' | 'mousemove' | 'mouseover' | 'mouseout' | 'mouseenter' | 'mouseleave' | 'wheel' | 'pointerdown' | 'pointerup' | 'pointermove' | 'pointerover' | 'pointerout' | 'pointerenter' | 'pointerleave' | 'pointercancel' | 'gotpointercapture' | 'lostpointercapture' | 'keydown' | 'keyup' | 'keypress' | 'input' | 'beforeinput' | 'change' | 'submit' | 'reset' | 'invalid' | 'select' | 'formdata' | 'search' | 'focus' | 'blur' | 'focusin' | 'focusout' | 'copy' | 'cut' | 'paste' | 'drag' | 'dragstart' | 'dragend' | 'dragenter' | 'dragleave' | 'dragover' | 'drop' | 'touchstart' | 'touchend' | 'touchmove' | 'touchcancel' | 'compositionstart' | 'compositionupdate' | 'compositionend' | 'play' | 'pause' | 'playing' | 'ended' | 'timeupdate' | 'volumechange' | 'ratechange' | 'durationchange' | 'loadstart' | 'loadeddata' | 'loadedmetadata' | 'canplay' | 'canplaythrough' | 'seeking' | 'seeked' | 'waiting' | 'stalled' | 'suspend' | 'emptied' | 'progress' | 'abort' | 'error' | 'load' | 'animationstart' | 'animationend' | 'animationiteration' | 'animationcancel' | 'transitionstart' | 'transitionend' | 'transitionrun' | 'transitioncancel' | 'scroll' | 'scrollend' | 'resize' | 'toggle' | 'beforetoggle' | 'close' | 'cancel' | 'online' | 'popstate' | 'hashchange' | 'beforeunload' | 'pagehide' | 'pageshow' | 'storage' | 'message' | 'visibilitychange' | 'selectionchange' | 'fullscreenchange' | 'slotchange' | 'cuechange';
124
+ /** `o:model`, `o:model-live`, …: each directive and each of its modifier forms, with the directive's value. */
125
+ type LiveDirectiveAttributes = {
126
+ [N in keyof LiveDirectives as `o:${N}` | `o:${N}-${LiveDirectives[N]['modifiers']}`]?: LiveDirectives[N]['value'];
127
+ };
128
+ /** `o:click="save"`: an action (a method, `method(args)`, `$refresh`, `$set(…)`, `$dispatch(…)`) on a DOM event. */
129
+ type LiveEventAttributes = {
130
+ [E in LiveEvent as `o:${E}`]?: string;
131
+ };
132
+ type Letter = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z';
133
+ type Digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
134
+ /**
135
+ * Every other attribute, with any value: each name that doesn't start with `o:` (`o`, `href`, `onclick`, `open`,
136
+ * `xlink:href`, `viewBox`; names with a `-`, such as `data-*`, `aria-*` and `hx-post`, are never checked).
137
+ */
138
+ type OtherAttributes = {
139
+ [K in 'o' | `${Exclude<Letter, 'o'> | Uppercase<Letter> | '_' | '$'}${string}` | `o${Letter | Uppercase<Letter> | Digit | '_' | '.' | '$'}${string}`]?: unknown;
140
+ };
141
+
55
142
  /**
56
143
  * The automatic JSX runtime (`jsxImportSource: "@orieljs/view"`). jsx() only describes elements; rendering
57
144
  * (escaping, async components) happens in renderToString()/renderToStream().
@@ -60,8 +147,13 @@ declare function renderToStream(node: Renderable): ReadableStream<Uint8Array>;
60
147
  declare function jsx(type: ElementType, props: Props | null, key?: string | number): OrielElement;
61
148
  /** Same as jsx(); the compiler uses it when there are several static children. */
62
149
  declare const jsxs: typeof jsx;
63
- /** Attributes every intrinsic element accepts. Unknown attributes (hx-*, x-*, o:click, …) are allowed. */
64
- interface HtmlAttributes {
150
+ /**
151
+ * Attributes every intrinsic element accepts. Any attribute is allowed (hx-*, x-*, data-*, …) except an `o:` name
152
+ * that isn't a Live directive or `o:<event>` (directives.ts), so a typo such as `o:clik` doesn't compile. An `o:` form
153
+ * with a `-` that the type doesn't list compiles unchecked (TypeScript doesn't check a hyphenated JSX name the type
154
+ * leaves out), and a custom event name is spread: `<div {...{ 'o:saved': 'refresh' }} />`.
155
+ */
156
+ interface HtmlAttributes extends OtherAttributes, LiveDirectiveAttributes, LiveEventAttributes {
65
157
  children?: Renderable;
66
158
  class?: ClassValue;
67
159
  className?: ClassValue;
@@ -69,7 +161,6 @@ interface HtmlAttributes {
69
161
  dangerouslySetInnerHTML?: {
70
162
  __html: string;
71
163
  };
72
- [attribute: string]: unknown;
73
164
  }
74
165
  declare namespace JSX {
75
166
  type Element = OrielElement;
@@ -206,4 +297,4 @@ declare class ViewServiceProvider extends ServiceProvider {
206
297
  register(): void;
207
298
  }
208
299
 
209
- export { type ClassValue as C, ELEMENT as E, FileViewFinder as F, type HtmlAttributes as H, InvalidViewError as I, JSX as J, type OrielElement as O, type Props as P, type Renderable as R, type StyleObject as S, TsxView as T, View as V, Fragment as a, HtmlString as b, type Component as c, type ViewEnvironment as d, Factory as e, ViewNotFoundError as f, ViewRenderError as g, ViewServiceProvider as h, classNames as i, createElement as j, csrfField as k, e as l, isElement as m, isHtmlable as n, methodField as o, renderToStream as p, renderToString as q, raw as r, styleString as s, jsx as t, jsxs as u, view as v };
300
+ export { type ClassValue as C, ELEMENT as E, FileViewFinder as F, type HtmlAttributes as H, InvalidViewError as I, JSX as J, type LiveDirectives as L, type OrielElement as O, type Props as P, type Renderable as R, type StyleObject as S, TsxView as T, View as V, Fragment as a, HtmlString as b, type LiveEvent as c, type Component as d, type ViewEnvironment as e, Factory as f, ViewNotFoundError as g, ViewRenderError as h, ViewServiceProvider as i, classNames as j, createElement as k, csrfField as l, e as m, isElement as n, isHtmlable as o, methodField as p, renderToStream as q, raw as r, renderToString as s, styleString as t, jsx as u, view as v, jsxs as w };
@@ -1,3 +1,3 @@
1
- export { a as Fragment, H as HtmlAttributes, J as JSX, t as jsx, u as jsxs } from './jsx-runtime-CBZQYYDS.js';
1
+ export { a as Fragment, H as HtmlAttributes, J as JSX, u as jsx, w as jsxs } from './jsx-runtime-6um4Mwfb.js';
2
2
  import './contracts.js';
3
- import './index.d-BJyJx6U1.js';
3
+ import './index.d-WQpfdIbG.js';
@@ -2,9 +2,9 @@ import {
2
2
  Fragment,
3
3
  jsx,
4
4
  jsxs
5
- } from "./chunk-MFTZQMZM.js";
6
- import "./chunk-POEP4B2M.js";
7
- import "./chunk-I63ZFMX6.js";
5
+ } from "./chunk-VOYW3R5J.js";
6
+ import "./chunk-7ZQZYDOC.js";
7
+ import "./chunk-GVNLZZTN.js";
8
8
  export {
9
9
  Fragment,
10
10
  jsx,
@@ -1,5 +1,5 @@
1
- import { BusDispatcher, Job, PendingBatchOptions, Class, PendingChain, PendingBatch, Batch, EventDispatcher, Listener, MailManager, Mailable, Address, MailRecipient, Mailer, PendingMail, SentMessage, MailTransport, NotificationDispatcher, Notifiable, Notification, NotificationChannel, QueueManager, QueuePayload, Queue, QueueJob, FilesystemManager, Filesystem, PutOptions, UploadedFile, Application, Session, View, Authenticatable, Container, AuthFactory, InertiaPage, ServiceProvider, ServiceProviderClass, DatabaseManager, ModelInstance, Row, Encrypter, Token, ExceptionHandler, ViewFactory, Rules, MessageBag, LiveSnapshot, LiveEffects, OrielError, ErrorKind, Htmlable, LiveManager, HttpRequest, LiveUpdateRequest, LiveUpdateResponse, MiddlewareClass, Router } from './contracts.js';
2
- import { S as ServiceProvider$1 } from './index.d-BJyJx6U1.js';
1
+ import { BusDispatcher, Job, PendingBatchOptions, Class, PendingChain, PendingBatch, Batch, EventDispatcher, Listener, MailManager, Mailable, Address, MailRecipient, Mailer, PendingMail, SentMessage, MailTransport, NotificationDispatcher, Notifiable, Notification, NotificationChannel, QueueManager, QueuePayload, Queue, QueueJob, FilesystemManager, Filesystem, PutOptions, UploadedFile, Application, Session, View, Authenticatable, Container, AuthFactory, InertiaPage, ServiceProvider, ServiceProviderClass, DatabaseManager, ModelInstance, Row, Encrypter, Token, ExceptionHandler, ViewFactory, RouteName, RouteArguments, Rules, InferValidatedType, MessageBag, LiveSnapshot, LiveEffects, OrielError, ErrorKind, Htmlable, LiveManager, HttpRequest, LiveUpdateRequest, LiveUpdateResponse, MiddlewareClass, Router } from './contracts.js';
2
+ import { S as ServiceProvider$1 } from './index.d-WQpfdIbG.js';
3
3
 
4
4
  /** A date the tests travel to: a Date, an ISO string or milliseconds since the epoch. */
5
5
  type TravelDate = Date | string | number;
@@ -417,6 +417,11 @@ declare class HttpClient {
417
417
  defaultGuard: string | undefined;
418
418
  /** Session attributes carried from one request to the next (Laravel keeps one session store per test). */
419
419
  session: Record<string, unknown> | undefined;
420
+ /**
421
+ * withSession() and flushSession() since the last started session: applied to the stored session (the one the
422
+ * session cookie points to) once the next request starts it, so they win over what it holds, as in Laravel.
423
+ */
424
+ sessionChanges: Array<(session: Session) => void>;
420
425
  /** from(url): the session's previous URL for the next request only (Laravel sets it once). */
421
426
  previousUrl: string | undefined;
422
427
  /** Requests whose actingAs users reached the guards (the AuthFactory they went through). */
@@ -442,6 +447,10 @@ declare class HttpClient {
442
447
  * request sticks. Reads each actingAs guard back and forgets or replaces its user to match.
443
448
  */
444
449
  protected syncActingAs(auth: AuthFactory): Promise<void>;
450
+ /** Applies the pending withSession()/flushSession() changes once the session has loaded what it stored. */
451
+ protected applyOnStart(session: Session): void;
452
+ /** Applies the pending withSession()/flushSession() changes to the session, once. */
453
+ protected applyPending(session: Session): void;
445
454
  /** The request's (scoped) Session, created now so the carried attributes are in place before StartSession. */
446
455
  protected scopeSession(scope: Container): Session | undefined;
447
456
  buildRequest(method: string, uri: string, options: RequestOptions): Request;
@@ -538,9 +547,9 @@ declare abstract class MakesHttpRequests extends InteractsWithApplication {
538
547
  followingRedirects(): this;
539
548
  /** Sets the Referer and the session's previous URL, so redirect()->back() goes there. */
540
549
  from(url: string): this;
541
- /** Puts data in the session for the following requests (Laravel's withSession()). */
550
+ /** Puts data in the session for the following requests, over what the stored session holds (Laravel's withSession()). */
542
551
  withSession(data: Record<string, unknown>): this;
543
- /** Empties the session carried between requests. */
552
+ /** Empties the session, the stored one included, so the next request starts with none (Laravel's flushSession()). */
544
553
  flushSession(): this;
545
554
  /** Every following request is authenticated as `user` on `guard` (which also becomes the default guard). */
546
555
  actingAs(user: Authenticatable, guard?: string): this;
@@ -1082,8 +1091,11 @@ interface QueuedDispatch {
1082
1091
  }
1083
1092
  /** The validation errors of a component (Laravel's MessageBag), for render(): `this.errors.first('title')`. */
1084
1093
  declare class ErrorBag implements MessageBag {
1094
+ #private;
1085
1095
  private readonly messages;
1086
1096
  constructor(messages: Record<string, string[]>);
1097
+ /** Adds to the component's errors, as addError() does. */
1098
+ add(key: string, message: string): void;
1087
1099
  has(key: string): boolean;
1088
1100
  first(key?: string): string | undefined;
1089
1101
  get(key: string): string[];
@@ -1114,6 +1126,13 @@ declare abstract class Component {
1114
1126
  static layout?: string;
1115
1127
  /** The page title passed to the layout as `title`. */
1116
1128
  static title?: string;
1129
+ /**
1130
+ * Livewire's #[Lazy]: every embed (and the full page) renders the placeholder first and mounts once the browser shows
1131
+ * it. `<Live component={…} lazy={false} />` mounts one at once. The placeholder is the component's
1132
+ * `placeholder(params)` method (TSX), else the `live.lazy_placeholder` view, else an empty `<div>`: give it the root
1133
+ * element the component renders.
1134
+ */
1135
+ static lazy?: boolean;
1117
1136
  /** Static fallbacks for runtimes without decorators: { event: 'method' }, locked names, computed getter names. */
1118
1137
  static listeners?: Record<string, string>;
1119
1138
  static locked?: string[];
@@ -1127,14 +1146,19 @@ declare abstract class Component {
1127
1146
  redirect(url: string, options?: {
1128
1147
  navigate?: boolean;
1129
1148
  }): void;
1130
- redirectRoute(name: string, parameters?: unknown, options?: {
1149
+ /**
1150
+ * redirect() to a named route: `this.redirectRoute('posts.show', post, { navigate: true })`. Once `oriel
1151
+ * route:types` has run, the name and the route's parameters are checked, as route()'s are.
1152
+ */
1153
+ redirectRoute<N extends RouteName>(name: N, ...args: RouteArguments<N, [options?: {
1131
1154
  navigate?: boolean;
1132
- }): void;
1155
+ }]>): void;
1133
1156
  /**
1134
- * Validates the public state. On success clears the error bag and returns the validated data; on failure fills the
1135
- * error bag and throws (the rest of the action is skipped and the component re-renders with `errors`).
1157
+ * Validates the public state. On success clears the error bag and returns the validated data, typed from the rules
1158
+ * (`await this.validate({ title: 'required|string' })` is `{ title: string }`); on failure fills the error bag and
1159
+ * throws (the rest of the action is skipped and the component re-renders with `errors`).
1136
1160
  */
1137
- validate<T = Record<string, unknown>>(rules: Rules, messages?: Record<string, string>, attributes?: Record<string, string>): Promise<T>;
1161
+ validate<const R extends Rules>(rules: R, messages?: Record<string, string>, attributes?: Record<string, string>): Promise<InferValidatedType<R>>;
1138
1162
  addError(key: string, message: string): void;
1139
1163
  /** Clears every error, or only those of `keys`. */
1140
1164
  resetErrorBag(...keys: string[]): void;
@@ -1178,7 +1202,10 @@ declare class Testable<C extends Component = Component> {
1178
1202
  private readonly manager;
1179
1203
  private readonly scope;
1180
1204
  private constructor();
1181
- /** Mounts `component` with `params`, as `<Live component={…} {...params} />` would. */
1205
+ /**
1206
+ * Mounts `component` with `params`, as `<Live component={…} {...params} />` would. A lazy component mounts at once
1207
+ * (Livewire's withoutLazyLoading()); `{ lazy: true }` renders its placeholder, and `call('__lazyLoad', …)` loads it.
1208
+ */
1182
1209
  static create<C extends Component>(component: Class<C> | string, params?: Record<string, unknown>): Promise<Testable<C>>;
1183
1210
  /** The component instance after the last request. */
1184
1211
  instance(): C;
@@ -1188,7 +1215,14 @@ declare class Testable<C extends Component = Component> {
1188
1215
  html(): string;
1189
1216
  /** The effects of the last request. */
1190
1217
  effects(): LiveEffects;
1218
+ /**
1219
+ * Sets public properties through an update. A file (a FakeFile) or an array of files is uploaded as `o:model` on a
1220
+ * file input does it: the upload rules, the temporary disk, then a TemporaryUploadedFile (or an array) in the
1221
+ * property, or the upload's errors on it (Livewire's).
1222
+ */
1191
1223
  set(path: string | Record<string, unknown>, value?: unknown): Promise<this>;
1224
+ /** Uploads `files` into the property `name` (an array when `multiple`), as the browser's upload calls do. */
1225
+ upload(name: string, files: readonly Blob[], multiple?: boolean): Promise<this>;
1192
1226
  call(method: string, ...params: unknown[]): Promise<this>;
1193
1227
  toggle(path: string): Promise<this>;
1194
1228
  /** Dispatches an event to this component, as the browser does for its listeners. */
@@ -1221,6 +1255,11 @@ interface LiveProps {
1221
1255
  component: Class<Component> | string;
1222
1256
  /** Identifies a child inside its parent across re-renders (Livewire's :key / wire:key). */
1223
1257
  'o:key'?: string | number;
1258
+ /**
1259
+ * Renders the placeholder and mounts the component once it scrolls into view (`'on-load'`: once the page starts);
1260
+ * `false` mounts a `static lazy` component at once.
1261
+ */
1262
+ lazy?: boolean | 'on-load';
1224
1263
  [param: string]: unknown;
1225
1264
  }
1226
1265
  /** Blade's @livewire('counter', ['count' => 3], key('c1')): the component's first render, as trusted HTML. */
@@ -1263,10 +1302,25 @@ declare class LiveComponentManager implements LiveManager {
1263
1302
  isLiveRequest(request: HttpRequest): boolean;
1264
1303
  /** The first render: HTML with o:id, o:snapshot and o:effects on the root element. */
1265
1304
  mount(component: string | Class<unknown>, params?: Record<string, unknown>, key?: string): Promise<string>;
1266
- mountComponent(component: string | Class<unknown>, params?: Record<string, unknown>, existing?: Component): Promise<ComponentResult>;
1305
+ /**
1306
+ * Mounts a component: boot(), the params into its properties, mount(params), then its first render. A lazy one
1307
+ * (`lazy` in the params, or `static lazy`) renders its placeholder instead and mounts when the browser loads it.
1308
+ */
1309
+ mountComponent(component: string | Class<unknown>, embedParams?: Record<string, unknown>, existing?: Component): Promise<ComponentResult>;
1310
+ /**
1311
+ * A lazy component's first render (Livewire's): its placeholder, with the state it has before mount() and the mount
1312
+ * params signed for the `__lazyLoad` call the browser makes when it shows it (`o:lazy`, or `o:lazy-on-load`).
1313
+ */
1314
+ private mountPlaceholder;
1267
1315
  /** Applies each component's updates and calls, re-renders it and returns its new snapshot and effects. */
1268
1316
  update(request: LiveUpdateRequest): Promise<LiveUpdateResponse>;
1269
1317
  updateComponent(snapshotJson: string, updates: Record<string, unknown>, calls: Call[]): Promise<ComponentResult>;
1318
+ /**
1319
+ * The mount params and placeholder tag of a `__lazyLoad` request, or undefined for any other update. The load comes
1320
+ * alone (no updates, no other call: the browser sends it in a request of its own) and its payload must be the one
1321
+ * signed for this component: anything else is refused as corrupt (a 403) before the component boots.
1322
+ */
1323
+ private lazyLoad;
1270
1324
  /**
1271
1325
  * The route action of POST /oriel/live/update. Each component's update runs behind the persistent middleware of the
1272
1326
  * route that rendered its page (Livewire's): `auth`, `verified`, `guest` and `can`, with the page route's parameters
@@ -1285,7 +1339,7 @@ declare class LiveComponentManager implements LiveManager {
1285
1339
  /** Makes every computed getter (static `computed` too) cache its value for the rest of the request. */
1286
1340
  private prepareComputed;
1287
1341
  private applyUpdate;
1288
- /** Runs one call from the browser: a magic action, an event, or a public method. Returns its return value. */
1342
+ /** Runs one call from the browser: a magic action, an event, an upload call, or a public method. Returns its return value. */
1289
1343
  private call;
1290
1344
  /**
1291
1345
  * Renders the component (rendering/rendered hooks, nested children tracked) and checks for a single root. A
@@ -1305,8 +1359,9 @@ declare class LiveComponentManager implements LiveManager {
1305
1359
  declare const UPDATE_URI = "/oriel/live/update";
1306
1360
  /**
1307
1361
  * Binds the LiveManager and the PaginationState that WithPagination components answer, merges the `live` config,
1308
- * registers POST /oriel/live/update (named `live.update`, in the `web` group: sessions and CSRF apply), the make:live
1309
- * command, and the components under app/Live.
1362
+ * registers POST /oriel/live/update (named `live.update`, in the `web` group: sessions and CSRF apply), the upload and
1363
+ * preview routes of WithFileUploads (`live.upload-file`, `live.preview-file`), the make:live command, and the
1364
+ * components under app/Live.
1310
1365
  */
1311
1366
  declare class LiveServiceProvider extends ServiceProvider$1 {
1312
1367
  register(): void;
@@ -1356,6 +1411,108 @@ declare class InvalidLiveRequestError extends LiveError {
1356
1411
  readonly kind: ErrorKind;
1357
1412
  readonly status: number;
1358
1413
  }
1414
+ /** An upload or preview URL whose signature is missing, wrong or expired (Livewire's 401). Nothing is read or stored. */
1415
+ declare class InvalidUploadSignatureError extends LiveError {
1416
+ readonly name: string;
1417
+ readonly kind: ErrorKind;
1418
+ readonly status: number;
1419
+ constructor();
1420
+ }
1421
+ /** A preview of a temporary upload that is no longer on the disk (cleaned up, or stored and deleted). */
1422
+ declare class TemporaryFileNotFoundError extends LiveError {
1423
+ readonly name: string;
1424
+ readonly kind: ErrorKind;
1425
+ readonly status: number;
1426
+ constructor(filename: string);
1427
+ }
1428
+ /** temporaryUrl() on an upload whose type has no preview (live.temporary_file_upload.preview_mimes). */
1429
+ declare class FileNotPreviewableError extends LiveError {
1430
+ readonly name: string;
1431
+ constructor(extension: string);
1432
+ }
1433
+ /** The errors an upload came back with (`_uploadErrored`): the component re-renders with them on the property. */
1434
+ declare class UploadValidationError extends LiveError {
1435
+ readonly errors: Record<string, string[]>;
1436
+ readonly name: string;
1437
+ readonly kind: ErrorKind;
1438
+ readonly status: number;
1439
+ readonly errorBag: string;
1440
+ constructor(errors: Record<string, string[]>);
1441
+ }
1442
+
1443
+ /**
1444
+ * Livewire's `temporary_file_upload` settings, read from config `live.temporary_file_upload.*` (each one falls back on
1445
+ * its own): the disk (the default filesystem disk), the directory on it, the rules every upload must pass, the upload
1446
+ * route's middleware, the types a preview is served for, how long an upload URL lasts (minutes), and whether a finished
1447
+ * upload removes the temporary files older than a day.
1448
+ */
1449
+ declare const TEMPORARY_UPLOAD_DEFAULTS: {
1450
+ disk: string | null;
1451
+ directory: string;
1452
+ rules: string | string[];
1453
+ middleware: string | string[];
1454
+ preview_mimes: string[];
1455
+ max_upload_time: number;
1456
+ cleanup: boolean;
1457
+ };
1458
+ /** What a temporary upload is: its stored name on the temporary disk and what the browser sent (signed with it). */
1459
+ interface TemporaryFileData {
1460
+ /** A random 40-character name with the extension its bytes showed: `live-tmp/<filename>` on the temporary disk. */
1461
+ filename: string;
1462
+ /** The name the browser gave the file. */
1463
+ name: string;
1464
+ size: number;
1465
+ /** The MIME type the browser claimed. */
1466
+ type: string;
1467
+ /** The extension of the upload's own type (its bytes, else a plain claimed extension), or ''. */
1468
+ extension: string;
1469
+ }
1470
+ /**
1471
+ * Livewire's TemporaryUploadedFile: a file the browser uploaded to the temporary directory before an action stores
1472
+ * it. A WithFileUploads component's property holds one (or an array of them) once `o:model` on a file input has
1473
+ * uploaded it: validate it like any upload (`'photo' => 'image|max:1024'`), preview it with `temporaryUrl()`, then
1474
+ * `store()` it. It travels in the component's snapshot as its data, signed with the rest.
1475
+ */
1476
+ declare class TemporaryUploadedFile implements UploadedFile {
1477
+ #private;
1478
+ readonly filename: string;
1479
+ readonly clientName: string;
1480
+ readonly mimeType: string;
1481
+ readonly size: number;
1482
+ constructor(data: TemporaryFileData);
1483
+ /** What the snapshot carries. */
1484
+ toData(): TemporaryFileData;
1485
+ /** The file's path on the temporary disk. */
1486
+ get path(): string;
1487
+ /** The extension of the upload's own type, as FormUploadedFile's extension(): what putFile() names a stored copy by. */
1488
+ extension(): string;
1489
+ /** The extension of the name the browser gave the file, lower-cased ('' without one). */
1490
+ clientExtension(): string;
1491
+ /** A random 40-character name with extension(), as FormUploadedFile's. */
1492
+ hashName(): string;
1493
+ arrayBuffer(): Promise<ArrayBuffer>;
1494
+ text(): Promise<string>;
1495
+ /** The file's bytes from the temporary disk, opened on the first read. */
1496
+ stream(): ReadableStream<Uint8Array>;
1497
+ /** Stores a copy under a random name in `directory`, on `disk` (by default the temporary disk, as Livewire's). */
1498
+ store(directory: string, disk?: string): Promise<string>;
1499
+ storeAs(directory: string, name: string, disk?: string): Promise<string>;
1500
+ exists(): Promise<boolean>;
1501
+ /** Removes the temporary file (a stored copy stays). */
1502
+ delete(): Promise<boolean>;
1503
+ /** Whether temporaryUrl() serves this file: its type is in `live.temporary_file_upload.preview_mimes`. */
1504
+ isPreviewable(): boolean;
1505
+ /**
1506
+ * A signed link to the file for `<img src>` or `<video src>` before it is stored. It lasts until the end of the hour
1507
+ * at least 30 minutes away (Livewire's), so a re-render keeps the same link and the browser doesn't reload it.
1508
+ */
1509
+ temporaryUrl(): string;
1510
+ }
1511
+
1512
+ /** Where the browser POSTs a WithFileUploads component's files (Livewire's /livewire/upload-file), named live.upload-file. */
1513
+ declare const UPLOAD_URI = "/oriel/live/upload-file";
1514
+ /** Where temporaryUrl() links lead (Livewire's /livewire/preview-file/{filename}), named live.preview-file. */
1515
+ declare const PREVIEW_URI = "/oriel/live/preview-file";
1359
1516
 
1360
1517
  /** The route middleware an update re-applies by default (config live.persistent_middleware), by alias. */
1361
1518
  declare const PERSISTENT_MIDDLEWARE: string[];
@@ -1391,6 +1548,14 @@ interface Paginated {
1391
1548
  */
1392
1549
  declare function WithPagination<TBase extends ComponentConstructor>(Base: TBase): TBase & (abstract new (...args: any[]) => Paginated);
1393
1550
 
1551
+ /**
1552
+ * Livewire's WithFileUploads: `class Profile extends WithFileUploads(Component)`. A file input with `o:model="photo"`
1553
+ * uploads the file to the temporary directory as soon as it is picked, then sets `photo` to a TemporaryUploadedFile
1554
+ * (`<input type="file" multiple>` sets an array), through `updatingPhoto()`/`updatedPhoto()` like any update. Validate
1555
+ * it with the file rules, preview it with `temporaryUrl()`, store it with `store()`.
1556
+ */
1557
+ declare function WithFileUploads<TBase extends ComponentConstructor>(Base: TBase): TBase;
1558
+
1394
1559
  /**
1395
1560
  * What <Pagination> reads from a paginator. Structural, since Live can't import Database: paginate()'s
1396
1561
  * LengthAwarePaginator (with lastPage(), so page buttons) and simplePaginate()'s Paginator (Previous and Next only).
@@ -1418,4 +1583,4 @@ interface PaginationProps {
1418
1583
  */
1419
1584
  declare function Pagination({ paginator, class: className }: PaginationProps): Htmlable;
1420
1585
 
1421
- export { InteractsWithDatabase as $, AnonymousNotifiable as A, BusFake as B, Component as C, type CountOrFilter as D, EventFake as E, DatabaseMigrations as F, type DatabaseTestOptions as G, DatabaseTransactions as H, InvalidLiveRequestError as I, type DispatchedEvent as J, type ExpectedErrors as K, Live as L, MailFake as M, NotificationFake as N, On as O, PERSISTENT_MIDDLEWARE as P, QueueFake as Q, type ExpectedListener as R, StorageFake as S, TestRequestScope as T, UPDATE_URI as U, FakeDisk as V, WithPagination as W, FakeFile as X, HttpClient as Y, InteractsWithApplication as Z, InteractsWithConsole as _, type ComponentResult as a, InteractsWithTime as a0, type JsonStructure as a1, MailRecord as a2, MakesHttpRequests as a3, PendingCommand as a4, type PushedJob as a5, RefreshDatabase as a6, RefreshDatabaseState as a7, type RequestData as a8, type RequestOptions as a9, matches as aA, nameOf as aB, recordingExceptionHandler as aC, recordingViewFactory as aD, responseCookies as aE, runCommand as aF, travel as aG, travelBack as aH, travelTo as aI, usingInMemoryDatabase as aJ, type ResponseContext as aa, type ResponseCookie as ab, type SentNotification as ac, TESTING_ENVIRONMENT as ad, type TableOrModel as ae, type Target as af, TestCase as ag, type TestHooks as ah, TestResponse as ai, type TestTrait as aj, type TravelDate as ak, Wormhole as al, actingAsAuthFactory as am, addresses as an, applyEnvironment as ao, cookieHeader as ap, cookiePrefix as aq, decryptCookie as ar, encryptCookie as as, flatten as at, freezeSecond as au, freezeTime as av, guessMimeType as aw, inertiaPageOf as ax, install as ay, isExpired as az, Computed as b, CorruptComponentPayloadError as c, ErrorBag as d, LiveComponentManager as e, LiveComponentNotFoundError as f, LiveError as g, type LiveProps as h, LiveServiceProvider as i, Locked as j, MethodNotCallableError as k, type Paginated as l, Pagination as m, type PaginationProps as n, type PaginationSource as o, PendingEvent as p, type PersistentMiddleware as q, PropertyNotUpdatableError as r, Testable as s, componentName as t, live as u, persistentMiddleware as v, AssertableInertia as w, AssertableJson as x, type BatchRecord as y, type BootOptions as z };
1586
+ export { type DatabaseTestOptions as $, UploadValidationError as A, BusFake as B, Component as C, WithPagination as D, EventFake as E, FileNotPreviewableError as F, componentName as G, live as H, InvalidLiveRequestError as I, persistentMiddleware as J, AnonymousNotifiable as K, Live as L, MailFake as M, NotificationFake as N, On as O, PERSISTENT_MIDDLEWARE as P, QueueFake as Q, AssertableInertia as R, StorageFake as S, TEMPORARY_UPLOAD_DEFAULTS as T, UPDATE_URI as U, AssertableJson as V, WithFileUploads as W, type BatchRecord as X, type BootOptions as Y, type CountOrFilter as Z, DatabaseMigrations as _, type ComponentResult as a, DatabaseTransactions as a0, type DispatchedEvent as a1, type ExpectedErrors as a2, type ExpectedListener as a3, FakeDisk as a4, FakeFile as a5, HttpClient as a6, InteractsWithApplication as a7, InteractsWithConsole as a8, InteractsWithDatabase as a9, cookiePrefix as aA, decryptCookie as aB, encryptCookie as aC, flatten as aD, freezeSecond as aE, freezeTime as aF, guessMimeType as aG, inertiaPageOf as aH, install as aI, isExpired as aJ, matches as aK, nameOf as aL, recordingExceptionHandler as aM, recordingViewFactory as aN, responseCookies as aO, runCommand as aP, travel as aQ, travelBack as aR, travelTo as aS, usingInMemoryDatabase as aT, InteractsWithTime as aa, type JsonStructure as ab, MailRecord as ac, MakesHttpRequests as ad, PendingCommand as ae, type PushedJob as af, RefreshDatabase as ag, RefreshDatabaseState as ah, type RequestData as ai, type RequestOptions as aj, type ResponseContext as ak, type ResponseCookie as al, type SentNotification as am, TESTING_ENVIRONMENT as an, type TableOrModel as ao, type Target as ap, TestCase as aq, type TestHooks as ar, TestResponse as as, type TestTrait as at, type TravelDate as au, Wormhole as av, actingAsAuthFactory as aw, addresses as ax, applyEnvironment as ay, cookieHeader as az, Computed as b, CorruptComponentPayloadError as c, ErrorBag as d, InvalidUploadSignatureError as e, LiveComponentManager as f, LiveComponentNotFoundError as g, LiveError as h, type LiveProps as i, LiveServiceProvider as j, Locked as k, MethodNotCallableError as l, PREVIEW_URI as m, type Paginated as n, Pagination as o, type PaginationProps as p, type PaginationSource as q, PendingEvent as r, type PersistentMiddleware as s, PropertyNotUpdatableError as t, type TemporaryFileData as u, TemporaryFileNotFoundError as v, TemporaryUploadedFile as w, TestRequestScope as x, Testable as y, UPLOAD_URI as z };
package/dist/testing.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { A as AnonymousNotifiable, w as AssertableInertia, x as AssertableJson, y as BatchRecord, z as BootOptions, B as BusFake, D as CountOrFilter, F as DatabaseMigrations, G as DatabaseTestOptions, H as DatabaseTransactions, J as DispatchedEvent, E as EventFake, K as ExpectedErrors, R as ExpectedListener, V as FakeDisk, X as FakeFile, Y as HttpClient, Z as InteractsWithApplication, _ as InteractsWithConsole, $ as InteractsWithDatabase, a0 as InteractsWithTime, a1 as JsonStructure, L as Live, M as MailFake, a2 as MailRecord, a3 as MakesHttpRequests, N as NotificationFake, a4 as PendingCommand, a5 as PushedJob, Q as QueueFake, a6 as RefreshDatabase, a7 as RefreshDatabaseState, a8 as RequestData, a9 as RequestOptions, aa as ResponseContext, ab as ResponseCookie, ac as SentNotification, S as StorageFake, ad as TESTING_ENVIRONMENT, ae as TableOrModel, af as Target, ag as TestCase, ah as TestHooks, ai as TestResponse, aj as TestTrait, s as Testable, ak as TravelDate, al as Wormhole, am as actingAsAuthFactory, an as addresses, ao as applyEnvironment, ap as cookieHeader, aq as cookiePrefix, ar as decryptCookie, as as encryptCookie, at as flatten, au as freezeSecond, av as freezeTime, aw as guessMimeType, ax as inertiaPageOf, ay as install, az as isExpired, aA as matches, aB as nameOf, aC as recordingExceptionHandler, aD as recordingViewFactory, aE as responseCookies, aF as runCommand, aG as travel, aH as travelBack, aI as travelTo, aJ as usingInMemoryDatabase } from './testing-BM481Hdz.js';
1
+ export { K as AnonymousNotifiable, R as AssertableInertia, V as AssertableJson, X as BatchRecord, Y as BootOptions, B as BusFake, Z as CountOrFilter, _ as DatabaseMigrations, $ as DatabaseTestOptions, a0 as DatabaseTransactions, a1 as DispatchedEvent, E as EventFake, a2 as ExpectedErrors, a3 as ExpectedListener, a4 as FakeDisk, a5 as FakeFile, a6 as HttpClient, a7 as InteractsWithApplication, a8 as InteractsWithConsole, a9 as InteractsWithDatabase, aa as InteractsWithTime, ab as JsonStructure, L as Live, M as MailFake, ac as MailRecord, ad as MakesHttpRequests, N as NotificationFake, ae as PendingCommand, af as PushedJob, Q as QueueFake, ag as RefreshDatabase, ah as RefreshDatabaseState, ai as RequestData, aj as RequestOptions, ak as ResponseContext, al as ResponseCookie, am as SentNotification, S as StorageFake, an as TESTING_ENVIRONMENT, ao as TableOrModel, ap as Target, aq as TestCase, ar as TestHooks, as as TestResponse, at as TestTrait, y as Testable, au as TravelDate, av as Wormhole, aw as actingAsAuthFactory, ax as addresses, ay as applyEnvironment, az as cookieHeader, aA as cookiePrefix, aB as decryptCookie, aC as encryptCookie, aD as flatten, aE as freezeSecond, aF as freezeTime, aG as guessMimeType, aH as inertiaPageOf, aI as install, aJ as isExpired, aK as matches, aL as nameOf, aM as recordingExceptionHandler, aN as recordingViewFactory, aO as responseCookies, aP as runCommand, aQ as travel, aR as travelBack, aS as travelTo, aT as usingInMemoryDatabase } from './testing-CKwfWJGn.js';
2
2
  import './contracts.js';
3
- import './index.d-BJyJx6U1.js';
3
+ import './index.d-WQpfdIbG.js';
package/dist/testing.js CHANGED
@@ -52,9 +52,9 @@ import {
52
52
  travelBack,
53
53
  travelTo,
54
54
  usingInMemoryDatabase
55
- } from "./chunk-ZOEPKBVF.js";
56
- import "./chunk-POEP4B2M.js";
57
- import "./chunk-I63ZFMX6.js";
55
+ } from "./chunk-4MWG3B7G.js";
56
+ import "./chunk-7ZQZYDOC.js";
57
+ import "./chunk-GVNLZZTN.js";
58
58
  export {
59
59
  AnonymousNotifiable,
60
60
  AssertableInertia,