@jterrazz/test 18.2.0 → 18.3.0
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/README.md +2 -3
- package/dist/browser-shared-index.browser.js +1 -2
- package/dist/checker.js +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -2
- package/dist/index.d.ts +196 -194
- package/dist/index.js +1742 -1690
- package/dist/oxlint.cjs +5 -8
- package/dist/oxlint.d.cts +1 -1
- package/dist/oxlint.d.ts +1 -1
- package/dist/oxlint.js +1 -3
- package/dist/shared-exchange.js +1 -1
- package/dist/shared-in-place.js +1 -1
- package/dist/shared-manifest.js +4 -4
- package/dist/shared-route-coverage.global-setup.js +1 -1
- package/dist/shared-session-ledger.js +1 -1
- package/dist/shared-specifications.js +0 -1
- package/dist/shared-stub-server.js +13 -0
- package/dist/shared-testcontainers.adapter.js +1 -1
- package/dist/stubs.js +1 -1
- package/dist/vitest.d.ts +1 -6
- package/dist/vitest.js +2 -8
- package/docs/README.md +1 -2
- package/docs/concepts/architecture.md +15 -16
- package/docs/concepts/conventions.md +2 -2
- package/docs/guides/api-specs.md +172 -3
- package/docs/guides/component-specs.md +1 -1
- package/docs/guides/website-specs.md +1 -1
- package/docs/reference/assertions.md +2 -2
- package/docs/reference/glossary.md +1 -1
- package/docs/reference/linting.md +4 -4
- package/docs/reference/tokens.md +1 -1
- package/docs/start/getting-started.md +14 -15
- package/docs/start/set-up-a-project.md +2 -2
- package/package.json +1 -1
- package/docs/guides/deployment-specs.md +0 -265
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @jterrazz/test
|
|
2
2
|
|
|
3
|
-
A testing framework on vitest for whole products: HTTP APIs, background jobs, CLIs, websites,
|
|
3
|
+
A testing framework on vitest for whole products: HTTP APIs, background jobs, CLIs, websites, native mobile apps, rendered components, modules against real databases, and the lint rules a project ships. You declare what a test needs (Postgres, a built binary, a real Chromium, an iOS simulator), and the framework starts it, isolates it per worker and cleans it up. Each test is one sentence: a few setups, one action, and the whole result compared with `expect()`.
|
|
4
4
|
|
|
5
5
|
```typescript
|
|
6
6
|
// specs/api/users/list/shape.spec.ts
|
|
@@ -52,8 +52,7 @@ An ES module project on Node 24, vitest 5 and `@jterrazz/typescript` 11 is requi
|
|
|
52
52
|
| [Component](docs/guides/component-specs.md) | A React component, hook or DOM function in a real Chromium | `component.render()` |
|
|
53
53
|
| [Website](docs/guides/website-specs.md) | A served page, fetched or driven in a browser | `specification.website()` |
|
|
54
54
|
| [Mobile](docs/guides/mobile-specs.md) | A native app on an iOS simulator | `specification.mobile()` |
|
|
55
|
-
| [
|
|
56
|
-
| [API](docs/guides/api-specs.md) | An HTTP app, through complete requests | `specification.api()` |
|
|
55
|
+
| [API](docs/guides/api-specs.md) | An HTTP app, in this process or deployed at a `url` | `specification.api()` |
|
|
57
56
|
| [Job](docs/guides/job-specs.md) | A pipeline triggered by name | `specification.job()` |
|
|
58
57
|
| [CLI](docs/guides/cli-specs.md) | A binary in a fresh working directory, often as a YAML document | `specification.cli()` |
|
|
59
58
|
| [Lint](docs/guides/lint-specs.md) | The rules a project ships, over fixture trees | `specification.lint()` |
|
|
@@ -3211,11 +3211,10 @@ async function waitUntil(predicate, options = {}) {
|
|
|
3211
3211
|
}
|
|
3212
3212
|
//#endregion
|
|
3213
3213
|
//#region src/index.browser.ts
|
|
3214
|
-
/** The
|
|
3214
|
+
/** The seven constructors, present and refusing in a page. */
|
|
3215
3215
|
const specification = {
|
|
3216
3216
|
api: () => refuse("specification.api()"),
|
|
3217
3217
|
cli: () => refuse("specification.cli()"),
|
|
3218
|
-
deployment: () => refuse("specification.deployment()"),
|
|
3219
3218
|
integration: () => refuse("specification.integration()"),
|
|
3220
3219
|
job: () => refuse("specification.job()"),
|
|
3221
3220
|
lint: () => refuse("specification.lint()"),
|
package/dist/checker.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as parsedJson } from "./shared-json-shape.js";
|
|
2
1
|
import { t as CATALOGUE_CHAPTER } from "./shared-chapter.js";
|
|
2
|
+
import { n as parsedJson } from "./shared-json-shape.js";
|
|
3
3
|
import { i as findUnknownTokens, n as findKnownTokens, r as findMalformedRefs, t as TOKEN_KINDS } from "./shared-tokens.js";
|
|
4
4
|
import { a as RUN_KEYS, c as isRelativePath, o as SPEC_EXTENSION, s as SpecSyntaxError, t as DOCUMENT_KEYS } from "./shared-spec-grammar.js";
|
|
5
5
|
import { i as literalEnd, n as argumentsOf, o as openersAt, r as closingOf, s as skipString, t as argumentSpans } from "./shared-source-scan.js";
|
package/dist/config.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ type TestSettings = {
|
|
|
22
22
|
specifications?: readonly string[];
|
|
23
23
|
};
|
|
24
24
|
/** The helpers a project is built by, named by their specification. */
|
|
25
|
-
type TestSpecification = 'api' | 'cli' | 'component' | '
|
|
25
|
+
type TestSpecification = 'api' | 'cli' | 'component' | 'integration' | 'job' | 'lint' | 'mobile' | 'unit' | 'website';
|
|
26
26
|
/** What a declared project states beyond its derived one: the global setups it runs, the options its helper takes, and why. */
|
|
27
27
|
type TestProject = {
|
|
28
28
|
readonly reason: string;
|
package/dist/config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as isRecord } from "./shared-json-shape.js";
|
|
2
1
|
import { t as CATALOGUE_CHAPTER } from "./shared-chapter.js";
|
|
2
|
+
import { t as isRecord } from "./shared-json-shape.js";
|
|
3
3
|
import { n as specificationModules, t as derivedProjects } from "./shared-derived-projects.js";
|
|
4
4
|
import { t as TEST_SECTION } from "./shared-test-section.js";
|
|
5
5
|
import { n as recommendedRules, t as consumerRows } from "./shared-manifest.js";
|
|
@@ -13,7 +13,6 @@ var standard_default = defineStandard({ test: {
|
|
|
13
13
|
"api",
|
|
14
14
|
"cli",
|
|
15
15
|
"component",
|
|
16
|
-
"deployment",
|
|
17
16
|
"integration",
|
|
18
17
|
"job",
|
|
19
18
|
"lint",
|
package/dist/index.d.ts
CHANGED
|
@@ -307,6 +307,163 @@ declare class ResponseAccessor {
|
|
|
307
307
|
constructor(response: ServerResponse, testDir: string, captures?: CaptureScope, recording?: ResponseRecording);
|
|
308
308
|
}
|
|
309
309
|
//#endregion
|
|
310
|
+
//#region src/specifications/api/deployed/tls-facts.d.ts
|
|
311
|
+
/** The certificate an HTTPS exchange was presented, and what the client made of it. */
|
|
312
|
+
type TlsFacts = {
|
|
313
|
+
/** The names the certificate is valid for (its subjectAltName), each without its `DNS:` or `IP Address:` prefix. */
|
|
314
|
+
readonly altNames: readonly string[];
|
|
315
|
+
/** The code the trust check refused with (`DEPTH_ZERO_SELF_SIGNED_CERT`, `CERT_HAS_EXPIRED`, `ERR_TLS_CERT_ALTNAME_INVALID` ...), undefined when trusted. */
|
|
316
|
+
readonly authorizationError: string | undefined;
|
|
317
|
+
/** Whether the certificate chains to a trusted authority and covers the URL's host. */
|
|
318
|
+
readonly authorized: boolean;
|
|
319
|
+
/** Whole days from the exchange to `validTo`, negative once it has expired. */
|
|
320
|
+
readonly daysRemaining: number;
|
|
321
|
+
/** The issuer's common name, or its organisation when it states none. */
|
|
322
|
+
readonly issuer: string;
|
|
323
|
+
/** The TLS version negotiated (`TLSv1.3`). */
|
|
324
|
+
readonly protocol: string | undefined;
|
|
325
|
+
/** The subject's common name; empty when it states none. */
|
|
326
|
+
readonly subject: string;
|
|
327
|
+
readonly validFrom: Date;
|
|
328
|
+
readonly validTo: Date;
|
|
329
|
+
/** Whether the certificate is valid for `host`, wildcards read as a client reads them. */
|
|
330
|
+
covers: (host: string) => boolean;
|
|
331
|
+
};
|
|
332
|
+
//#endregion
|
|
333
|
+
//#region src/specifications/api/deployed/exchange.result.d.ts
|
|
334
|
+
/** What one request to a deployed api hands back: the response, or why none came, and the certificate it came over; no table and no disk, which a deployed api keeps to itself. */
|
|
335
|
+
declare class ExchangeResult {
|
|
336
|
+
private readonly answer;
|
|
337
|
+
private readonly recording;
|
|
338
|
+
private readonly scope;
|
|
339
|
+
private readonly testDir;
|
|
340
|
+
/** The certificate an https request was presented and the trust check's verdict; undefined over http, or when no handshake completed. */
|
|
341
|
+
readonly tls: TlsFacts | undefined;
|
|
342
|
+
constructor(options: {
|
|
343
|
+
recording: ResponseRecording;
|
|
344
|
+
response: ServerResponse;
|
|
345
|
+
testDir: string;
|
|
346
|
+
tls: TlsFacts | undefined;
|
|
347
|
+
});
|
|
348
|
+
/** The whole response (status, headers, body), or `unreachable: <reason>`, compared whole: `toMatch(<.http text>)` or `toMatch(file(...))`. */
|
|
349
|
+
get response(): ResponseAccessor;
|
|
350
|
+
}
|
|
351
|
+
//#endregion
|
|
352
|
+
//#region src/chain/action.d.ts
|
|
353
|
+
type SliceReader = <Slice>(capability: {
|
|
354
|
+
readonly initial: Slice;
|
|
355
|
+
readonly name: string;
|
|
356
|
+
}) => Slice;
|
|
357
|
+
type Action<Name extends string, Args extends readonly unknown[], Result, Signature extends ChainSignature = ChainSignature, Needs extends object = Record<never, never>, Config extends ChainConfig = ChainConfig> = {
|
|
358
|
+
readonly accessors: readonly MatrixRow[];
|
|
359
|
+
readonly targets?: readonly MatrixRow[];
|
|
360
|
+
readonly kind: 'action';
|
|
361
|
+
readonly name: Name;
|
|
362
|
+
readonly options?: readonly ActionOption<string>[];
|
|
363
|
+
readonly row: MatrixRow;
|
|
364
|
+
/** A type alone, never set at runtime: `ChainOf` reads it. */
|
|
365
|
+
readonly signature?: Signature;
|
|
366
|
+
readonly verbs?: readonly MatrixRow[];
|
|
367
|
+
prepare?(args: Args, read: SliceReader): Promise<{
|
|
368
|
+
readonly workDir: null | string;
|
|
369
|
+
}> | {
|
|
370
|
+
readonly workDir: null | string;
|
|
371
|
+
};
|
|
372
|
+
perform(args: Args, read: SliceReader, adapters: Needs, run: Run<Config>): Promise<Result>;
|
|
373
|
+
};
|
|
374
|
+
type AnyAction = Action<string, readonly unknown[], unknown, ChainSignature, object>;
|
|
375
|
+
//#endregion
|
|
376
|
+
//#region src/specifications/api/deployed/request.action.d.ts
|
|
377
|
+
type ExchangeSignature = ChainSignature & {
|
|
378
|
+
readonly chain: {
|
|
379
|
+
/** Send a GET to a URL, written whole or as a path from the specification's `url`, and resolve with what came back. */
|
|
380
|
+
get: (target: string) => Promise<ExchangeResult>;
|
|
381
|
+
/** Send a complete request: its `.http` text written in the test, or `file('./__requests__/<name>.http')`; its first line names the URL whole or a path. */
|
|
382
|
+
request: (source: DiskFile<'.http'> | string) => Promise<ExchangeResult>;
|
|
383
|
+
};
|
|
384
|
+
};
|
|
385
|
+
//#endregion
|
|
386
|
+
//#region src/specifications/api/deployed/connect.capability.d.ts
|
|
387
|
+
type ConnectChain<Self> = {
|
|
388
|
+
/** Open the socket on this address instead of the URL's host and port, as curl's `--connect-to`: the Host header and the TLS server name stay the URL's; a later call wins. */
|
|
389
|
+
connect: (address: string) => Self;
|
|
390
|
+
};
|
|
391
|
+
interface ConnectSignature extends ChainSignature {
|
|
392
|
+
readonly chain: ConnectChain<this['self']>;
|
|
393
|
+
}
|
|
394
|
+
//#endregion
|
|
395
|
+
//#region src/chain/context/headers.capability.d.ts
|
|
396
|
+
type HeadersMethod<Self> = (headers: Record<string, string>) => Self;
|
|
397
|
+
type HeadersChain<Self> = {
|
|
398
|
+
/** Set HTTP headers for the exchange. Multiple calls merge. */
|
|
399
|
+
headers: HeadersMethod<Self>;
|
|
400
|
+
};
|
|
401
|
+
interface HeadersSignature extends ChainSignature {
|
|
402
|
+
readonly chain: HeadersChain<this['self']>;
|
|
403
|
+
}
|
|
404
|
+
//#endregion
|
|
405
|
+
//#region src/chain/define-specification.d.ts
|
|
406
|
+
type Composition = {
|
|
407
|
+
readonly actions: readonly AnyAction[];
|
|
408
|
+
readonly capabilities: readonly (AnyCapability | Sharing)[];
|
|
409
|
+
readonly options: Readonly<Record<string, MatrixRow>>;
|
|
410
|
+
};
|
|
411
|
+
//#endregion
|
|
412
|
+
//#region src/chain/chain.d.ts
|
|
413
|
+
type Names<List extends readonly {
|
|
414
|
+
readonly name: string;
|
|
415
|
+
}[]> = List[number]['name'];
|
|
416
|
+
type ContextOf<C extends Composition> = C['capabilities'][number] extends (infer Member) ? Member extends Capability<string, infer _Slice, infer _Args, infer _Signature, infer _Needs, infer Key> ? Key : never : never;
|
|
417
|
+
type SharingOf<C extends Composition, Self> = 'with' extends Names<C['capabilities']> ? {
|
|
418
|
+
with: (context: Pick<ChainContext, ContextOf<C>>) => Self;
|
|
419
|
+
} : unknown;
|
|
420
|
+
type MethodsOf<Member, P extends SpecificationParams, Self> = Member extends {
|
|
421
|
+
readonly signature?: infer Signature;
|
|
422
|
+
} ? Signature extends ChainSignature ? (Signature & {
|
|
423
|
+
readonly params: P;
|
|
424
|
+
readonly self: Self;
|
|
425
|
+
})['chain'] : never : never;
|
|
426
|
+
type Methods<C extends Composition, P extends SpecificationParams, Self> = Intersect<MethodsOf<C['actions'][number] | C['capabilities'][number], P, Self>>;
|
|
427
|
+
type ChainOf<C extends Composition, P extends SpecificationParams, Self> = Pick<Methods<C, P, Self>, Extract<Names<C['actions']> | Names<C['capabilities']>, keyof Methods<C, P, Self>>> & SharingOf<C, Self>;
|
|
428
|
+
//#endregion
|
|
429
|
+
//#region src/specifications/api/deployed/deployed.composition.d.ts
|
|
430
|
+
declare const composition$8: {
|
|
431
|
+
readonly actions: readonly [Action<"request", [source: string | DiskFile<".http">], ExchangeResult, ExchangeSignature, Record<never, never>, ApiDeployedConfig>, Action<"get", [target: string], ExchangeResult, ExchangeSignature, Record<never, never>, ApiDeployedConfig>];
|
|
432
|
+
readonly capabilities: readonly [Capability<"connect", string | null, [address: string], ConnectSignature, Record<never, never>, never, ChainConfig>, Capability<"headers", Readonly<Record<string, string>>, [headers: Record<string, string>], HeadersSignature, Record<never, never>, "headers", ChainConfig>, Sharing];
|
|
433
|
+
readonly options: {
|
|
434
|
+
ca: {
|
|
435
|
+
group: "Constructor option";
|
|
436
|
+
name: string;
|
|
437
|
+
probe: string;
|
|
438
|
+
};
|
|
439
|
+
insecure: {
|
|
440
|
+
group: "Constructor option";
|
|
441
|
+
name: string;
|
|
442
|
+
probe: string;
|
|
443
|
+
};
|
|
444
|
+
recordedHeaders: {
|
|
445
|
+
group: "Constructor option";
|
|
446
|
+
name: string;
|
|
447
|
+
probe: string;
|
|
448
|
+
};
|
|
449
|
+
timeout: {
|
|
450
|
+
group: "Constructor option";
|
|
451
|
+
name: string;
|
|
452
|
+
probe: string;
|
|
453
|
+
};
|
|
454
|
+
url: {
|
|
455
|
+
group: "Constructor option";
|
|
456
|
+
name: string;
|
|
457
|
+
probe: string;
|
|
458
|
+
};
|
|
459
|
+
};
|
|
460
|
+
};
|
|
461
|
+
/** The chain `specification.api({ url })` hands out: requests to the deployed api, over the network. */
|
|
462
|
+
interface ApiDeployedSpecification extends ChainOf<typeof composition$8, {
|
|
463
|
+
databaseKey: string;
|
|
464
|
+
services: Record<string, unknown>;
|
|
465
|
+
}, ApiDeployedSpecification> {}
|
|
466
|
+
//#endregion
|
|
310
467
|
//#region src/specifications/api/server/server.port.d.ts
|
|
311
468
|
/** What a request carries beside its method, path and body. */
|
|
312
469
|
type ServerRequestOptions = {
|
|
@@ -347,30 +504,6 @@ type HonoApp = {
|
|
|
347
504
|
routes?: readonly TableEntry[];
|
|
348
505
|
};
|
|
349
506
|
//#endregion
|
|
350
|
-
//#region src/chain/action.d.ts
|
|
351
|
-
type SliceReader = <Slice>(capability: {
|
|
352
|
-
readonly initial: Slice;
|
|
353
|
-
readonly name: string;
|
|
354
|
-
}) => Slice;
|
|
355
|
-
type Action<Name extends string, Args extends readonly unknown[], Result, Signature extends ChainSignature = ChainSignature, Needs extends object = Record<never, never>, Config extends ChainConfig = ChainConfig> = {
|
|
356
|
-
readonly accessors: readonly MatrixRow[];
|
|
357
|
-
readonly targets?: readonly MatrixRow[];
|
|
358
|
-
readonly kind: 'action';
|
|
359
|
-
readonly name: Name;
|
|
360
|
-
readonly options?: readonly ActionOption<string>[];
|
|
361
|
-
readonly row: MatrixRow;
|
|
362
|
-
/** A type alone, never set at runtime: `ChainOf` reads it. */
|
|
363
|
-
readonly signature?: Signature;
|
|
364
|
-
readonly verbs?: readonly MatrixRow[];
|
|
365
|
-
prepare?(args: Args, read: SliceReader): Promise<{
|
|
366
|
-
readonly workDir: null | string;
|
|
367
|
-
}> | {
|
|
368
|
-
readonly workDir: null | string;
|
|
369
|
-
};
|
|
370
|
-
perform(args: Args, read: SliceReader, adapters: Needs, run: Run<Config>): Promise<Result>;
|
|
371
|
-
};
|
|
372
|
-
type AnyAction = Action<string, readonly unknown[], unknown, ChainSignature, object>;
|
|
373
|
-
//#endregion
|
|
374
507
|
//#region src/specifications/api/request/route.d.ts
|
|
375
508
|
type RouteParamNames<Path extends string> = Path extends `${infer Route}?${string}` ? RouteParamNames<Route> : Path extends `${string}/:${infer Rest}` ? Rest extends `${infer Name}/${infer Tail}` ? Name | RouteParamNames<`/${Tail}`> : Rest : never;
|
|
376
509
|
type RouteOptions<Path extends string> = [RouteParamNames<Path>] extends [never] ? {
|
|
@@ -415,16 +548,6 @@ interface ClockSignature extends ChainSignature {
|
|
|
415
548
|
readonly chain: ClockChain<this['self']>;
|
|
416
549
|
}
|
|
417
550
|
//#endregion
|
|
418
|
-
//#region src/chain/context/headers.capability.d.ts
|
|
419
|
-
type HeadersMethod<Self> = (headers: Record<string, string>) => Self;
|
|
420
|
-
type HeadersChain<Self> = {
|
|
421
|
-
/** Set HTTP headers for the exchange. Multiple calls merge. */
|
|
422
|
-
headers: HeadersMethod<Self>;
|
|
423
|
-
};
|
|
424
|
-
interface HeadersSignature extends ChainSignature {
|
|
425
|
-
readonly chain: HeadersChain<this['self']>;
|
|
426
|
-
}
|
|
427
|
-
//#endregion
|
|
428
551
|
//#region src/stubs/intercept/intercept.port.d.ts
|
|
429
552
|
type InterceptPort = {
|
|
430
553
|
/** Refuse the setup when this adapter cannot serve a stub at all. */
|
|
@@ -453,32 +576,8 @@ type SeedPort = {
|
|
|
453
576
|
readonly target: (database?: string) => DatabasePort;
|
|
454
577
|
};
|
|
455
578
|
//#endregion
|
|
456
|
-
//#region src/chain/define-specification.d.ts
|
|
457
|
-
type Composition = {
|
|
458
|
-
readonly actions: readonly AnyAction[];
|
|
459
|
-
readonly capabilities: readonly (AnyCapability | Sharing)[];
|
|
460
|
-
readonly options: Readonly<Record<string, MatrixRow>>;
|
|
461
|
-
};
|
|
462
|
-
//#endregion
|
|
463
|
-
//#region src/chain/chain.d.ts
|
|
464
|
-
type Names<List extends readonly {
|
|
465
|
-
readonly name: string;
|
|
466
|
-
}[]> = List[number]['name'];
|
|
467
|
-
type ContextOf<C extends Composition> = C['capabilities'][number] extends (infer Member) ? Member extends Capability<string, infer _Slice, infer _Args, infer _Signature, infer _Needs, infer Key> ? Key : never : never;
|
|
468
|
-
type SharingOf<C extends Composition, Self> = 'with' extends Names<C['capabilities']> ? {
|
|
469
|
-
with: (context: Pick<ChainContext, ContextOf<C>>) => Self;
|
|
470
|
-
} : unknown;
|
|
471
|
-
type MethodsOf<Member, P extends SpecificationParams, Self> = Member extends {
|
|
472
|
-
readonly signature?: infer Signature;
|
|
473
|
-
} ? Signature extends ChainSignature ? (Signature & {
|
|
474
|
-
readonly params: P;
|
|
475
|
-
readonly self: Self;
|
|
476
|
-
})['chain'] : never : never;
|
|
477
|
-
type Methods<C extends Composition, P extends SpecificationParams, Self> = Intersect<MethodsOf<C['actions'][number] | C['capabilities'][number], P, Self>>;
|
|
478
|
-
type ChainOf<C extends Composition, P extends SpecificationParams, Self> = Pick<Methods<C, P, Self>, Extract<Names<C['actions']> | Names<C['capabilities']>, keyof Methods<C, P, Self>>> & SharingOf<C, Self>;
|
|
479
|
-
//#endregion
|
|
480
579
|
//#region src/specifications/api/api.composition.d.ts
|
|
481
|
-
declare const composition$
|
|
580
|
+
declare const composition$7: {
|
|
482
581
|
readonly actions: readonly [Action<"request", [source: string | DiskFile<".http">], HttpResult, RequestSignature, {
|
|
483
582
|
server: ServerPort;
|
|
484
583
|
}, ChainConfig>, Action<"get", [path: string, options?: RouteOptionsAny], HttpResult, RequestSignature, {
|
|
@@ -521,14 +620,14 @@ declare const composition$8: {
|
|
|
521
620
|
};
|
|
522
621
|
};
|
|
523
622
|
/** The chain `specification.api()` hands out; the app answers in this process (`server-sees-declared-services`). */
|
|
524
|
-
interface ApiSpecification<DatabaseKey extends string = string> extends ChainOf<typeof composition$
|
|
623
|
+
interface ApiSpecification<DatabaseKey extends string = string> extends ChainOf<typeof composition$7, {
|
|
525
624
|
databaseKey: DatabaseKey;
|
|
526
625
|
services: Record<string, unknown>;
|
|
527
626
|
}, ApiSpecification<DatabaseKey>> {}
|
|
528
627
|
//#endregion
|
|
529
628
|
//#region src/specifications/api/api.handle.d.ts
|
|
530
|
-
/**
|
|
531
|
-
type
|
|
629
|
+
/** The app built in this process, from the services the specification starts. */
|
|
630
|
+
type ApiServedOptions<Services extends ServiceRecord = ServiceRecord> = {
|
|
532
631
|
/** Project root override; by default the nearest `package.json` above the specification file (`no-redundant-root`). */
|
|
533
632
|
root?: string;
|
|
534
633
|
/** The app factory: receives the started services record, returns the Hono app. */
|
|
@@ -536,7 +635,30 @@ type ApiSpecificationOptions<Services extends ServiceRecord = ServiceRecord> = {
|
|
|
536
635
|
/** Named infrastructure record: the keys are the `database` vocabulary, and name the init-script folder. */
|
|
537
636
|
services?: Services;
|
|
538
637
|
};
|
|
539
|
-
/**
|
|
638
|
+
/** The api already deployed, met over the network at its URL. */
|
|
639
|
+
type ApiDeployedOptions = {
|
|
640
|
+
/** A certificate authority trusted beside the ones node trusts: its PEM text, a value like any string. */
|
|
641
|
+
ca?: string;
|
|
642
|
+
/** Accept a certificate the trust check refuses (self-signed, expired, another host's); `result.tls` still says why. Default `false`. */
|
|
643
|
+
insecure?: boolean;
|
|
644
|
+
/** The headers update mode records into a golden that states none yet, those the response carries. Default `['content-type', 'location']`. */
|
|
645
|
+
recordedHeaders?: readonly string[];
|
|
646
|
+
/** The milliseconds one request may take, connection to last byte, before it reads `unreachable: timeout`. Default `5000`. */
|
|
647
|
+
timeout?: number;
|
|
648
|
+
/** The deployed api's base URL: a path is read from it (`.get('/health')`), a URL written whole reaches any host. */
|
|
649
|
+
url: string;
|
|
650
|
+
};
|
|
651
|
+
type Absent<Options> = { [Key in keyof Options]?: never; };
|
|
652
|
+
/** Options for {@link startApi | specification.api}: `server` or `url`, exclusive by type. */
|
|
653
|
+
type ApiSpecificationOptions<Services extends ServiceRecord = ServiceRecord> = (Absent<ApiDeployedOptions> & ApiServedOptions<Services>) | (Absent<ApiServedOptions> & ApiDeployedOptions);
|
|
654
|
+
type ApiDeployedConfig = ChainConfig & {
|
|
655
|
+
baseUrl: string;
|
|
656
|
+
ca: string | undefined;
|
|
657
|
+
insecure: boolean;
|
|
658
|
+
recording: ResponseRecording;
|
|
659
|
+
timeout: number;
|
|
660
|
+
};
|
|
661
|
+
/** What `specification.api({ server })` returns: `const { api, cleanup, docker } = ...` (`no-runner-alias`). */
|
|
540
662
|
type ApiHandle<DatabaseKey extends string = string> = {
|
|
541
663
|
api: ApiSpecification<DatabaseKey>;
|
|
542
664
|
/** Stop all infrastructure started by this specification. */
|
|
@@ -544,7 +666,13 @@ type ApiHandle<DatabaseKey extends string = string> = {
|
|
|
544
666
|
/** Read a running container by id. */
|
|
545
667
|
docker: (containerId: string) => ContainerAccessor;
|
|
546
668
|
};
|
|
547
|
-
|
|
669
|
+
/** What `specification.api({ url })` returns: `const { api, cleanup } = ...`; it starts nothing, so `cleanup` releases nothing and there is no container to read. */
|
|
670
|
+
type ApiDeployedHandle = {
|
|
671
|
+
api: ApiDeployedSpecification;
|
|
672
|
+
cleanup: () => Promise<void>;
|
|
673
|
+
};
|
|
674
|
+
declare function startApi(options: Absent<ApiServedOptions> & ApiDeployedOptions): Promise<ApiDeployedHandle>;
|
|
675
|
+
declare function startApi<Services extends ServiceRecord = ServiceRecord>(options: Absent<ApiDeployedOptions> & ApiServedOptions<Services>): Promise<ApiHandle<DatabaseKeys<Services>>>;
|
|
548
676
|
//#endregion
|
|
549
677
|
//#region src/services/startup/startup-report.d.ts
|
|
550
678
|
type AppInfo = {
|
|
@@ -733,7 +861,7 @@ interface PrepareSignature extends ChainSignature {
|
|
|
733
861
|
}
|
|
734
862
|
//#endregion
|
|
735
863
|
//#region src/specifications/cli/cli.composition.d.ts
|
|
736
|
-
declare const composition$
|
|
864
|
+
declare const composition$6: {
|
|
737
865
|
readonly actions: readonly [Action<"exec", [args?: string | string[], options?: ExecOptions], CliResult, ExecSignature, {
|
|
738
866
|
command: CliPort;
|
|
739
867
|
}, CliConfig>, Action<"run", [document: DiskFile<".spec.yaml">, options?: LiterateRunFlags], CliResult, RunSignature$1, Record<never, never>, CliConfig>];
|
|
@@ -806,7 +934,7 @@ declare const composition$7: {
|
|
|
806
934
|
};
|
|
807
935
|
};
|
|
808
936
|
/** The chain `specification.cli()` hands out: a binary run in a fresh, empty working directory, in its own process. */
|
|
809
|
-
interface CliSpecification<DatabaseKey extends string = string> extends ChainOf<typeof composition$
|
|
937
|
+
interface CliSpecification<DatabaseKey extends string = string> extends ChainOf<typeof composition$6, {
|
|
810
938
|
databaseKey: DatabaseKey;
|
|
811
939
|
services: Record<string, unknown>;
|
|
812
940
|
}, CliSpecification<DatabaseKey>> {}
|
|
@@ -874,131 +1002,6 @@ type CliHandle<DatabaseKey extends string = string> = {
|
|
|
874
1002
|
};
|
|
875
1003
|
declare function startCli<Services extends ServiceRecord>(bin: string, options?: CliSpecificationOptions<Services>): Promise<CliHandle<DatabaseKeys<Services>>>;
|
|
876
1004
|
//#endregion
|
|
877
|
-
//#region src/specifications/deployment/exchange/tls-facts.d.ts
|
|
878
|
-
/** The certificate an HTTPS exchange was presented, and what the client made of it. */
|
|
879
|
-
type TlsFacts = {
|
|
880
|
-
/** The names the certificate is valid for (its subjectAltName), each without its `DNS:` or `IP Address:` prefix. */
|
|
881
|
-
readonly altNames: readonly string[];
|
|
882
|
-
/** The code the trust check refused with (`DEPTH_ZERO_SELF_SIGNED_CERT`, `CERT_HAS_EXPIRED`, `ERR_TLS_CERT_ALTNAME_INVALID` ...), undefined when trusted. */
|
|
883
|
-
readonly authorizationError: string | undefined;
|
|
884
|
-
/** Whether the certificate chains to a trusted authority and covers the URL's host. */
|
|
885
|
-
readonly authorized: boolean;
|
|
886
|
-
/** Whole days from the exchange to `validTo`, negative once it has expired. */
|
|
887
|
-
readonly daysRemaining: number;
|
|
888
|
-
/** The issuer's common name, or its organisation when it states none. */
|
|
889
|
-
readonly issuer: string;
|
|
890
|
-
/** The TLS version negotiated (`TLSv1.3`). */
|
|
891
|
-
readonly protocol: string | undefined;
|
|
892
|
-
/** The subject's common name; empty when it states none. */
|
|
893
|
-
readonly subject: string;
|
|
894
|
-
readonly validFrom: Date;
|
|
895
|
-
readonly validTo: Date;
|
|
896
|
-
/** Whether the certificate is valid for `host`, wildcards read as a client reads them. */
|
|
897
|
-
covers: (host: string) => boolean;
|
|
898
|
-
};
|
|
899
|
-
//#endregion
|
|
900
|
-
//#region src/specifications/deployment/exchange/exchange.result.d.ts
|
|
901
|
-
/** What one exchange with a deployment hands back: the response, or why none came, and the certificate it was presented. */
|
|
902
|
-
declare class ExchangeResult extends BaseResult {
|
|
903
|
-
private readonly answer;
|
|
904
|
-
private readonly recording;
|
|
905
|
-
/** The certificate an https exchange was presented and the trust check's verdict; undefined over http, or when no handshake completed. */
|
|
906
|
-
readonly tls: TlsFacts | undefined;
|
|
907
|
-
constructor(options: BaseResultOptions & {
|
|
908
|
-
recording: ResponseRecording;
|
|
909
|
-
response: ServerResponse;
|
|
910
|
-
tls: TlsFacts | undefined;
|
|
911
|
-
});
|
|
912
|
-
/** The whole response (status, headers, body), or `unreachable: <reason>`, compared whole: `toMatch(<.http text>)` or `toMatch(file(...))`. */
|
|
913
|
-
get response(): ResponseAccessor;
|
|
914
|
-
}
|
|
915
|
-
//#endregion
|
|
916
|
-
//#region src/specifications/deployment/exchange/request.action.d.ts
|
|
917
|
-
type ExchangeSignature = ChainSignature & {
|
|
918
|
-
readonly chain: {
|
|
919
|
-
/** Send a GET to a URL, written whole or as a path from the specification's `url`, and resolve with what came back. */
|
|
920
|
-
get: (target: string) => Promise<ExchangeResult>;
|
|
921
|
-
/** Send a complete request: its `.http` text written in the test, or `file('./__requests__/<name>.http')`; its first line names the URL whole or a path. */
|
|
922
|
-
request: (source: DiskFile<'.http'> | string) => Promise<ExchangeResult>;
|
|
923
|
-
};
|
|
924
|
-
};
|
|
925
|
-
//#endregion
|
|
926
|
-
//#region src/specifications/deployment/exchange/connect.capability.d.ts
|
|
927
|
-
type ConnectChain<Self> = {
|
|
928
|
-
/** Open the socket on this address instead of the URL's host and port, as curl's `--connect-to`: the Host header and the TLS server name stay the URL's; a later call wins. */
|
|
929
|
-
connect: (address: string) => Self;
|
|
930
|
-
};
|
|
931
|
-
interface ConnectSignature extends ChainSignature {
|
|
932
|
-
readonly chain: ConnectChain<this['self']>;
|
|
933
|
-
}
|
|
934
|
-
//#endregion
|
|
935
|
-
//#region src/specifications/deployment/deployment.composition.d.ts
|
|
936
|
-
declare const composition$6: {
|
|
937
|
-
readonly actions: readonly [Action<"request", [source: string | DiskFile<".http">], ExchangeResult, ExchangeSignature, Record<never, never>, DeploymentConfig>, Action<"get", [target: string], ExchangeResult, ExchangeSignature, Record<never, never>, DeploymentConfig>];
|
|
938
|
-
readonly capabilities: readonly [Capability<"connect", string | null, [address: string], ConnectSignature, Record<never, never>, never, ChainConfig>, Capability<"headers", Readonly<Record<string, string>>, [headers: Record<string, string>], HeadersSignature, Record<never, never>, "headers", ChainConfig>, Sharing];
|
|
939
|
-
readonly options: {
|
|
940
|
-
ca: {
|
|
941
|
-
group: "Constructor option";
|
|
942
|
-
name: string;
|
|
943
|
-
probe: string;
|
|
944
|
-
};
|
|
945
|
-
insecure: {
|
|
946
|
-
group: "Constructor option";
|
|
947
|
-
name: string;
|
|
948
|
-
probe: string;
|
|
949
|
-
};
|
|
950
|
-
recordedHeaders: {
|
|
951
|
-
group: "Constructor option";
|
|
952
|
-
name: string;
|
|
953
|
-
probe: string;
|
|
954
|
-
};
|
|
955
|
-
timeout: {
|
|
956
|
-
group: "Constructor option";
|
|
957
|
-
name: string;
|
|
958
|
-
probe: string;
|
|
959
|
-
};
|
|
960
|
-
url: {
|
|
961
|
-
group: "Constructor option";
|
|
962
|
-
name: string;
|
|
963
|
-
probe: string;
|
|
964
|
-
};
|
|
965
|
-
};
|
|
966
|
-
};
|
|
967
|
-
/** The chain `specification.deployment()` hands out: one HTTP exchange with a running deployment, over the network. */
|
|
968
|
-
interface DeploymentSpecification extends ChainOf<typeof composition$6, {
|
|
969
|
-
databaseKey: string;
|
|
970
|
-
services: Record<string, unknown>;
|
|
971
|
-
}, DeploymentSpecification> {}
|
|
972
|
-
//#endregion
|
|
973
|
-
//#region src/specifications/deployment/deployment.handle.d.ts
|
|
974
|
-
/** Options for {@link startDeployment | specification.deployment}. */
|
|
975
|
-
type DeploymentSpecificationOptions = {
|
|
976
|
-
/** A certificate authority trusted beside the ones node trusts: its PEM text, a value like any string. */
|
|
977
|
-
ca?: string;
|
|
978
|
-
/** Accept a certificate the trust check refuses (self-signed, expired, another host's); `result.tls` still says why. Default `false`. */
|
|
979
|
-
insecure?: boolean;
|
|
980
|
-
/** The headers update mode records into a golden that states none yet, those the response carries. Default `['content-type', 'location']`. */
|
|
981
|
-
recordedHeaders?: readonly string[];
|
|
982
|
-
/** The milliseconds one exchange may take, connection to last byte, before it reads `unreachable: timeout`. Default `5000`. */
|
|
983
|
-
timeout?: number;
|
|
984
|
-
/** The base URL a path is read from (`.get('/health')`); a URL written whole needs none. */
|
|
985
|
-
url?: string;
|
|
986
|
-
};
|
|
987
|
-
type DeploymentConfig = ChainConfig & {
|
|
988
|
-
baseUrl: string | undefined;
|
|
989
|
-
ca: string | undefined;
|
|
990
|
-
insecure: boolean;
|
|
991
|
-
recording: ResponseRecording;
|
|
992
|
-
timeout: number;
|
|
993
|
-
};
|
|
994
|
-
/** What `specification.deployment()` returns: `const { deployment, cleanup } = ...` (`no-runner-alias`). */
|
|
995
|
-
type DeploymentHandle = {
|
|
996
|
-
/** Starts nothing, so releases nothing: passed to `afterAll` like every specification's. */
|
|
997
|
-
cleanup: () => Promise<void>;
|
|
998
|
-
deployment: DeploymentSpecification;
|
|
999
|
-
};
|
|
1000
|
-
declare function startDeployment(options?: DeploymentSpecificationOptions): Promise<DeploymentHandle>;
|
|
1001
|
-
//#endregion
|
|
1002
1005
|
//#region src/specifications/integration/call.result.d.ts
|
|
1003
1006
|
type CallOutcome = {
|
|
1004
1007
|
error: unknown;
|
|
@@ -1690,11 +1693,10 @@ type WebsiteHandle = {
|
|
|
1690
1693
|
declare function startWebsite<Services extends ServiceRecord>(options: WebsiteSpecificationOptions<Services>): Promise<WebsiteHandle>;
|
|
1691
1694
|
//#endregion
|
|
1692
1695
|
//#region src/specifications/specification.d.ts
|
|
1693
|
-
/** The
|
|
1696
|
+
/** The seven constructors, and only seven: the framework's whole entry surface. */
|
|
1694
1697
|
type Specification = {
|
|
1695
1698
|
api: typeof startApi;
|
|
1696
1699
|
cli: typeof startCli;
|
|
1697
|
-
deployment: typeof startDeployment;
|
|
1698
1700
|
integration: typeof startIntegration;
|
|
1699
1701
|
job: typeof startJob;
|
|
1700
1702
|
lint: typeof startLint;
|
|
@@ -2051,5 +2053,5 @@ declare module 'vitest' {
|
|
|
2051
2053
|
}
|
|
2052
2054
|
}
|
|
2053
2055
|
//#endregion
|
|
2054
|
-
export { type ApiHandle, type ApiSpecification, type ApiSpecificationOptions, type BaseResult, type BrowserConsoleMessage, type BrowserLinkElement, type BrowserMetaElement, type BrowserOpenOptions, type BrowserPage, type BrowserPort, type CallResult, type CaptureScope, type CliEnv, type CliHandle, type CliInput, type CliOutput, type CliPort, type CliResult, type CliSpecification, type CliSpecificationOptions, type ComponentChain, type ComponentScenario, type ComponentUi, type ComponentVisitor, type ContainerAccessor, type
|
|
2056
|
+
export { type ApiDeployedHandle, type ApiDeployedOptions, type ApiDeployedSpecification, type ApiHandle, type ApiServedOptions, type ApiSpecification, type ApiSpecificationOptions, type BaseResult, type BrowserConsoleMessage, type BrowserLinkElement, type BrowserMetaElement, type BrowserOpenOptions, type BrowserPage, type BrowserPort, type CallResult, type CaptureScope, type CliEnv, type CliHandle, type CliInput, type CliOutput, type CliPort, type CliResult, type CliSpecification, type CliSpecificationOptions, type ComponentChain, type ComponentScenario, type ComponentUi, type ComponentVisitor, type ContainerAccessor, type DeviceOpenOptions, type DevicePort, type DeviceScreen, type DeviceTimeouts, type DirectoryAccessor, type DiskDirectory, type DiskFile, type DiskTarget, type DockerSpecConfig, type DomMount, type ElementKind, type ElementMatch, type ExchangeResult, type ExecOptions, type FetchResult, type FileAccessor, type FileAt, type FilesystemAccessor, type HonoApp, type HttpResult, type IntegrationHandle, type IntegrationSpecification, type IntegrationSpecificationOptions, type Job, type JobHandle, type JobResult, type JobSpecification, type JobSpecificationOptions, type JsonAccessor, type LandmarkKind, type LintConfig, type LintHandle, type LintResult, type LintRules, type LintRunOptions, type LintSpecification, type LintSpecificationOptions, type LiterateRunFlags, type LiterateServeRegistration, type MatchFixtureOptions, Matcher, type MatcherKind, type MobileBackendOptions, type MobileElementKind, type MobileElementMatch, type MobileHandle, type MobileScenario, type MobileSpecification, type MobileSpecificationOptions, type MobileVisitor, type MockOfOptions, type MockPort, type PackedPackage, type PageResult, type PinnedClock, type PositionedCases, type PositionedRuleTester, type PrepareStep, type RelativePath, type RenderResult, type RenderSubject, type RenderedText, type ResponseAccessor, type ScreenNode, type ScreenResult, type ServerPort, type ServerRequestOptions, type ServerResponse, type ServerSpec, type SpecDocument, type SpecEnvToken, type SpecFileAssertion, type SpecFixture, type SpecRun, type SpecServeEntry, type SpecStream, type TableAccessor, type Target, type TargetOptions, type TextAccessor, type TlsFacts, type VisitScenario, type WaitUntilOptions, type WebsiteBackendOptions, type WebsiteHandle, type WebsiteSpecification, type WebsiteSpecificationOptions, type WebsiteVisitor, directory, file, match };
|
|
2055
2057
|
//# sourceMappingURL=index.d.ts.map
|