clone

push a directory of html from the terminal and get a four-character url back. a deno cli on cloudflare

docs: complete shared JSR documentation

Dami committed 890b49b
Document every exported property and target variant, enrich function JSDoc, gate releases with deno doc lint, and prepare the immutable registry update as v0.3.1.
commit
890b49b482be9f441510ae26e5a551d7b8b19194
parent
ba5c7eb542dc4346825d301be7df450f9140a14c
author
Dami <dami.etoile@gmail.com>
12 files changed, +142 -20
M.github/workflows/publish.yml1+
Mcli/deno.json2+-
Mdeno.json1+
Mshared/address.ts72++++++++++++++++++++++++++----
Mshared/deno.json2+-
Mshared/hash.ts7+++-
Mshared/limits.ts13+++++-
Mshared/manifest.tsbin
Mshared/mediatypes.ts8+++-
Mshared/types.ts47+++++++++++++++++++-
Mshared/version.ts7++-
Mworker/test/index.runtime.test.ts2+-
M .github/workflows/publish.yml +1 -0
M cli/deno.json +1 -1
M deno.json +1 -0
M shared/address.ts +63 -9
@@ -9,12 +9,23 @@ export const SITES_PER_VAULT = 0x1000;
99 const ADDR_RE = /^[0-9a-f]{4}$/;1010 const NAME_RE = /^[a-z0-9][a-z0-9-]{0,31}$/;1111 12-/** True if `s` is a well-formed 4-hex address like `"2a3f"`. */12+/**13+ * Tests whether a string is a canonical four-character site address.14+ *15+ * @param s Candidate address such as `"2a3f"`.16+ * @returns `true` only for four lowercase hexadecimal characters.17+ */1318 export function isAddressString(s: string): boolean {1419 return ADDR_RE.test(s);1520 }1621 17-/** "2a3f" → 0x2a3f. Throws on malformed input. */22+/**23+ * Converts a canonical address string to its numeric representation.24+ *25+ * @param s Four-character lowercase hexadecimal address.26+ * @returns Integer in the inclusive range `0x0000`–`0xffff`.27+ * @throws {Error} If `s` is not a canonical address.28+ */1829 export function parseAddress(s: string): number {1930 if (!ADDR_RE.test(s)) {2031 throw new Error(`invalid address: ${JSON.stringify(s)}`);
@@ -22,7 +33,13 @@ export function parseAddress(s: string): number {
2233 return parseInt(s, 16);2334 }2435 25-/** 0x2a3f → "2a3f" */36+/**37+ * Formats a numeric site address as four lowercase hexadecimal characters.38+ *39+ * @param addr Integer site address.40+ * @returns Canonical address string such as `"2a3f"`.41+ * @throws {Error} If `addr` is not an integer from `0x0000` through `0xffff`.42+ */2643 export function formatAddress(addr: number): string {2744 if (2845 !Number.isInteger(addr) || addr < 0 || addr >= VAULT_SLOTS * SITES_PER_VAULT
@@ -32,23 +49,60 @@ export function formatAddress(addr: number): string {
3249 return addr.toString(16).padStart(4, "0");3350 }3451 35-/** Extract the vault slot (0–15) from an address integer. */52+/**53+ * Extracts the high-nibble vault slot from a numeric site address.54+ *55+ * @param addr Numeric site address.56+ * @returns Vault slot from `0` through `15`.57+ */3658 export function vaultSlotOf(addr: number): number {3759 return addr >> 12;3860 }3961 40-/** Valid vault or alias name: lowercase alnum + hyphen, 1-32 chars, must not look like an address. */62+/**63+ * Tests whether a string is a valid vault or alias name.64+ *65+ * Names contain 1–32 lowercase alphanumeric or hyphen characters, start with66+ * an alphanumeric character, and cannot look like a four-hex address.67+ *68+ * @param name Candidate vault or alias name.69+ * @returns Whether the candidate satisfies the shared naming contract.70+ */4171 export function isValidName(name: string): boolean {4272 return NAME_RE.test(name) && !ADDR_RE.test(name);4373 }4474 4575 /** A parsed target: a raw address, a `vault:alias` pair, or a bare alias in the default vault. */4676 export type ParsedTarget =47- | { kind: "address"; address: number }48- | { kind: "vaultAlias"; vault: string; alias: string }49- | { kind: "alias"; alias: string };77+ | {78+ /** Discriminator for a direct four-hex address. */79+ kind: "address";80+ /** Parsed numeric site address. */81+ address: number;82+ }83+ | {84+ /** Discriminator for an explicitly named vault and alias. */85+ kind: "vaultAlias";86+ /** Valid registered-vault name from the input. */87+ vault: string;88+ /** Valid site alias from the input. */89+ alias: string;90+ }91+ | {92+ /** Discriminator for an alias that requires the caller's default vault. */93+ kind: "alias";94+ /** Valid site alias from the input. */95+ alias: string;96+ };5097 51-/** Parse a CLI/API target: "2a3f" | "work:demo" | "demo". */98+/**99+ * Parses a CLI or API target into a discriminated union.100+ *101+ * @param s Direct address (`"2a3f"`), vault alias (`"work:demo"`), or bare102+ * alias (`"demo"`).103+ * @returns Structured target for address or vault resolution.104+ * @throws {Error} If the target or either name component is malformed.105+ */52106 export function parseTarget(s: string): ParsedTarget {53107 if (ADDR_RE.test(s)) return { kind: "address", address: parseInt(s, 16) };54108 const colon = s.indexOf(":");
M shared/deno.json +1 -1
M shared/hash.ts +6 -1
M shared/limits.ts +11 -2
M shared/manifest.ts +0 -0

Binary file.

M shared/mediatypes.ts +7 -1
M shared/types.ts +45 -2
@@ -21,16 +21,26 @@ export interface Manifest {
2121 2222 /** A push destination: a raw address, or a vault (optionally with an alias). */2323 export type Target =24- | { address: number }25- | { vault: string; alias?: string | null };24+ | {25+ /** Numeric site address in the inclusive range `0x0000`–`0xffff`. */26+ address: number;27+ }28+ | {29+ /** Registered vault name that owns the destination address. */30+ vault: string;31+ /** Optional site alias within the vault; `null` requests an unaliased site. */32+ alias?: string | null;33+ };2634 2735 /** Body of `POST /api/push/prepare`: the manifest the client wants to push. */2836 export interface PrepareRequest {37+ /** Complete manifest whose referenced blob availability should be checked. */2938 manifest: Manifest;3039 }3140 3241 /** Reply to `prepare`: the manifest's hash and which blobs the server still needs. */3342 export interface PrepareResponse {43+ /** Lowercase SHA-256 of the canonical manifest bytes. */3444 manifestHash: string;3545 /** blob hashes the server does not have yet */3646 missing: string[];
@@ -38,7 +48,9 @@ export interface PrepareResponse {
3848 3949 /** Body of `POST /api/push/commit`: atomically publish content and its access policy. */4050 export interface CommitRequest {51+ /** Complete manifest to publish as the site's current version. */4152 manifest: Manifest;53+ /** Address or vault destination that should receive the new version. */4254 target: Target;4355 /** days until expiry; "forever" = no expiry; omitted = server default (14) */4456 ttl?: number | "forever";
@@ -50,8 +62,11 @@ export interface CommitRequest {
5062 export interface CommitResponse {5163 /** 4-hex address, e.g. "2a3f" */5264 address: string;65+ /** Absolute public URL of the committed site. */5366 url: string;67+ /** Resolved site alias, or `null` for an unaliased address. */5468 alias: string | null;69+ /** Lowercase SHA-256 of the committed canonical manifest. */5570 manifestHash: string;5671 /** unix seconds, null = permanent */5772 expiresAt: number | null;
@@ -61,50 +76,75 @@ export interface CommitResponse {
6176 6277 /** Summary of a single site, as returned by list/status endpoints. */6378 export interface SiteInfo {79+ /** Four-character lowercase hexadecimal site address. */6480 address: string;81+ /** Name of the vault containing the site. */6582 vault: string;83+ /** Site alias within its vault, or `null` when unaliased. */6684 alias: string | null;85+ /** Lowercase SHA-256 of the site's current canonical manifest. */6786 manifestHash: string;87+ /** Unix timestamp, in seconds, when the site was created. */6888 createdAt: number;89+ /** Unix timestamp, in seconds, of the most recent site update. */6990 updatedAt: number;91+ /** Unix expiry timestamp in seconds, or `null` for a permanent site. */7092 expiresAt: number | null;93+ /** Absolute public URL of the site. */7194 url: string;95+ /** Whether visitors must unlock the site with a password. */7296 protected: boolean;7397 }7498 7599 /** One entry in a site's push history. */76100 export interface PushInfo {101+ /** Monotonically increasing push sequence number within the site. */77102 seq: number;103+ /** Lowercase SHA-256 of the manifest published by this push. */78104 manifestHash: string;105+ /** Unix timestamp, in seconds, when the push was committed. */79106 pushedAt: number;107+ /** Optional audit note, such as the source sequence of a revert. */80108 note: string | null;81109 }82110 83111 /** A site plus its retained push history (powers `nzip revert`). */84112 export interface SiteDetail extends SiteInfo {113+ /** Retained push history ordered from newest to oldest. */85114 history: PushInfo[];86115 }87116 88117 /** Current uploaded bundle for a site, returned only by the authenticated recovery API. */89118 export interface SourceResponse {119+ /** Four-character lowercase hexadecimal address of the recovered site. */90120 address: string;121+ /** Lowercase SHA-256 of the returned canonical manifest. */91122 manifestHash: string;123+ /** Current manifest used to reconstruct and verify the hosted bundle. */92124 manifest: Manifest;93125 }94126 95127 /** A registered vault: its slot, name, and current site count. */96128 export interface VaultInfo {129+ /** Numeric vault slot in the inclusive range `0x0`–`0xf`. */97130 slot: number;131+ /** Registered lowercase vault name. */98132 name: string;133+ /** Unix timestamp, in seconds, when the vault was registered. */99134 createdAt: number;135+ /** Number of currently live sites assigned to this vault. */100136 siteCount: number;101137 }102138 103139 /** Reply to `GET /api/status`: server version and a snapshot of vaults and sites. */104140 export interface StatusResponse {141+ /** Literal success marker for a healthy authenticated status response. */105142 ok: true;143+ /** Semantic version reported by the running nzip Worker. */106144 version: string;145+ /** All registered vaults and their current site counts. */107146 vaults: VaultInfo[];147+ /** Total number of currently registered sites across every vault. */108148 siteCount: number;109149 /** sites expiring within 48h */110150 expiringSoon: number;
@@ -112,11 +152,13 @@ export interface StatusResponse {
112152 113153 /** Body of a revert request: the push sequence number to repoint to (defaults to previous). */114154 export interface RevertRequest {155+ /** Push sequence to restore; omission selects the newest differing version. */115156 toSeq?: number;116157 }117158 118159 /** Body of a site PATCH: change TTL and/or password. Omitted fields are left unchanged. */119160 export interface PatchSiteRequest {161+ /** New lifetime in days, or `"forever"`; omission preserves the current expiry. */120162 ttl?: number | "forever";121163 /** set a password (string), clear it (null), or leave unchanged (undefined) */122164 password?: string | null;
@@ -124,5 +166,6 @@ export interface PatchSiteRequest {
124166 125167 /** Standard error envelope returned by the API on failure. */126168 export interface ApiError {169+ /** Human-readable error message safe to show to the authenticated client. */127170 error: string;128171 }
M shared/version.ts +5 -2
M worker/test/index.runtime.test.ts +1 -1