@orieljs/framework 0.1.0-alpha.1 → 0.1.0-alpha.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/{chunk-K6MAA3RM.js → chunk-3ZRPBRAE.js} +3 -1
- package/dist/chunk-3ZRPBRAE.js.map +1 -0
- package/dist/{chunk-AI2RFMBT.js → chunk-HU43NADT.js} +2 -2
- package/dist/chunk-I2OMKIQZ.js +4693 -0
- package/dist/chunk-I2OMKIQZ.js.map +1 -0
- package/dist/chunk-IRHK7GH7.js +745 -0
- package/dist/chunk-IRHK7GH7.js.map +1 -0
- package/dist/chunk-S7YC43IH.js +93 -0
- package/dist/chunk-S7YC43IH.js.map +1 -0
- package/dist/{chunk-WI7E7Q46.js → chunk-TIE5OAMF.js} +3 -3
- package/dist/{chunk-BZPCRKFQ.js → chunk-UPZAML2Q.js} +729 -17
- package/dist/chunk-UPZAML2Q.js.map +1 -0
- package/dist/chunk-WEGTH46M.js +478 -0
- package/dist/chunk-WEGTH46M.js.map +1 -0
- package/dist/contracts.d.ts +111 -21
- package/dist/contracts.js +3 -1
- package/dist/index.d-DOlTeG-8.d.ts +99 -0
- package/dist/index.d.ts +1979 -1090
- package/dist/index.js +1482 -64
- package/dist/index.js.map +1 -1
- package/dist/{jsx-runtime-B8J6xq-7.d.ts → jsx-runtime-CZ6JqBQo.d.ts} +6 -11
- package/dist/jsx-runtime-WKTl3EEw.d.ts +254 -0
- package/dist/jsx-runtime.d.ts +3 -1
- package/dist/jsx-runtime.js +3 -3
- package/dist/testing--F6FODc_.d.ts +2068 -0
- package/dist/testing.d.ts +3 -1408
- package/dist/testing.js +13 -3
- package/package.json +31 -28
- package/dist/chunk-BZPCRKFQ.js.map +0 -1
- package/dist/chunk-K6MAA3RM.js.map +0 -1
- /package/dist/{chunk-AI2RFMBT.js.map → chunk-HU43NADT.js.map} +0 -0
- /package/dist/{chunk-WI7E7Q46.js.map → chunk-TIE5OAMF.js.map} +0 -0
|
@@ -2,10 +2,11 @@ import {
|
|
|
2
2
|
Arr,
|
|
3
3
|
ClassRegistry as ClassRegistry2,
|
|
4
4
|
Container,
|
|
5
|
+
ContainerNotAvailableError,
|
|
5
6
|
Str,
|
|
6
7
|
currentContainer,
|
|
7
8
|
facade
|
|
8
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-IRHK7GH7.js";
|
|
9
10
|
import {
|
|
10
11
|
Application,
|
|
11
12
|
AuthFactory,
|
|
@@ -20,6 +21,7 @@ import {
|
|
|
20
21
|
ExceptionHandler,
|
|
21
22
|
FilesystemManager,
|
|
22
23
|
HttpKernel,
|
|
24
|
+
HttpRequest,
|
|
23
25
|
MailManager,
|
|
24
26
|
MiddlewareCallbacks,
|
|
25
27
|
NotificationDispatcher,
|
|
@@ -28,7 +30,7 @@ import {
|
|
|
28
30
|
Session,
|
|
29
31
|
UrlGenerator,
|
|
30
32
|
ViewFactory
|
|
31
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-3ZRPBRAE.js";
|
|
32
34
|
|
|
33
35
|
// ../Config/dist/index.js
|
|
34
36
|
import { existsSync, readFileSync } from "fs";
|
|
@@ -111,8 +113,11 @@ async function loadConfiguration(configPath) {
|
|
|
111
113
|
}
|
|
112
114
|
|
|
113
115
|
// ../Foundation/dist/index.js
|
|
116
|
+
import { join as join3 } from "path";
|
|
117
|
+
import { isAbsolute, join as join4 } from "path";
|
|
118
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2, statSync } from "fs";
|
|
119
|
+
import { createHash, randomBytes } from "crypto";
|
|
114
120
|
import { join as join22 } from "path";
|
|
115
|
-
import { isAbsolute, join as join3 } from "path";
|
|
116
121
|
var ApplicationBuilder = class {
|
|
117
122
|
constructor(app) {
|
|
118
123
|
this.app = app;
|
|
@@ -127,7 +132,7 @@ var ApplicationBuilder = class {
|
|
|
127
132
|
return this;
|
|
128
133
|
}
|
|
129
134
|
withRouting(options) {
|
|
130
|
-
const abs = (p) => p === void 0 ? void 0 : isAbsolute(p) ? p :
|
|
135
|
+
const abs = (p) => p === void 0 ? void 0 : isAbsolute(p) ? p : join4(this.app.basePath(), p);
|
|
131
136
|
const paths = { apiPrefix: options.apiPrefix ?? "api" };
|
|
132
137
|
if (options.web !== void 0) paths.web = abs(options.web);
|
|
133
138
|
if (options.api !== void 0) paths.api = abs(options.api);
|
|
@@ -178,6 +183,280 @@ var ProviderRegisterError = class extends Error {
|
|
|
178
183
|
provider;
|
|
179
184
|
name = "ProviderRegisterError";
|
|
180
185
|
};
|
|
186
|
+
var ViteError = class extends Error {
|
|
187
|
+
kind = "Server";
|
|
188
|
+
status = 500;
|
|
189
|
+
constructor(message) {
|
|
190
|
+
super(message);
|
|
191
|
+
this.name = "ViteError";
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
var ViteHtml = class {
|
|
195
|
+
constructor(html) {
|
|
196
|
+
this.html = html;
|
|
197
|
+
}
|
|
198
|
+
html;
|
|
199
|
+
toHtml() {
|
|
200
|
+
return this.html;
|
|
201
|
+
}
|
|
202
|
+
toString() {
|
|
203
|
+
return this.html;
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
var CSS_PATH = /\.(css|less|sass|scss|styl|stylus|pcss|postcss)(\?[^.]*)?$/;
|
|
207
|
+
var manifests = /* @__PURE__ */ new Map();
|
|
208
|
+
var escapeAttribute = (value) => value.replace(/&/g, "&").replace(/"/g, """);
|
|
209
|
+
var Vite = class {
|
|
210
|
+
constructor(app) {
|
|
211
|
+
this.app = app;
|
|
212
|
+
}
|
|
213
|
+
app;
|
|
214
|
+
#hotFile;
|
|
215
|
+
#buildDirectory = "build";
|
|
216
|
+
#manifestFilename = "manifest.json";
|
|
217
|
+
#nonce;
|
|
218
|
+
#integrityKey = "integrity";
|
|
219
|
+
#entryPoints = [];
|
|
220
|
+
#scriptResolvers = [];
|
|
221
|
+
#styleResolvers = [];
|
|
222
|
+
#preloadResolvers = [];
|
|
223
|
+
#assetPathResolver;
|
|
224
|
+
#preloaded = {};
|
|
225
|
+
// Configuration --------------------------------------------------------------------------------------------
|
|
226
|
+
useCspNonce(nonce) {
|
|
227
|
+
this.#nonce = nonce ?? randomBytes(30).toString("base64url").slice(0, 40);
|
|
228
|
+
return this.#nonce;
|
|
229
|
+
}
|
|
230
|
+
cspNonce() {
|
|
231
|
+
return this.#nonce;
|
|
232
|
+
}
|
|
233
|
+
useIntegrityKey(key) {
|
|
234
|
+
this.#integrityKey = key;
|
|
235
|
+
return this;
|
|
236
|
+
}
|
|
237
|
+
withEntryPoints(entryPoints) {
|
|
238
|
+
this.#entryPoints = entryPoints;
|
|
239
|
+
return this;
|
|
240
|
+
}
|
|
241
|
+
useHotFile(path) {
|
|
242
|
+
this.#hotFile = path;
|
|
243
|
+
return this;
|
|
244
|
+
}
|
|
245
|
+
useBuildDirectory(path) {
|
|
246
|
+
this.#buildDirectory = path;
|
|
247
|
+
return this;
|
|
248
|
+
}
|
|
249
|
+
useManifestFilename(filename) {
|
|
250
|
+
this.#manifestFilename = filename;
|
|
251
|
+
return this;
|
|
252
|
+
}
|
|
253
|
+
useScriptTagAttributes(attributes) {
|
|
254
|
+
this.#scriptResolvers.push(typeof attributes === "function" ? attributes : () => attributes);
|
|
255
|
+
return this;
|
|
256
|
+
}
|
|
257
|
+
useStyleTagAttributes(attributes) {
|
|
258
|
+
this.#styleResolvers.push(typeof attributes === "function" ? attributes : () => attributes);
|
|
259
|
+
return this;
|
|
260
|
+
}
|
|
261
|
+
/** Extra preload attributes; a resolver returning false drops that preload. */
|
|
262
|
+
usePreloadTagAttributes(attributes) {
|
|
263
|
+
this.#preloadResolvers.push(typeof attributes === "function" ? attributes : () => attributes);
|
|
264
|
+
return this;
|
|
265
|
+
}
|
|
266
|
+
createAssetPathsUsing(resolver) {
|
|
267
|
+
this.#assetPathResolver = resolver;
|
|
268
|
+
return this;
|
|
269
|
+
}
|
|
270
|
+
// Dev server -----------------------------------------------------------------------------------------------
|
|
271
|
+
hotFile() {
|
|
272
|
+
return this.#hotFile ?? this.app.publicPath("hot");
|
|
273
|
+
}
|
|
274
|
+
isRunningHot() {
|
|
275
|
+
return existsSync3(this.hotFile());
|
|
276
|
+
}
|
|
277
|
+
/** The dev server URL written by @orieljs/vite, or undefined when it isn't running. */
|
|
278
|
+
devServerUrl() {
|
|
279
|
+
return this.isRunningHot() ? readFileSync2(this.hotFile(), "utf8").trimEnd() : void 0;
|
|
280
|
+
}
|
|
281
|
+
// Tags -----------------------------------------------------------------------------------------------------
|
|
282
|
+
/** Laravel's @vite([...]): preloads (styles first), then stylesheets, then scripts. */
|
|
283
|
+
tags(entryPoints, buildDirectory = this.#buildDirectory) {
|
|
284
|
+
const entries = [entryPoints].flat();
|
|
285
|
+
if (this.isRunningHot()) {
|
|
286
|
+
return new ViteHtml(["@vite/client", ...entries].map((entry) => this.#tagForChunk(entry, this.#hotAsset(entry), void 0, void 0)).join(""));
|
|
287
|
+
}
|
|
288
|
+
const manifest = this.manifest(buildDirectory);
|
|
289
|
+
const tags = [];
|
|
290
|
+
const preloads = [];
|
|
291
|
+
const cssChunk = (css) => {
|
|
292
|
+
const found = Object.entries(manifest).find(([, chunk2]) => chunk2.file === css);
|
|
293
|
+
return found === void 0 ? [css, void 0] : [found[0], found[1]];
|
|
294
|
+
};
|
|
295
|
+
for (const entry of entries) {
|
|
296
|
+
const chunk2 = this.#chunk(manifest, entry);
|
|
297
|
+
preloads.push([chunk2.src ?? entry, this.#assetPath(`${buildDirectory}/${chunk2.file}`), chunk2]);
|
|
298
|
+
for (const name of this.#resolveImports(manifest, chunk2)) {
|
|
299
|
+
const imported = manifest[name];
|
|
300
|
+
preloads.push([name, this.#assetPath(`${buildDirectory}/${imported.file}`), imported]);
|
|
301
|
+
for (const css of imported.css ?? []) {
|
|
302
|
+
const [key, partial] = cssChunk(css);
|
|
303
|
+
preloads.push([key, this.#assetPath(`${buildDirectory}/${css}`), partial]);
|
|
304
|
+
tags.push(this.#tagForChunk(key, this.#assetPath(`${buildDirectory}/${css}`), partial, manifest));
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
tags.push(this.#tagForChunk(entry, this.#assetPath(`${buildDirectory}/${chunk2.file}`), chunk2, manifest));
|
|
308
|
+
for (const css of chunk2.css ?? []) {
|
|
309
|
+
const [key, partial] = cssChunk(css);
|
|
310
|
+
preloads.push([key, this.#assetPath(`${buildDirectory}/${css}`), partial]);
|
|
311
|
+
tags.push(this.#tagForChunk(key, this.#assetPath(`${buildDirectory}/${css}`), partial, manifest));
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
const uniqueTags = [...new Set(tags)];
|
|
315
|
+
const stylesheets = uniqueTags.filter((tag) => tag.startsWith("<link"));
|
|
316
|
+
const scripts = uniqueTags.filter((tag) => !tag.startsWith("<link"));
|
|
317
|
+
const seen = /* @__PURE__ */ new Set();
|
|
318
|
+
const uniquePreloads = preloads.filter(([, url]) => seen.has(url) ? false : (seen.add(url), true));
|
|
319
|
+
const sorted = [...uniquePreloads.filter(([, url]) => CSS_PATH.test(url)), ...uniquePreloads.filter(([, url]) => !CSS_PATH.test(url))];
|
|
320
|
+
const preloadTags = sorted.map(([src, url, chunk2]) => this.#preloadTag(src, url, chunk2, manifest));
|
|
321
|
+
return new ViteHtml(preloadTags.join("") + stylesheets.join("") + scripts.join(""));
|
|
322
|
+
}
|
|
323
|
+
/** Laravel's @viteReactRefresh: the React Refresh preamble while the dev server runs; nothing otherwise. */
|
|
324
|
+
reactRefresh() {
|
|
325
|
+
if (!this.isRunningHot()) return void 0;
|
|
326
|
+
const attributes = this.#parseAttributes({ nonce: this.#nonce ?? false });
|
|
327
|
+
return new ViteHtml(
|
|
328
|
+
[
|
|
329
|
+
`<script type="module" ${attributes.join(" ")}>`,
|
|
330
|
+
` import RefreshRuntime from '${this.#hotAsset("@react-refresh")}'`,
|
|
331
|
+
" RefreshRuntime.injectIntoGlobalHook(window)",
|
|
332
|
+
" window.$RefreshReg$ = () => {}",
|
|
333
|
+
" window.$RefreshSig$ = () => (type) => type",
|
|
334
|
+
" window.__vite_plugin_react_preamble_installed__ = true",
|
|
335
|
+
"</script>"
|
|
336
|
+
].join("\n")
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
/** The URL of a processed asset (Vite::asset('resources/images/logo.svg')). */
|
|
340
|
+
asset(path, buildDirectory = this.#buildDirectory) {
|
|
341
|
+
if (this.isRunningHot()) return this.#hotAsset(path);
|
|
342
|
+
return this.#assetPath(`${buildDirectory}/${this.#chunk(this.manifest(buildDirectory), path).file}`);
|
|
343
|
+
}
|
|
344
|
+
/** The built file's contents (Vite::content()). */
|
|
345
|
+
content(path, buildDirectory = this.#buildDirectory) {
|
|
346
|
+
const chunk2 = this.#chunk(this.manifest(buildDirectory), path);
|
|
347
|
+
const file = this.app.publicPath(join22(buildDirectory, chunk2.file));
|
|
348
|
+
if (!existsSync3(file)) throw new ViteError(`Unable to locate file from Vite manifest: ${file}.`);
|
|
349
|
+
return readFileSync2(file, "utf8");
|
|
350
|
+
}
|
|
351
|
+
/** md5 of the manifest (a cache-busting asset version); undefined while hot or without a build. */
|
|
352
|
+
manifestHash(buildDirectory = this.#buildDirectory) {
|
|
353
|
+
if (this.isRunningHot()) return void 0;
|
|
354
|
+
const path = this.manifestPath(buildDirectory);
|
|
355
|
+
return existsSync3(path) ? createHash("md5").update(readFileSync2(path)).digest("hex") : void 0;
|
|
356
|
+
}
|
|
357
|
+
manifestPath(buildDirectory = this.#buildDirectory) {
|
|
358
|
+
return this.app.publicPath(join22(buildDirectory, this.#manifestFilename));
|
|
359
|
+
}
|
|
360
|
+
manifest(buildDirectory = this.#buildDirectory) {
|
|
361
|
+
const path = this.manifestPath(buildDirectory);
|
|
362
|
+
if (!existsSync3(path)) throw new ViteError(`Vite manifest not found at: ${path}`);
|
|
363
|
+
const { mtimeMs } = statSync(path);
|
|
364
|
+
const cached = manifests.get(path);
|
|
365
|
+
if (cached !== void 0 && cached.mtimeMs === mtimeMs) return cached.manifest;
|
|
366
|
+
const manifest = JSON.parse(readFileSync2(path, "utf8"));
|
|
367
|
+
manifests.set(path, { mtimeMs, manifest });
|
|
368
|
+
return manifest;
|
|
369
|
+
}
|
|
370
|
+
/** URL → the attributes of the preload tags rendered so far (without href), for Link headers. */
|
|
371
|
+
preloadedAssets() {
|
|
372
|
+
return { ...this.#preloaded };
|
|
373
|
+
}
|
|
374
|
+
/** Renders withEntryPoints() (Vite is Htmlable, like Laravel's). */
|
|
375
|
+
toHtml() {
|
|
376
|
+
return this.tags(this.#entryPoints).toHtml();
|
|
377
|
+
}
|
|
378
|
+
// Internals ------------------------------------------------------------------------------------------------
|
|
379
|
+
#hotAsset(path) {
|
|
380
|
+
return `${this.devServerUrl() ?? ""}/${path}`;
|
|
381
|
+
}
|
|
382
|
+
#assetPath(path) {
|
|
383
|
+
if (this.#assetPathResolver !== void 0) return this.#assetPathResolver(path);
|
|
384
|
+
if (this.app.bound(UrlGenerator)) return this.app.make(UrlGenerator).asset(path);
|
|
385
|
+
const base = this.app.bound(ConfigRepository) ? this.app.make(ConfigRepository).get("app.asset_url", null) : null;
|
|
386
|
+
return `${(base ?? "").replace(/\/+$/, "")}/${path.replace(/^\/+/, "")}`;
|
|
387
|
+
}
|
|
388
|
+
#chunk(manifest, file) {
|
|
389
|
+
const chunk2 = manifest[file];
|
|
390
|
+
if (chunk2 === void 0) throw new ViteError(`Unable to locate file in Vite manifest: ${file}.`);
|
|
391
|
+
return chunk2;
|
|
392
|
+
}
|
|
393
|
+
/** Every static import, depth first, each once. */
|
|
394
|
+
#resolveImports(manifest, chunk2, seen = /* @__PURE__ */ new Set()) {
|
|
395
|
+
const imports = [];
|
|
396
|
+
for (const name of chunk2.imports ?? []) {
|
|
397
|
+
if (seen.has(name)) continue;
|
|
398
|
+
seen.add(name);
|
|
399
|
+
imports.push(name);
|
|
400
|
+
const imported = manifest[name];
|
|
401
|
+
if (imported !== void 0) imports.push(...this.#resolveImports(manifest, imported, seen));
|
|
402
|
+
}
|
|
403
|
+
return imports;
|
|
404
|
+
}
|
|
405
|
+
#tagForChunk(src, url, chunk2, manifest) {
|
|
406
|
+
if (CSS_PATH.test(url)) {
|
|
407
|
+
const attributes2 = this.#parseAttributes({ rel: "stylesheet", href: url, nonce: this.#nonce ?? false, ...this.#styleAttributes(src, url, chunk2, manifest) });
|
|
408
|
+
return `<link ${attributes2.join(" ")} />`;
|
|
409
|
+
}
|
|
410
|
+
const attributes = this.#parseAttributes({ type: "module", src: url, nonce: this.#nonce ?? false, ...this.#scriptAttributes(src, url, chunk2, manifest) });
|
|
411
|
+
return `<script ${attributes.join(" ")}></script>`;
|
|
412
|
+
}
|
|
413
|
+
#preloadTag(src, url, chunk2, manifest) {
|
|
414
|
+
const css = CSS_PATH.test(url);
|
|
415
|
+
let attributes = {
|
|
416
|
+
rel: css ? "preload" : "modulepreload",
|
|
417
|
+
as: css ? "style" : "script",
|
|
418
|
+
href: url,
|
|
419
|
+
nonce: this.#nonce ?? false,
|
|
420
|
+
crossorigin: (css ? this.#styleAttributes(src, url, chunk2, manifest) : this.#scriptAttributes(src, url, chunk2, manifest)).crossorigin ?? false
|
|
421
|
+
};
|
|
422
|
+
if (this.#integrityKey !== false) attributes.integrity = chunk2?.[this.#integrityKey] ?? false;
|
|
423
|
+
for (const resolver of this.#preloadResolvers) {
|
|
424
|
+
const resolved = resolver(src, url, chunk2, manifest);
|
|
425
|
+
if (resolved === false) return "";
|
|
426
|
+
attributes = { ...attributes, ...resolved };
|
|
427
|
+
}
|
|
428
|
+
const { href: _href, ...rest } = attributes;
|
|
429
|
+
this.#preloaded[url] = this.#parseAttributes(rest);
|
|
430
|
+
return `<link ${this.#parseAttributes(attributes).join(" ")} />`;
|
|
431
|
+
}
|
|
432
|
+
#scriptAttributes(src, url, chunk2, manifest) {
|
|
433
|
+
let attributes = this.#integrityKey !== false ? { integrity: chunk2?.[this.#integrityKey] ?? false } : {};
|
|
434
|
+
for (const resolver of this.#scriptResolvers) attributes = { ...attributes, ...resolver(src, url, chunk2, manifest) };
|
|
435
|
+
return attributes;
|
|
436
|
+
}
|
|
437
|
+
#styleAttributes(src, url, chunk2, manifest) {
|
|
438
|
+
let attributes = this.#integrityKey !== false ? { integrity: chunk2?.[this.#integrityKey] ?? false } : {};
|
|
439
|
+
for (const resolver of this.#styleResolvers) attributes = { ...attributes, ...resolver(src, url, chunk2, manifest) };
|
|
440
|
+
return attributes;
|
|
441
|
+
}
|
|
442
|
+
/** false/null/undefined are dropped, true is a bare attribute, anything else name="value". */
|
|
443
|
+
#parseAttributes(attributes) {
|
|
444
|
+
return Object.entries(attributes).filter(([, value]) => value !== false && value !== null && value !== void 0).map(([name, value]) => value === true ? name : `${name}="${escapeAttribute(String(value))}"`);
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
function currentVite() {
|
|
448
|
+
const container = currentContainer();
|
|
449
|
+
if (container === void 0) throw new ContainerNotAvailableError("Vite");
|
|
450
|
+
if (container.bound(HttpRequest)) return container.make(Vite);
|
|
451
|
+
return new Vite(container.make(Application));
|
|
452
|
+
}
|
|
453
|
+
function vite(entryPoints, buildDirectory) {
|
|
454
|
+
const instance = currentVite();
|
|
455
|
+
return entryPoints === void 0 ? instance : instance.tags(entryPoints, buildDirectory);
|
|
456
|
+
}
|
|
457
|
+
function viteReactRefresh() {
|
|
458
|
+
return currentVite().reactRefresh();
|
|
459
|
+
}
|
|
181
460
|
var Application2 = class _Application extends Container {
|
|
182
461
|
constructor(base) {
|
|
183
462
|
super();
|
|
@@ -186,6 +465,7 @@ var Application2 = class _Application extends Container {
|
|
|
186
465
|
this.instance(Application, this);
|
|
187
466
|
this.instance(_Application, this);
|
|
188
467
|
this.singleton(ClassRegistry, ClassRegistry2);
|
|
468
|
+
this.scoped(Vite, () => new Vite(this));
|
|
189
469
|
}
|
|
190
470
|
base;
|
|
191
471
|
version = "0.1.0-alpha.1";
|
|
@@ -201,28 +481,28 @@ var Application2 = class _Application extends Container {
|
|
|
201
481
|
return new ApplicationBuilder(new _Application(options.basePath));
|
|
202
482
|
}
|
|
203
483
|
basePath(path = "") {
|
|
204
|
-
return
|
|
484
|
+
return join3(this.base, path);
|
|
205
485
|
}
|
|
206
486
|
appPath(path = "") {
|
|
207
|
-
return this.basePath(
|
|
487
|
+
return this.basePath(join3("app", path));
|
|
208
488
|
}
|
|
209
489
|
bootstrapPath(path = "") {
|
|
210
|
-
return this.basePath(
|
|
490
|
+
return this.basePath(join3("bootstrap", path));
|
|
211
491
|
}
|
|
212
492
|
configPath(path = "") {
|
|
213
|
-
return this.basePath(
|
|
493
|
+
return this.basePath(join3("config", path));
|
|
214
494
|
}
|
|
215
495
|
databasePath(path = "") {
|
|
216
|
-
return this.basePath(
|
|
496
|
+
return this.basePath(join3("database", path));
|
|
217
497
|
}
|
|
218
498
|
publicPath(path = "") {
|
|
219
|
-
return this.basePath(
|
|
499
|
+
return this.basePath(join3("public", path));
|
|
220
500
|
}
|
|
221
501
|
resourcePath(path = "") {
|
|
222
|
-
return this.basePath(
|
|
502
|
+
return this.basePath(join3("resources", path));
|
|
223
503
|
}
|
|
224
504
|
storagePath(path = "") {
|
|
225
|
-
return this.basePath(
|
|
505
|
+
return this.basePath(join3("storage", path));
|
|
226
506
|
}
|
|
227
507
|
environment(...environments) {
|
|
228
508
|
const fallback = process.env.APP_ENV ?? "production";
|
|
@@ -322,11 +602,13 @@ function toResponse(output) {
|
|
|
322
602
|
// ../Testing/dist/index.js
|
|
323
603
|
import { AssertionError } from "assert";
|
|
324
604
|
import { isDeepStrictEqual } from "util";
|
|
605
|
+
import { existsSync as existsSync4 } from "fs";
|
|
606
|
+
import { join as join5 } from "path";
|
|
325
607
|
import { createHmac } from "crypto";
|
|
326
608
|
import { randomUUID } from "crypto";
|
|
327
609
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
328
610
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
329
|
-
import { randomBytes } from "crypto";
|
|
611
|
+
import { randomBytes as randomBytes2 } from "crypto";
|
|
330
612
|
import { deflateSync } from "zlib";
|
|
331
613
|
function fail(message, details = {}) {
|
|
332
614
|
const error = new AssertionError({ message, actual: details.actual, expected: details.expected, operator: "fail" });
|
|
@@ -608,6 +890,395 @@ function clonePlain2(value) {
|
|
|
608
890
|
}
|
|
609
891
|
return value;
|
|
610
892
|
}
|
|
893
|
+
function typeOf(value) {
|
|
894
|
+
if (value === null) return ["null"];
|
|
895
|
+
if (Array.isArray(value)) return ["array"];
|
|
896
|
+
switch (typeof value) {
|
|
897
|
+
case "string":
|
|
898
|
+
return ["string"];
|
|
899
|
+
case "boolean":
|
|
900
|
+
return ["boolean"];
|
|
901
|
+
case "number":
|
|
902
|
+
return Number.isInteger(value) ? ["integer", "number"] : ["double", "float", "number"];
|
|
903
|
+
case "object":
|
|
904
|
+
return ["array", "object"];
|
|
905
|
+
default:
|
|
906
|
+
return [typeof value];
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
var AssertableJson = class _AssertableJson {
|
|
910
|
+
constructor(props, path = void 0) {
|
|
911
|
+
this.props = props;
|
|
912
|
+
this.path = path;
|
|
913
|
+
}
|
|
914
|
+
props;
|
|
915
|
+
path;
|
|
916
|
+
interactedKeys = [];
|
|
917
|
+
static fromJson(json) {
|
|
918
|
+
return new _AssertableJson(json);
|
|
919
|
+
}
|
|
920
|
+
/** A child scope of the same class (subclasses override to keep their extra state out of scopes). */
|
|
921
|
+
newScope(props, path) {
|
|
922
|
+
return new _AssertableJson(props, path);
|
|
923
|
+
}
|
|
924
|
+
dotPath(key = "") {
|
|
925
|
+
if (this.path === void 0) return key;
|
|
926
|
+
return key === "" ? this.path : `${this.path}.${key}`;
|
|
927
|
+
}
|
|
928
|
+
/** The value at `key` in this scope, or the whole scope. */
|
|
929
|
+
prop(key) {
|
|
930
|
+
if (key !== void 0 && this.hasOwnKey(key)) return this.props[key];
|
|
931
|
+
return Arr.get(this.props, key);
|
|
932
|
+
}
|
|
933
|
+
/** A literal key of this scope wins over a dot path, like Laravel's Arr::get (keys such as 'items.0.name'). */
|
|
934
|
+
hasOwnKey(key) {
|
|
935
|
+
return typeof this.props === "object" && this.props !== null && Object.hasOwn(this.props, key);
|
|
936
|
+
}
|
|
937
|
+
exists(key) {
|
|
938
|
+
return this.hasOwnKey(key) || Arr.has(this.props, key);
|
|
939
|
+
}
|
|
940
|
+
interactsWith(key) {
|
|
941
|
+
const prop = this.hasOwnKey(String(key)) ? String(key) : String(key).split(".")[0];
|
|
942
|
+
if (!this.interactedKeys.includes(prop)) this.interactedKeys.push(prop);
|
|
943
|
+
}
|
|
944
|
+
/** Every property of the scope was checked (called when a scope ends). */
|
|
945
|
+
interacted() {
|
|
946
|
+
const props = this.prop();
|
|
947
|
+
const keys = typeof props === "object" && props !== null ? Object.keys(props) : [];
|
|
948
|
+
const unexpected = keys.filter((key) => !this.interactedKeys.includes(key));
|
|
949
|
+
assert(
|
|
950
|
+
unexpected.length === 0,
|
|
951
|
+
this.path === void 0 ? "Unexpected properties were found on the root level." : `Unexpected properties were found in scope [${this.path}].`,
|
|
952
|
+
{ actual: unexpected, expected: [] }
|
|
953
|
+
);
|
|
954
|
+
}
|
|
955
|
+
/** Allow the properties this scope didn't check. */
|
|
956
|
+
etc() {
|
|
957
|
+
const props = this.prop();
|
|
958
|
+
this.interactedKeys = typeof props === "object" && props !== null ? Object.keys(props) : [];
|
|
959
|
+
return this;
|
|
960
|
+
}
|
|
961
|
+
// Has ------------------------------------------------------------------------------------------------------
|
|
962
|
+
/** has('key'), has('key', 3), has('key', json => …), has('key', 3, first => …), or has(3) for the root size. */
|
|
963
|
+
has(key, length, callback) {
|
|
964
|
+
if (typeof key === "number" && length === void 0) return this.count(key);
|
|
965
|
+
const name = String(key);
|
|
966
|
+
assert(this.exists(name), `Property [${this.dotPath(name)}] does not exist.`);
|
|
967
|
+
this.interactsWith(name);
|
|
968
|
+
if (callback !== void 0) {
|
|
969
|
+
return this.has(name, (scope) => {
|
|
970
|
+
if (typeof length === "number") scope.count(length);
|
|
971
|
+
scope.first(callback).etc();
|
|
972
|
+
});
|
|
973
|
+
}
|
|
974
|
+
if (typeof length === "function") return this.scope(name, length);
|
|
975
|
+
if (typeof length === "number") return this.count(name, length);
|
|
976
|
+
return this;
|
|
977
|
+
}
|
|
978
|
+
/** hasAll(['a', 'b']) or hasAll({ items: 3 }). */
|
|
979
|
+
hasAll(keys) {
|
|
980
|
+
if (typeof keys === "string" || Array.isArray(keys)) {
|
|
981
|
+
for (const key of [keys].flat()) this.has(key);
|
|
982
|
+
return this;
|
|
983
|
+
}
|
|
984
|
+
for (const [key, length] of Object.entries(keys)) this.has(key, length);
|
|
985
|
+
return this;
|
|
986
|
+
}
|
|
987
|
+
hasAny(keys) {
|
|
988
|
+
const list = [keys].flat();
|
|
989
|
+
const present = list.filter((key) => this.exists(key));
|
|
990
|
+
assert(present.length > 0, `None of properties [${list.map((key) => this.dotPath(key)).join(", ")}] exist.`);
|
|
991
|
+
for (const key of present) this.interactsWith(key);
|
|
992
|
+
return this;
|
|
993
|
+
}
|
|
994
|
+
missing(key) {
|
|
995
|
+
assert(!this.exists(key), `Property [${this.dotPath(key)}] was found while it was expected to be missing.`);
|
|
996
|
+
return this;
|
|
997
|
+
}
|
|
998
|
+
missingAll(keys) {
|
|
999
|
+
for (const key of [keys].flat()) this.missing(key);
|
|
1000
|
+
return this;
|
|
1001
|
+
}
|
|
1002
|
+
/** count(3) checks this scope's size; count('items', 3) a property's. */
|
|
1003
|
+
count(key, length) {
|
|
1004
|
+
if (typeof key === "number") {
|
|
1005
|
+
const size2 = sizeOf(this.prop());
|
|
1006
|
+
assert(size2 === key, this.path === void 0 ? "Root level does not have the expected size." : `Property [${this.path}] does not have the expected size.`, { actual: size2, expected: key });
|
|
1007
|
+
return this;
|
|
1008
|
+
}
|
|
1009
|
+
this.has(key);
|
|
1010
|
+
const size = sizeOf(this.prop(key));
|
|
1011
|
+
assert(size === length, `Property [${this.dotPath(key)}] does not have the expected size.`, { actual: size, expected: length });
|
|
1012
|
+
return this;
|
|
1013
|
+
}
|
|
1014
|
+
countBetween(key, min, max) {
|
|
1015
|
+
this.has(key);
|
|
1016
|
+
const size = sizeOf(this.prop(key));
|
|
1017
|
+
assert(size >= min && size <= max, `Property [${this.dotPath(key)}] size is not between ${min} and ${max}.`, { actual: size });
|
|
1018
|
+
return this;
|
|
1019
|
+
}
|
|
1020
|
+
// Matching -------------------------------------------------------------------------------------------------
|
|
1021
|
+
/** where('name', 'Ann'), or where('name', value => value.startsWith('A')). Objects compare ignoring key order. */
|
|
1022
|
+
where(key, expected) {
|
|
1023
|
+
this.has(key);
|
|
1024
|
+
const actual = this.prop(key);
|
|
1025
|
+
if (typeof expected === "function") {
|
|
1026
|
+
assert(expected(actual), `Property [${this.dotPath(key)}] was marked as invalid using a closure.`);
|
|
1027
|
+
return this;
|
|
1028
|
+
}
|
|
1029
|
+
const normalized = toPlain(expected);
|
|
1030
|
+
assert(equals(normalized, actual), `Property [${this.dotPath(key)}] does not match the expected value.`, { actual, expected: normalized });
|
|
1031
|
+
return this;
|
|
1032
|
+
}
|
|
1033
|
+
whereNot(key, expected) {
|
|
1034
|
+
this.has(key);
|
|
1035
|
+
const actual = this.prop(key);
|
|
1036
|
+
if (typeof expected === "function") {
|
|
1037
|
+
assert(!expected(actual), `Property [${this.dotPath(key)}] was marked as invalid using a closure.`);
|
|
1038
|
+
return this;
|
|
1039
|
+
}
|
|
1040
|
+
assert(!equals(toPlain(expected), actual), `Property [${this.dotPath(key)}] contains a value that should be missing: [${key}, ${format(expected)}]`);
|
|
1041
|
+
return this;
|
|
1042
|
+
}
|
|
1043
|
+
whereNull(key) {
|
|
1044
|
+
this.has(key);
|
|
1045
|
+
const actual = this.prop(key);
|
|
1046
|
+
assert(actual === null, `Property [${this.dotPath(key)}] should be null.`, { actual, expected: null });
|
|
1047
|
+
return this;
|
|
1048
|
+
}
|
|
1049
|
+
whereNotNull(key) {
|
|
1050
|
+
this.has(key);
|
|
1051
|
+
assert(this.prop(key) !== null, `Property [${this.dotPath(key)}] should not be null.`);
|
|
1052
|
+
return this;
|
|
1053
|
+
}
|
|
1054
|
+
whereAll(bindings) {
|
|
1055
|
+
for (const [key, value] of Object.entries(bindings)) this.where(key, value);
|
|
1056
|
+
return this;
|
|
1057
|
+
}
|
|
1058
|
+
/** whereType('id', 'integer'), whereType('name', 'string|null'), whereType('tags', ['array', 'null']). */
|
|
1059
|
+
whereType(key, expected) {
|
|
1060
|
+
this.has(key);
|
|
1061
|
+
const types = typeof expected === "string" ? expected.split("|") : expected;
|
|
1062
|
+
const actual = typeOf(this.prop(key));
|
|
1063
|
+
assert(
|
|
1064
|
+
types.some((type) => actual.includes(type)),
|
|
1065
|
+
`Property [${this.dotPath(key)}] is not of expected type [${types.join("|")}].`,
|
|
1066
|
+
{ actual: actual[0], expected: types.join("|") }
|
|
1067
|
+
);
|
|
1068
|
+
return this;
|
|
1069
|
+
}
|
|
1070
|
+
whereAllType(bindings) {
|
|
1071
|
+
for (const [key, type] of Object.entries(bindings)) this.whereType(key, type);
|
|
1072
|
+
return this;
|
|
1073
|
+
}
|
|
1074
|
+
/** The list contains every expected value (or one passing the callback); a string contains the substring. */
|
|
1075
|
+
whereContains(key, expected) {
|
|
1076
|
+
this.has(key);
|
|
1077
|
+
const actual = this.prop(key);
|
|
1078
|
+
if (typeof actual === "string") {
|
|
1079
|
+
assert(actual.includes(String(expected)), `Property [${this.dotPath(key)}] does not contain [${format(expected)}].`);
|
|
1080
|
+
return this;
|
|
1081
|
+
}
|
|
1082
|
+
const values = typeof actual === "object" && actual !== null ? Object.values(actual) : [actual];
|
|
1083
|
+
const wanted = Array.isArray(expected) ? expected : [expected];
|
|
1084
|
+
const missing = wanted.filter(
|
|
1085
|
+
(item) => typeof item === "function" ? !values.some((value) => item(value)) : !values.some((value) => equals(toPlain(item), value))
|
|
1086
|
+
);
|
|
1087
|
+
assert(missing.length === 0, `Property [${this.dotPath(key)}] does not contain [${missing.map(format).join(", ")}].`, { actual });
|
|
1088
|
+
return this;
|
|
1089
|
+
}
|
|
1090
|
+
// Scoping --------------------------------------------------------------------------------------------------
|
|
1091
|
+
scope(key, callback) {
|
|
1092
|
+
const props = this.prop(key);
|
|
1093
|
+
const path = this.dotPath(key);
|
|
1094
|
+
assert(typeof props === "object" && props !== null, `Property [${path}] is not scopeable.`);
|
|
1095
|
+
const scope = this.newScope(props, path);
|
|
1096
|
+
callback(scope);
|
|
1097
|
+
scope.interacted();
|
|
1098
|
+
return this;
|
|
1099
|
+
}
|
|
1100
|
+
first(callback) {
|
|
1101
|
+
const props = this.prop();
|
|
1102
|
+
const keys = typeof props === "object" && props !== null ? Object.keys(props) : [];
|
|
1103
|
+
if (keys.length === 0) {
|
|
1104
|
+
fail(this.path === void 0 ? "Cannot scope directly onto the first element of the root level because it is empty." : `Cannot scope directly onto the first element of property [${this.path}] because it is empty.`);
|
|
1105
|
+
}
|
|
1106
|
+
this.interactsWith(keys[0]);
|
|
1107
|
+
return this.scope(keys[0], callback);
|
|
1108
|
+
}
|
|
1109
|
+
each(callback) {
|
|
1110
|
+
const props = this.prop();
|
|
1111
|
+
const keys = typeof props === "object" && props !== null ? Object.keys(props) : [];
|
|
1112
|
+
if (keys.length === 0) {
|
|
1113
|
+
fail(this.path === void 0 ? "Cannot scope directly onto each element of the root level because it is empty." : `Cannot scope directly onto each element of property [${this.path}] because it is empty.`);
|
|
1114
|
+
}
|
|
1115
|
+
for (const key of keys) {
|
|
1116
|
+
this.interactsWith(key);
|
|
1117
|
+
this.scope(key, callback);
|
|
1118
|
+
}
|
|
1119
|
+
return this;
|
|
1120
|
+
}
|
|
1121
|
+
// Helpers --------------------------------------------------------------------------------------------------
|
|
1122
|
+
when(condition, callback, otherwise) {
|
|
1123
|
+
if (condition) callback(this);
|
|
1124
|
+
else otherwise?.(this);
|
|
1125
|
+
return this;
|
|
1126
|
+
}
|
|
1127
|
+
dump(key) {
|
|
1128
|
+
console.log(format(this.prop(key)));
|
|
1129
|
+
return this;
|
|
1130
|
+
}
|
|
1131
|
+
toArray() {
|
|
1132
|
+
return this.prop();
|
|
1133
|
+
}
|
|
1134
|
+
};
|
|
1135
|
+
function sizeOf(value) {
|
|
1136
|
+
if (Array.isArray(value)) return value.length;
|
|
1137
|
+
if (typeof value === "object" && value !== null) return Object.keys(value).length;
|
|
1138
|
+
if (typeof value === "string") return value.length;
|
|
1139
|
+
return 0;
|
|
1140
|
+
}
|
|
1141
|
+
function toPlain(value) {
|
|
1142
|
+
return value === void 0 ? void 0 : JSON.parse(JSON.stringify(value));
|
|
1143
|
+
}
|
|
1144
|
+
function inertiaPageOf(response) {
|
|
1145
|
+
let page;
|
|
1146
|
+
try {
|
|
1147
|
+
if (response.headers.has("X-Inertia")) page = JSON.parse(response.content);
|
|
1148
|
+
else {
|
|
1149
|
+
const match = /<script data-page="[^"]*" type="application\/json">([\s\S]*?)<\/script>/.exec(response.content);
|
|
1150
|
+
page = match === null ? void 0 : JSON.parse(match[1]);
|
|
1151
|
+
}
|
|
1152
|
+
} catch {
|
|
1153
|
+
page = void 0;
|
|
1154
|
+
}
|
|
1155
|
+
const valid = typeof page === "object" && page !== null && ["component", "props", "url", "version"].every((key) => Object.hasOwn(page, key));
|
|
1156
|
+
if (!valid) fail("Not a valid Inertia response.");
|
|
1157
|
+
return page;
|
|
1158
|
+
}
|
|
1159
|
+
var AssertableInertia = class _AssertableInertia extends AssertableJson {
|
|
1160
|
+
#page;
|
|
1161
|
+
#response;
|
|
1162
|
+
static fromTestResponse(response) {
|
|
1163
|
+
const page = inertiaPageOf(response);
|
|
1164
|
+
const instance = new _AssertableInertia(page.props);
|
|
1165
|
+
instance.#page = page;
|
|
1166
|
+
instance.#response = response;
|
|
1167
|
+
return instance;
|
|
1168
|
+
}
|
|
1169
|
+
/** Scopes are plain AssertableJson: the page-level methods only make sense at the root. */
|
|
1170
|
+
newScope(props, path) {
|
|
1171
|
+
return new AssertableJson(props, path);
|
|
1172
|
+
}
|
|
1173
|
+
get page() {
|
|
1174
|
+
if (this.#page === void 0) fail("This assertion is only available on the page root.");
|
|
1175
|
+
return this.#page;
|
|
1176
|
+
}
|
|
1177
|
+
/** The component name; the page file must exist unless `shouldExist` is false (inertia.testing.ensure_pages_exist). */
|
|
1178
|
+
component(value, shouldExist) {
|
|
1179
|
+
const actual = this.page.component;
|
|
1180
|
+
assert(actual === value, "Unexpected Inertia page component.", { actual, expected: value });
|
|
1181
|
+
const app = this.#app();
|
|
1182
|
+
const config = app?.bound(ConfigRepository) ? app.make(ConfigRepository) : void 0;
|
|
1183
|
+
if (shouldExist === true || shouldExist === void 0 && config?.get("inertia.testing.ensure_pages_exist", true) !== false) {
|
|
1184
|
+
const paths = config?.get("inertia.pages.paths", []) ?? [];
|
|
1185
|
+
const extensions = config?.get("inertia.pages.extensions", []) ?? [];
|
|
1186
|
+
const exists = paths.some((path) => extensions.some((extension) => existsSync4(join5(path, `${value}.${extension}`))));
|
|
1187
|
+
if (!exists) fail(`Inertia page component file [${value}] does not exist.`);
|
|
1188
|
+
}
|
|
1189
|
+
return this;
|
|
1190
|
+
}
|
|
1191
|
+
url(value) {
|
|
1192
|
+
assert(this.page.url === value, "Unexpected Inertia page url.", { actual: this.page.url, expected: value });
|
|
1193
|
+
return this;
|
|
1194
|
+
}
|
|
1195
|
+
version(value) {
|
|
1196
|
+
assert(this.page.version === value, "Unexpected Inertia asset version.", { actual: this.page.version, expected: value });
|
|
1197
|
+
return this;
|
|
1198
|
+
}
|
|
1199
|
+
/** The flash data has `key` (dot paths allowed), equal to `expected` when given. */
|
|
1200
|
+
hasFlash(key, ...expected) {
|
|
1201
|
+
_AssertableInertia.assertFlashHas(this.page.flash ?? {}, key, ...expected);
|
|
1202
|
+
return this;
|
|
1203
|
+
}
|
|
1204
|
+
missingFlash(key) {
|
|
1205
|
+
_AssertableInertia.assertFlashMissing(this.page.flash ?? {}, key);
|
|
1206
|
+
return this;
|
|
1207
|
+
}
|
|
1208
|
+
static assertFlashHas(flash, key, ...expected) {
|
|
1209
|
+
assert(Arr.has(flash, key), `Inertia Flash Data is missing key [${key}].`);
|
|
1210
|
+
if (expected.length > 0) {
|
|
1211
|
+
const actual = Arr.get(flash, key);
|
|
1212
|
+
assert(equals(actual, expected[0]), `Inertia Flash Data [${key}] does not match expected value.`, { actual, expected: expected[0] });
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
static assertFlashMissing(flash, key) {
|
|
1216
|
+
assert(!Arr.has(flash, key), `Inertia Flash Data has unexpected key [${key}].`);
|
|
1217
|
+
}
|
|
1218
|
+
/**
|
|
1219
|
+
* Requests the page again as a partial reload (only/except) and checks it is the same page. Uses the test's
|
|
1220
|
+
* HTTP client, so the session and cookies carry over.
|
|
1221
|
+
*/
|
|
1222
|
+
async reload(callback, only, except) {
|
|
1223
|
+
const client = this.#response?.context.client;
|
|
1224
|
+
if (client === void 0) fail("reload() needs a response from the test HTTP client.");
|
|
1225
|
+
const headers = {
|
|
1226
|
+
"X-Inertia": "true",
|
|
1227
|
+
"X-Requested-With": "XMLHttpRequest",
|
|
1228
|
+
"X-Inertia-Version": this.page.version
|
|
1229
|
+
};
|
|
1230
|
+
const onlyList = only === void 0 ? void 0 : [only].flat().join(",");
|
|
1231
|
+
const exceptList = except === void 0 ? void 0 : [except].flat().join(",");
|
|
1232
|
+
if (onlyList !== void 0 || exceptList !== void 0) headers["X-Inertia-Partial-Component"] = this.page.component;
|
|
1233
|
+
if (onlyList !== void 0) headers["X-Inertia-Partial-Data"] = onlyList;
|
|
1234
|
+
if (exceptList !== void 0) headers["X-Inertia-Partial-Except"] = exceptList;
|
|
1235
|
+
const response = await client.request("GET", this.page.url, { headers });
|
|
1236
|
+
const reloaded = _AssertableInertia.fromTestResponse(response);
|
|
1237
|
+
reloaded.component(this.page.component, false).url(this.page.url).version(this.page.version);
|
|
1238
|
+
await callback?.(reloaded);
|
|
1239
|
+
return this;
|
|
1240
|
+
}
|
|
1241
|
+
reloadOnly(only, callback) {
|
|
1242
|
+
return this.reload(
|
|
1243
|
+
async (page) => {
|
|
1244
|
+
page.hasAll(typeof only === "string" ? only.split(",") : only);
|
|
1245
|
+
await callback?.(page);
|
|
1246
|
+
},
|
|
1247
|
+
only
|
|
1248
|
+
);
|
|
1249
|
+
}
|
|
1250
|
+
reloadExcept(except, callback) {
|
|
1251
|
+
return this.reload(
|
|
1252
|
+
async (page) => {
|
|
1253
|
+
page.missingAll(typeof except === "string" ? except.split(",") : except);
|
|
1254
|
+
await callback?.(page);
|
|
1255
|
+
},
|
|
1256
|
+
void 0,
|
|
1257
|
+
except
|
|
1258
|
+
);
|
|
1259
|
+
}
|
|
1260
|
+
/** Loads the deferred props of every group (or the given groups) in one partial reload. */
|
|
1261
|
+
loadDeferredProps(groupsOrCallback, callback) {
|
|
1262
|
+
const deferred = this.page.deferredProps ?? {};
|
|
1263
|
+
const groups = typeof groupsOrCallback === "function" ? Object.keys(deferred) : [groupsOrCallback].flat();
|
|
1264
|
+
const props = groups.flatMap((group) => deferred[group] ?? []);
|
|
1265
|
+
return this.reloadOnly(props.join(","), typeof groupsOrCallback === "function" ? groupsOrCallback : callback);
|
|
1266
|
+
}
|
|
1267
|
+
toArray() {
|
|
1268
|
+
return {
|
|
1269
|
+
component: this.page.component,
|
|
1270
|
+
props: this.prop(),
|
|
1271
|
+
url: this.page.url,
|
|
1272
|
+
version: this.page.version,
|
|
1273
|
+
flash: this.page.flash ?? {},
|
|
1274
|
+
...this.page.encryptHistory === true ? { encryptHistory: true } : {},
|
|
1275
|
+
...this.page.clearHistory === true ? { clearHistory: true } : {}
|
|
1276
|
+
};
|
|
1277
|
+
}
|
|
1278
|
+
#app() {
|
|
1279
|
+
return this.#response?.context.app;
|
|
1280
|
+
}
|
|
1281
|
+
};
|
|
611
1282
|
function cookiePrefix(name, key) {
|
|
612
1283
|
return `${createHmac("sha1", key).update(`${name}v2`).digest("hex")}|`;
|
|
613
1284
|
}
|
|
@@ -880,12 +1551,44 @@ ${this.excerpt(text)}`);
|
|
|
880
1551
|
return this.inOrder(stripTags(this.content), this.needles(values, escape));
|
|
881
1552
|
}
|
|
882
1553
|
// JSON --------------------------------------------------------------------------------------------------
|
|
883
|
-
/**
|
|
1554
|
+
/**
|
|
1555
|
+
* The response JSON contains `data` (a subset match: extra keys in the response are fine), or fluent
|
|
1556
|
+
* assertions: assertJson(json => json.has('data', 3).etc()).
|
|
1557
|
+
*/
|
|
884
1558
|
assertJson(data) {
|
|
1559
|
+
if (typeof data === "function") {
|
|
1560
|
+
const json = AssertableJson.fromJson(this.json());
|
|
1561
|
+
data(json);
|
|
1562
|
+
if (!Array.isArray(json.toArray())) json.interacted();
|
|
1563
|
+
return this;
|
|
1564
|
+
}
|
|
885
1565
|
const actual = this.json();
|
|
886
1566
|
assert(isSubset(data, actual), "Unable to find the expected JSON subset in the response.", { actual, expected: data });
|
|
887
1567
|
return this;
|
|
888
1568
|
}
|
|
1569
|
+
assertInertia(callback) {
|
|
1570
|
+
const page = AssertableInertia.fromTestResponse(this);
|
|
1571
|
+
const result = callback?.(page);
|
|
1572
|
+
if (typeof result?.then === "function") return Promise.resolve(result).then(() => this);
|
|
1573
|
+
return this;
|
|
1574
|
+
}
|
|
1575
|
+
/** The Inertia page object of this response. */
|
|
1576
|
+
inertiaPage() {
|
|
1577
|
+
return inertiaPageOf(this);
|
|
1578
|
+
}
|
|
1579
|
+
/** The page props, or one prop by dot path. */
|
|
1580
|
+
inertiaProps(key) {
|
|
1581
|
+
return Arr.get(inertiaPageOf(this).props, key);
|
|
1582
|
+
}
|
|
1583
|
+
/** Inertia flash data waiting in the session for the next page (after a redirect). */
|
|
1584
|
+
assertInertiaFlash(key, ...expected) {
|
|
1585
|
+
AssertableInertia.assertFlashHas(this.session().get("inertia.flash_data", {}), key, ...expected);
|
|
1586
|
+
return this;
|
|
1587
|
+
}
|
|
1588
|
+
assertInertiaFlashMissing(key) {
|
|
1589
|
+
AssertableInertia.assertFlashMissing(this.session().get("inertia.flash_data", {}), key);
|
|
1590
|
+
return this;
|
|
1591
|
+
}
|
|
889
1592
|
/** The response JSON equals `data` exactly (object key order is ignored). */
|
|
890
1593
|
assertExactJson(data) {
|
|
891
1594
|
const actual = this.json();
|
|
@@ -1303,7 +2006,7 @@ var HttpClient = class {
|
|
|
1303
2006
|
await app.boot();
|
|
1304
2007
|
setClientAddress(request, "127.0.0.1");
|
|
1305
2008
|
const scope = app.createScope();
|
|
1306
|
-
const context = { request, app };
|
|
2009
|
+
const context = { request, app, client: this };
|
|
1307
2010
|
const response = await scope.run(async () => {
|
|
1308
2011
|
await this.beforeRequest(scope, context);
|
|
1309
2012
|
this.previousUrl = void 0;
|
|
@@ -2585,7 +3288,7 @@ function guessMimeType(path) {
|
|
|
2585
3288
|
}
|
|
2586
3289
|
function hashName(file) {
|
|
2587
3290
|
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
2588
|
-
const name = [...
|
|
3291
|
+
const name = [...randomBytes2(40)].map((byte) => alphabet[byte % alphabet.length]).join("");
|
|
2589
3292
|
const extension = file.extension();
|
|
2590
3293
|
return extension === "" ? name : `${name}.${extension}`;
|
|
2591
3294
|
}
|
|
@@ -2894,6 +3597,12 @@ export {
|
|
|
2894
3597
|
ApplicationBuilder,
|
|
2895
3598
|
ProviderBootError,
|
|
2896
3599
|
ProviderRegisterError,
|
|
3600
|
+
ViteError,
|
|
3601
|
+
ViteHtml,
|
|
3602
|
+
Vite,
|
|
3603
|
+
currentVite,
|
|
3604
|
+
vite,
|
|
3605
|
+
viteReactRefresh,
|
|
2897
3606
|
Application2 as Application,
|
|
2898
3607
|
ClosureKernel,
|
|
2899
3608
|
PendingCommand,
|
|
@@ -2905,6 +3614,9 @@ export {
|
|
|
2905
3614
|
DatabaseTransactions,
|
|
2906
3615
|
TESTING_ENVIRONMENT,
|
|
2907
3616
|
applyEnvironment,
|
|
3617
|
+
AssertableJson,
|
|
3618
|
+
inertiaPageOf,
|
|
3619
|
+
AssertableInertia,
|
|
2908
3620
|
cookiePrefix,
|
|
2909
3621
|
encryptCookie,
|
|
2910
3622
|
decryptCookie,
|
|
@@ -2938,4 +3650,4 @@ export {
|
|
|
2938
3650
|
StorageFake,
|
|
2939
3651
|
FakeFile
|
|
2940
3652
|
};
|
|
2941
|
-
//# sourceMappingURL=chunk-
|
|
3653
|
+
//# sourceMappingURL=chunk-UPZAML2Q.js.map
|