- Add JSDoc to every exported member flagged by `deno doc --lint` across the `@nzip/lofi/testing` surface (convergence, fixture, readiness, browser_error): 35 missing-jsdoc → 0. Remaining `private-type-ref` findings are inherent to exposing Playwright's `Page`/`Browser` types and do not block publish. - Bump version 0.1.0 → 0.1.1 across the invariant: deno.json, package/version.ts (LOFI_VERSION), apps/reference/deno.json jsr pins + lock, and the create_core_test assertions; regenerate the starter snapshot.
- commit
- 5430d6164fb4f2cf07c5c83eaca4954598136bf0
- parent
- 6f16b4edd640c113df88ce16fa34362000eac380
- author
- Dami <dami.etoile@gmail.com>
| M | apps/ | 14 | +++++++------- |
| M | apps/ | 28 | ++++------------------------ |
| M | deno.json | 2 | +- |
| M | package/ | 6 | +++--- |
| M | package/ | 2 | +- |
| M | package/ | 5 | +++++ |
| M | package/ | 24 | +++++++++++++++++++++++- |
| M | package/ | 15 | +++++++++++++++ |
| M | package/ | 6 | ++++++ |
| M | package/ | 2 | +- |
@@ -2,13 +2,13 @@
22 "imports": {33 "@astrojs/check": "npm:@astrojs/check@0.9.9",44 "@astrojs/preact": "npm:@astrojs/preact@6.0.1",5- "@nzip/lofi/": "jsr:@nzip/lofi@0.1.0/",6- "@nzip/lofi/build": "jsr:@nzip/lofi@0.1.0/build",7- "@nzip/lofi/dev": "jsr:@nzip/lofi@0.1.0/dev",8- "@nzip/lofi/doctor": "jsr:@nzip/lofi@0.1.0/doctor",9- "@nzip/lofi/preview": "jsr:@nzip/lofi@0.1.0/preview",10- "@nzip/lofi/test": "jsr:@nzip/lofi@0.1.0/test",11- "@nzip/lofi/testing": "jsr:@nzip/lofi@0.1.0/testing",5+ "@nzip/lofi/": "jsr:@nzip/lofi@0.1.1/",6+ "@nzip/lofi/build": "jsr:@nzip/lofi@0.1.1/build",7+ "@nzip/lofi/dev": "jsr:@nzip/lofi@0.1.1/dev",8+ "@nzip/lofi/doctor": "jsr:@nzip/lofi@0.1.1/doctor",9+ "@nzip/lofi/preview": "jsr:@nzip/lofi@0.1.1/preview",10+ "@nzip/lofi/test": "jsr:@nzip/lofi@0.1.1/test",11+ "@nzip/lofi/testing": "jsr:@nzip/lofi@0.1.1/testing",1212 "astro": "npm:astro@7.0.9",1313 "astro/config": "npm:astro@7.0.9/config",1414 "jazz-tools": "npm:jazz-tools@2.0.0-alpha.53",@@ -5,7 +5,6 @@
55 "npm:@astrojs/preact@6.0.1": "6.0.1_preact@10.29.7__preact-render-to-string@6.7.0_@babel+core@7.29.7",66 "npm:astro@7.0.9": "7.0.9_@emnapi+core@1.11.1_@emnapi+runtime@1.11.1",77 "npm:jazz-tools@2.0.0-alpha.53": "2.0.0-alpha.53",8- "npm:playwright@1.61.1": "1.61.1",98 "npm:preact@10.29.7": "10.29.7_preact-render-to-string@6.7.0",109 "npm:typescript@6.0.3": "6.0.3",1110 "npm:vite@8.0.1": "8.0.1_@emnapi+core@1.11.1_@emnapi+runtime@1.11.1"@@ -1935,11 +1934,6 @@
19351934 "tiny-inflate"19361935 ]19371936 },1938- "fsevents@2.3.2": {1939- "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",1940- "os": ["darwin"],1941- "scripts": true1942- },19431937 "fsevents@2.3.3": {19441938 "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",19451939 "os": ["darwin"],@@ -2396,20 +2390,6 @@
23962390 "picomatch@4.0.5": {23972391 "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A=="23982392 },2399- "playwright-core@1.61.1": {2400- "integrity": "sha512-h7Qlt6m4REp25qvIdvbDtVmD4LqVXfpRxhORv9L0jzETM05p4fuPJ3dKyuSXQxDSbXnmS79HAgi9589lGSpLkg==",2401- "bin": true2402- },2403- "playwright@1.61.1": {2404- "integrity": "sha512-DWnY5o3YbLWK4GovuAVwpqL+1VwGNdUGrRr++8j8PtQQzvAVZUIMjKQ90fY689sEJZJBbZVw1rXaOKSTitkzPQ==",2405- "dependencies": [2406- "playwright-core"2407- ],2408- "optionalDependencies": [2409- "fsevents@2.3.2"2410- ],2411- "bin": true2412- },24132393 "pluralize-esm@9.0.5": {24142394 "integrity": "sha512-Kb2dcpMsIutFw2hYrN0EhsAXOUJTd6FVMIxvNAkZCMQLVt9NGZqQczvGpYDxNWCZeCWLHUPxQIBudWzt1h7VVA=="24152395 },@@ -2872,7 +2852,7 @@
28722852 "tinyglobby"28732853 ],28742854 "optionalDependencies": [2875- "fsevents@2.3.3"2855+ "fsevents"28762856 ],28772857 "bin": true28782858 },@@ -2887,7 +2867,7 @@
28872867 "tinyglobby"28882868 ],28892869 "optionalDependencies": [2890- "fsevents@2.3.3"2870+ "fsevents"28912871 ],28922872 "optionalPeers": [28932873 "esbuild@0.28.1"@@ -3121,7 +3101,7 @@
31213101 },31223102 "workspace": {31233103 "dependencies": [3124- "jsr:@nzip/lofi@0.1.0",3104+ "jsr:@nzip/lofi@0.1.1",31253105 "npm:@astrojs/check@0.9.9",31263106 "npm:@astrojs/preact@6.0.1",31273107 "npm:astro@7.0.9",@@ -3131,7 +3111,7 @@
31313111 "npm:vite@8.0.1"31323112 ],31333113 "links": {3134- "jsr:@nzip/lofi@0.1.0": {3114+ "jsr:@nzip/lofi@0.1.1": {31353115 "dependencies": [31363116 "npm:@astrojs/check@0.9.9",31373117 "npm:@astrojs/preact@6.0.1",@@ -1,6 +1,6 @@
11 {22 "name": "@nzip/lofi",3- "version": "0.1.0",3+ "version": "0.1.1",44 "license": "MIT",55 "description": "A local-first mobile PWA meta-framework for Deno: declare a schema, build Preact islands, and ship an installable offline-capable app whose UI always hydrates from local data.",66 "exports": {@@ -99,8 +99,8 @@ Deno.test("createProject materializes the complete starter snapshot", async () =
9999 );100100 }101101 const config = JSON.parse(await Deno.readTextFile(join(result.destination, "deno.json")));102- assertEquals(config.imports["@nzip/lofi/"], "jsr:@nzip/lofi@0.1.0/");103- assertEquals(config.imports["@nzip/lofi/testing"], "jsr:@nzip/lofi@0.1.0/testing");102+ assertEquals(config.imports["@nzip/lofi/"], "jsr:@nzip/lofi@0.1.1/");103+ assertEquals(config.imports["@nzip/lofi/testing"], "jsr:@nzip/lofi@0.1.1/testing");104104 const lofiSpecifiers = Object.entries(config.imports)105105 .filter(([name]) => name.startsWith("@nzip/lofi/"))106106 .map(([, specifier]) => String(specifier));@@ -109,7 +109,7 @@ Deno.test("createProject materializes the complete starter snapshot", async () =
109109 `expected one package prefix, five commands, and testing, received ${lofiSpecifiers.length}`,110110 );111111 assert(112- lofiSpecifiers.every((specifier) => specifier.startsWith("jsr:@nzip/lofi@0.1.0/")),112+ lofiSpecifiers.every((specifier) => specifier.startsWith("jsr:@nzip/lofi@0.1.1/")),113113 "generated lofi commands do not resolve through one exact package version",114114 );115115 } finally {@@ -2,7 +2,7 @@
22 ".env.example": "c22aed73c7089168ac777fd4f68ad504f9b826ea7185b705514a4ac5505918b1",33 ".gitignore": "9efb15c6a9bfc20f296ed712e74273b6015a0dd9a40f7e861b8711dcf61825f1",44 "astro.config.ts": "8a19cae348af7fcbd9db119d2423dd2e464f0e5ace6e5723d06cd3a1cc9a0d4b",5- "deno.json": "679b5f2a8da16e060c2423ae159af5fba9a60d4435b5a3696425978010cbd2b7",5+ "deno.json": "afcf5ade84512c242a1466ac5a9ee24b306d4e045a83b1610942d5129a943672",66 "public/favicon.svg": "23efdb888dae688715faafe3ef94f7b5ad1976afcc715c0a742218b54732c6ad",77 "public/manifest.webmanifest": "7d492285fd982e6e68fa04f12d78cd4f0bef4343f0408e314f1582029f3ea407",88 "public/sw.js": "6fa9f4c4b5ef7baabd48256a91520c766a4ffaf75c261686384d6d13e663d0c2",@@ -1,7 +1,12 @@
11 /** Thrown when Playwright's Chromium browser is not installed, with install guidance. */22 export class BrowserUnavailableError extends Error {3+ /** Always `"BrowserUnavailableError"`. */34 override readonly name = "BrowserUnavailableError";45 6+ /**7+ * Builds the error with a fixed install-guidance message.8+ * @param options standard error options, e.g. a `cause` to chain the launch failure.9+ */510 constructor(options?: ErrorOptions) {611 super(712 "Playwright Chromium is not installed. Run `deno run -A npm:playwright@1.61.1 install chromium` and retry.",@@ -3,18 +3,30 @@ import type { ValueFreeState } from "./safety.ts";
33 44 /** Minimal client contract the convergence runner needs: offline state and toggles. */55 export interface OfflineTestClient {6+ /** Whether the client's network is currently forced offline. */67 readonly offline: boolean;8+ /** Force this client's network offline. */79 goOffline(): Promise<void>;10+ /** Restore this client's network. */811 goOnline(): Promise<void>;912 }1013 1114 /** Minimal two-client fixture contract required to drive an offline scenario. */1215 export interface OfflineTestFixture<Client extends OfflineTestClient> {16+ /** Both clients, ordered `[first, second]`. */1317 readonly clients: readonly [Client, Client];18+ /** The first client. */1419 readonly first: Client;20+ /** The second client. */1521 readonly second: Client;22+ /** Take both clients offline. */1623 goOffline(): Promise<void>;24+ /** Bring both clients back online. */1725 goOnline(): Promise<void>;26+ /**27+ * Capture a redacted failure artifact, optionally including a value-free28+ * per-client snapshot. Returns an opaque handle describing what was written.29+ */1830 captureFailure(1931 label: string,2032 snapshot?: (client: Client) => Promise<ValueFreeState>,@@ -30,12 +42,15 @@ export interface ConcurrentOfflineScenario<
3042 Edit,3143 Client extends OfflineTestClient = BrowserTestClient,3244 > {45+ /** The two concurrent edits, one applied on each client while offline. */3346 readonly edits: readonly [Edit, Edit];3447 /** Overall defensive deadline. Defaults to 60 seconds. */3548 readonly timeoutMs?: number;3649 /** App-owned, deterministic readiness assertion (locator/waitForFunction/etc.). */3750 readonly ready: (client: Client, signal: AbortSignal) => Promise<void>;51+ /** Apply one client's edit while it is offline. */3852 readonly apply: (client: Client, edit: Edit, signal: AbortSignal) => Promise<void>;53+ /** Assert the edit is visible locally on its own client before reconnection. */3954 readonly locallyApplied: (client: Client, edit: Edit, signal: AbortSignal) => Promise<void>;4055 /** Use this hook for page/client restart while offline work is pending. */4156 readonly whilePending?: (@@ -47,15 +62,22 @@ export interface ConcurrentOfflineScenario<
4762 fixture: OfflineTestFixture<Client>,4863 signal: AbortSignal,4964 ) => Promise<void>;65+ /** Optional value-free snapshot taken per client when a failure is captured. */5066 readonly snapshot?: (client: Client) => Promise<ValueFreeState>;67+ /** Label for any captured failure artifact. Defaults to a generic name. */5168 readonly failureLabel?: string;5269 }5370 5471 /** Thrown when a convergence scenario fails, naming the stage that failed via {@link stage}. */5572 export class ConvergenceScenarioError extends Error {73+ /** Always `"ConvergenceScenarioError"`. */5674 override readonly name = "ConvergenceScenarioError";5775 58- /** @param stage the lifecycle stage that was in progress when the scenario failed */76+ /**77+ * Builds the error, recording which lifecycle stage was in progress.78+ * @param stage the lifecycle stage that was in progress when the scenario failed79+ * @param options standard error options, e.g. a `cause` from the failing hook80+ */5981 constructor(readonly stage: string, options?: ErrorOptions) {6082 super(`Concurrent offline convergence failed during ${stage}`, options);6183 }@@ -32,10 +32,15 @@ export type ClientName = "first" | "second";
3232 3333 /** A redacted console, page-error, or failed-request record captured from a client. */3434 export interface BrowserDiagnostic {35+ /** Which of the two clients produced this diagnostic. */3536 readonly client: ClientName;37+ /** What surfaced it: a console message, an uncaught page error, or a failed request. */3638 readonly kind: "console" | "page-error" | "request-failed";39+ /** Console severity (e.g. `"error"`, `"warning"`), when applicable. */3740 readonly level?: string;41+ /** The redacted message text. */3842 readonly message: string;43+ /** The associated URL, for `request-failed` records. */3944 readonly url?: string;4045 }4146 @@ -58,6 +63,7 @@ export type IdentityOptions =
5863 5964 /** Configures where and how redacted failure artifacts are written on capture. */6065 export interface FailureArtifactOptions {66+ /** Directory the redacted artifacts are written into on capture. */6167 readonly directory: string;6268 /** Literal credential values to remove from retained diagnostics. */6369 readonly secretValues?: readonly string[];@@ -67,10 +73,15 @@ export interface FailureArtifactOptions {
6773 6874 /** Options for constructing a {@link TwoClientFixture} via {@link createTwoClientFixture}. */6975 export interface TwoClientFixtureOptions {76+ /** The origin both clients open and enroll identity against. */7077 readonly baseURL: string;78+ /** How the two clients obtain identity (`shared` or `isolated`). */7179 readonly identity: IdentityOptions;80+ /** An existing browser to reuse; when omitted the fixture launches and owns one. */7281 readonly browser?: Browser;82+ /** Extra context options (a disk `storageState` is forbidden to keep identity in memory). */7383 readonly context?: SafeContextOptions;84+ /** Where and how to write redacted artifacts if the test fails. */7485 readonly artifacts?: FailureArtifactOptions;7586 /** Defaults to true. Tracing begins only after identity preparation. */7687 readonly traceOnFailure?: boolean;@@ -100,6 +111,7 @@ export class BrowserTestClient {
100111 #recording = false;101112 #closed = false;102113 114+ /** Constructed by {@link createTwoClientFixture}; not intended for direct use. */103115 constructor(104116 readonly name: ClientName,105117 context: BrowserContext,@@ -255,7 +267,9 @@ export class BrowserTestClient {
255267 256268 /** The directory and file paths produced by a failure capture. */257269 export interface FailureArtifacts {270+ /** The directory the artifacts were written into. */258271 readonly directory: string;272+ /** Absolute paths of every file written (screenshots, traces, diagnostics). */259273 readonly files: readonly string[];260274 }261275 @@ -269,6 +283,7 @@ export class TwoClientFixture {
269283 readonly clients: readonly [BrowserTestClient, BrowserTestClient];270284 #closed = false;271285 286+ /** Constructed by {@link createTwoClientFixture}; not intended for direct use. */272287 constructor(273288 readonly browser: Browser,274289 readonly ownsBrowser: boolean,@@ -12,8 +12,14 @@ export interface ReadinessOptions {
1212 1313 /** Thrown when the readiness predicate does not become true before the timeout. */1414 export class ReadinessError extends Error {15+ /** Always `"ReadinessError"`. */1516 override readonly name = "ReadinessError";1617 18+ /**19+ * Builds the error, embedding the condition that failed to become ready.20+ * @param description the readiness condition that timed out, named in the message21+ * @param options standard error options, e.g. a `cause` from the underlying timeout22+ */1723 constructor(description: string, options?: ErrorOptions) {1824 super(`Page did not become ready: ${description}`, options);1925 }@@ -1,5 +1,5 @@
11 /** The single source version for generated @nzip/lofi references. */2-export const LOFI_VERSION = "0.1.0";2+export const LOFI_VERSION = "0.1.1";33 44 /** The exact JSR package prefix emitted into generated projects. */55 export const LOFI_PACKAGE_PREFIX = `jsr:@nzip/lofi@${LOFI_VERSION}/`;