@astilba/cache 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +14 -2
- package/dist/adapters/cloudflare/index.d.ts +299 -0
- package/dist/adapters/cloudflare/index.js +1699 -0
- package/dist/adapters/react-router/index.d.ts +92 -0
- package/dist/adapters/react-router/index.js +272 -0
- package/dist/cache-YWn0VZpn.d.ts +930 -0
- package/dist/cache-Z4cJzPmm.js +3528 -0
- package/dist/index.d.ts +131 -0
- package/dist/index.js +2 -0
- package/package.json +96 -3
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { $ as Clock, A as Tier, B as EnvelopeEnc, C as L3Ineligibility, Ct as TelemetrySink, D as RenderCollector, Dt as Watermark, E as PurgeResult, Et as Validity, F as compound, G as Bus, H as Duration, I as globalTag, J as CasOrder, K as BusEvent, L as t, M as createCache, N as Tag, O as RequestContext, P as TagPart, Q as CdnMode, R as ChannelState, S as L3Emission, St as TelemetryEventName, T as OriginLoadGuard, Tt as TagKnowledge, U as DurationUnit, V as EnvelopeKind, W as duration, X as CasStore, Y as CasRecord, Z as Cdn, _ as GetOptions, _t as SinkErrorHook, a as DeleteSelector, at as Registry, b as GracedInfo, bt as TelemetryConfig, c as ExplainDependencyScope, ct as Store, d as ExplainScope, dt as StoreWriteError, et as Codec, f as ExplainTtl, ft as StoreWriteOptions, g as FactoryCtx, gt as memory, h as Explanation, ht as isStoreWriteError, i as CacheEntry, it as ReadKind, j as UnknownPolicy, k as Scope, l as ExplainIdentity, lt as StoreMetadata, m as ExplainedDependency, mt as TagChange, n as CacheConfig, nt as LockHandle, o as EntryFactoryCtx, ot as RegistryAck, p as ExplainVerdict, pt as Subscription, q as BusFrame, r as CacheDefaults, rt as MemoryOptions, s as ExpireSelector, st as Rng, t as Cache, tt as Lock, u as ExplainReaderState, ut as StoreValue, v as GetOrSetEntryOptions, vt as StrongDegradedReason, w as MatchedHint, wt as Consistency, x as L3Budget, xt as TelemetryEvent, y as GetOrSetOptions, yt as TELEMETRY_EVENTS, z as Envelope } from "./cache-YWn0VZpn.js";
|
|
2
|
+
//#region src/errors.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Thrown by every public entry point during the correctness-kernel phase. A RED
|
|
5
|
+
* invariant that fails with `NotImplementedError` is red for the right reason
|
|
6
|
+
* (the kernel is unimplemented), as opposed to a toolchain/config failure.
|
|
7
|
+
*/
|
|
8
|
+
declare class NotImplementedError extends Error {
|
|
9
|
+
constructor(symbol: string);
|
|
10
|
+
}
|
|
11
|
+
/** Whether a cache timeout originated inside the cache or from a caller abort. */
|
|
12
|
+
type CacheTimeoutSource = "cache" | "caller";
|
|
13
|
+
/**
|
|
14
|
+
* Distinguishes cache-originated timeouts (retriable — evidence about origin
|
|
15
|
+
* health) from caller aborts (not evidence of origin health).
|
|
16
|
+
*/
|
|
17
|
+
declare class CacheTimeoutError extends Error {
|
|
18
|
+
readonly source: CacheTimeoutSource;
|
|
19
|
+
constructor(source: CacheTimeoutSource, message?: string);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Thrown by a `strong` read when the registry is unreachable. Opt out with
|
|
23
|
+
* `onUnavailable: 'eventual'`.
|
|
24
|
+
*/
|
|
25
|
+
declare class RegistryUnavailableError extends Error {
|
|
26
|
+
/**
|
|
27
|
+
* `options.cause` carries the error this one displaced, where there was one. The serve-time
|
|
28
|
+
* re-validation of a graced candidate runs INSIDE a failed fill: if the registry is unreachable
|
|
29
|
+
* there, this error is what the caller sees instead of the factory failure that started it, so
|
|
30
|
+
* the factory failure rides along rather than being dropped. Nothing is lost and callers get one
|
|
31
|
+
* uniform type. Widened additively — `new RegistryUnavailableError(msg)` is unchanged.
|
|
32
|
+
*/
|
|
33
|
+
constructor(message?: string, options?: ErrorOptions);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Thrown by a read whose tag knowledge is UNKNOWN under `unknownPolicy: 'error'`.
|
|
37
|
+
*
|
|
38
|
+
* WHAT MAKES THIS DISTINCT FROM A MISS, AND WHY THE DISTINCTION IS THE POINT. Every other
|
|
39
|
+
* fail-closed resolution refills from origin, which is hard-safe exactly when the origin is truth.
|
|
40
|
+
* `'error'` is the policy for the case where it is NOT: a namespace under a takedown or a legal
|
|
41
|
+
* embargo. There, an origin that has not caught up yet can lose a race with the purge and hand back
|
|
42
|
+
* exactly the content that was supposed to vanish. So this policy declines to guess: it neither
|
|
43
|
+
* serves the unknown value nor replaces it
|
|
44
|
+
* with a fresh one, and the caller — who knows what the content is — decides. A policy that resolved
|
|
45
|
+
* to the same refill as `'miss'` would be a switch that reads as protection and does nothing, which
|
|
46
|
+
* is worse than no switch at all.
|
|
47
|
+
*
|
|
48
|
+
* Carries the key and the tags whose knowledge was unknown, so a caller can tell an embargoed
|
|
49
|
+
* dependency from a cold one. EXACTLY those: the tags this read could not establish, and no others.
|
|
50
|
+
* A payload of everything the entry declared cannot answer the question the field exists for — the
|
|
51
|
+
* caller would have to guess which of them was the problem, which is the guess this policy refuses
|
|
52
|
+
* to make on their behalf. Reserved (`__`-prefixed) tags never appear here: they are the kernel's
|
|
53
|
+
* own bookkeeping, they are unknown for exactly the same reason the user's are, and naming them
|
|
54
|
+
* tells the caller nothing they can act on.
|
|
55
|
+
*/
|
|
56
|
+
declare class UnknownTagError extends Error {
|
|
57
|
+
readonly key: string;
|
|
58
|
+
readonly tags: readonly string[];
|
|
59
|
+
/**
|
|
60
|
+
* `armedBy` names what selected this resolution — an explicit `unknownPolicy: 'error'`, or the
|
|
61
|
+
* `takedownSensitive` override that outranks it. The message used to state the former
|
|
62
|
+
* unconditionally, which was wrong precisely on the takedown path: the one place where the
|
|
63
|
+
* operator most needs to know which switch fired is the one where the message named the other.
|
|
64
|
+
*/
|
|
65
|
+
constructor(key: string, tags: readonly string[], armedBy?: "unknownPolicy" | "takedownSensitive");
|
|
66
|
+
}
|
|
67
|
+
/** A typed HTTP error carrying the offending status and response. */
|
|
68
|
+
declare class HttpError extends Error {
|
|
69
|
+
readonly status: number;
|
|
70
|
+
readonly response: Response;
|
|
71
|
+
constructor(response: Response);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Thrown at the `getOrSet`/`getOrSetEntry` write boundary when a caller-supplied
|
|
75
|
+
* tag is malformed — in particular a user tag beginning with the reserved `__`
|
|
76
|
+
* prefix. A real runtime error, never `NotImplementedError`: tag
|
|
77
|
+
* validation is not deferred kernel logic.
|
|
78
|
+
*/
|
|
79
|
+
declare class InvalidTagError extends Error {
|
|
80
|
+
readonly tag: string;
|
|
81
|
+
constructor(tag: string, reason: string);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Thrown by `duration()` when a computed duration is malformed — a non-positive or
|
|
85
|
+
* non-finite `value`, or (critical case) a `value × unitFactor` product that
|
|
86
|
+
* is not a finite, positive, safe integer once multiplied out. A real
|
|
87
|
+
* runtime error, never `NotImplementedError`: duration validation is not deferred kernel
|
|
88
|
+
* logic. Mirrors `InvalidTagError` — the builder rejects a bad input, it never coerces one.
|
|
89
|
+
*/
|
|
90
|
+
declare class InvalidDurationError extends Error {
|
|
91
|
+
readonly value: number;
|
|
92
|
+
readonly unit: string;
|
|
93
|
+
constructor(value: number, unit: string, reason: string);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Thrown by the plain `getOrSet` form when a fill is fenced past its write-back
|
|
97
|
+
* retry attempt budget: a hard delete keeps landing mid-fill/mid-
|
|
98
|
+
* refresh so the accepted result never postdates every purge visible at
|
|
99
|
+
* write-back, and the fill fails within its attempt budget rather than ever
|
|
100
|
+
* storing or serving a fenced value. A real runtime outcome, never
|
|
101
|
+
* `NotImplementedError` — the entry form (`getOrSetEntry`) surfaces the same
|
|
102
|
+
* outcome as `{ value: undefined }` instead of throwing.
|
|
103
|
+
*/
|
|
104
|
+
declare class FencedError extends Error {
|
|
105
|
+
readonly key: string;
|
|
106
|
+
constructor(key: string, message?: string);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Thrown when a factory declares a dependency after it has settled: a
|
|
110
|
+
* `ctx.dependsOn`/`ctx.setTags` call reaching the context AFTER the factory promise
|
|
111
|
+
* resolved or rejected. The fill's tag set closes at settle, so a later declaration is
|
|
112
|
+
* outside the value's lifetime and cannot join it. A real runtime error, never
|
|
113
|
+
* `NotImplementedError`. Carries the offending key.
|
|
114
|
+
*/
|
|
115
|
+
declare class FactorySettledError extends Error {
|
|
116
|
+
readonly key: string;
|
|
117
|
+
constructor(key: string);
|
|
118
|
+
}
|
|
119
|
+
//#endregion
|
|
120
|
+
//#region src/http.d.ts
|
|
121
|
+
/** Wrap a non-ok `Response` into a typed `HttpError`. */
|
|
122
|
+
declare function httpError(response: Response): HttpError;
|
|
123
|
+
/**
|
|
124
|
+
* The default `staleIfError` predicate — retriable: the default
|
|
125
|
+
* retriable set, network errors, and cache-originated timeouts. `404/410/403` are
|
|
126
|
+
* facts, never masked (never retriable) — a caller-abort `CacheTimeoutError` with
|
|
127
|
+
* `source:'caller'` is likewise not evidence of origin health.
|
|
128
|
+
*/
|
|
129
|
+
declare function isRetriableHttp(err: unknown): boolean;
|
|
130
|
+
//#endregion
|
|
131
|
+
export { type Bus, type BusEvent, type BusFrame, type Cache, type CacheConfig, type CacheDefaults, type CacheEntry, CacheTimeoutError, type CacheTimeoutSource, type CasOrder, type CasRecord, type CasStore, type Cdn, type CdnMode, type ChannelState, type Clock, type Codec, type Consistency, type DeleteSelector, type Duration, type DurationUnit, type EntryFactoryCtx, type Envelope, type EnvelopeEnc, type EnvelopeKind, type ExpireSelector, type ExplainDependencyScope, type ExplainIdentity, type ExplainReaderState, type ExplainScope, type ExplainTtl, type ExplainVerdict, type ExplainedDependency, type Explanation, type FactoryCtx, FactorySettledError, FencedError, type GetOptions, type GetOrSetEntryOptions, type GetOrSetOptions, type GracedInfo, HttpError, InvalidDurationError, InvalidTagError, type L3Budget, type L3Emission, type L3Ineligibility, type Lock, type LockHandle, type MatchedHint, type MemoryOptions, NotImplementedError, type OriginLoadGuard, type PurgeResult, type ReadKind, type Registry, type RegistryAck, RegistryUnavailableError, type RenderCollector, type RequestContext, type Rng, type Scope, type SinkErrorHook, type Store, type StoreMetadata, type StoreValue, type StoreWriteError, type StoreWriteOptions, type StrongDegradedReason, type Subscription, TELEMETRY_EVENTS, type Tag, type TagChange, type TagKnowledge, type TagPart, type TelemetryConfig, type TelemetryEvent, type TelemetryEventName, type TelemetrySink, type Tier, type UnknownPolicy, UnknownTagError, type Validity, type Watermark, compound, createCache, duration, globalTag, httpError, isRetriableHttp, isStoreWriteError, memory, t };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { A as UnknownTagError, C as FactorySettledError, D as InvalidTagError, E as InvalidDurationError, O as NotImplementedError, S as CacheTimeoutError, T as HttpError, _ as t, c as isRetriableHttp, d as memory, g as globalTag, h as compound, k as RegistryUnavailableError, l as duration, p as TELEMETRY_EVENTS, r as createCache, s as httpError, u as isStoreWriteError, w as FencedError } from "./cache-Z4cJzPmm.js";
|
|
2
|
+
export { CacheTimeoutError, FactorySettledError, FencedError, HttpError, InvalidDurationError, InvalidTagError, NotImplementedError, RegistryUnavailableError, TELEMETRY_EVENTS, UnknownTagError, compound, createCache, duration, globalTag, httpError, isRetriableHttp, isStoreWriteError, memory, t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,99 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astilba/cache",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Portable TypeScript caching with tag invalidation, stale-if-error resilience, and privacy scopes.",
|
|
5
|
+
"homepage": "https://astilba.com/docs/cache/",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/astilbahq/astilba/issues"
|
|
8
|
+
},
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/astilbahq/astilba.git",
|
|
13
|
+
"directory": "packages/cache"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"type": "module",
|
|
19
|
+
"sideEffects": false,
|
|
20
|
+
"main": "./dist/index.js",
|
|
21
|
+
"module": "./dist/index.js",
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"default": "./dist/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./cloudflare": {
|
|
29
|
+
"types": "./dist/adapters/cloudflare/index.d.ts",
|
|
30
|
+
"default": "./dist/adapters/cloudflare/index.js"
|
|
31
|
+
},
|
|
32
|
+
"./react-router": {
|
|
33
|
+
"types": "./dist/adapters/react-router/index.d.ts",
|
|
34
|
+
"default": "./dist/adapters/react-router/index.js"
|
|
35
|
+
},
|
|
36
|
+
"./package.json": "./package.json"
|
|
37
|
+
},
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@arethetypeswrong/cli": "0.18.4",
|
|
43
|
+
"@cloudflare/vitest-pool-workers": "0.18.3",
|
|
44
|
+
"@fast-check/vitest": "^0.4.1",
|
|
45
|
+
"@stryker-mutator/core": "9.6.1",
|
|
46
|
+
"@stryker-mutator/vitest-runner": "9.6.1",
|
|
47
|
+
"@types/node": "24.13.2",
|
|
48
|
+
"@types/react": "19.2.17",
|
|
49
|
+
"@vitest/coverage-istanbul": "4.1.11",
|
|
50
|
+
"eslint-plugin-github": "6.0.0",
|
|
51
|
+
"eslint-plugin-sonarjs": "4.1.0",
|
|
52
|
+
"fast-check": "^4.8.0",
|
|
53
|
+
"knip": "6.24.0",
|
|
54
|
+
"miniflare": "4.20260708.0",
|
|
55
|
+
"oxfmt": "0.64.0",
|
|
56
|
+
"oxlint": "1.79.0",
|
|
57
|
+
"oxlint-tsgolint": "7.0.2001",
|
|
58
|
+
"publint": "0.3.21",
|
|
59
|
+
"react": "19.2.7",
|
|
60
|
+
"react-router": "8.3.0",
|
|
61
|
+
"typescript": "6.0.3",
|
|
62
|
+
"ultracite": "7.9.2",
|
|
63
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@0.3.0",
|
|
64
|
+
"vite-plus": "0.3.0",
|
|
65
|
+
"vitest": "4.1.11",
|
|
66
|
+
"wrangler": "4.109.0",
|
|
67
|
+
"yaml": "2.9.0",
|
|
68
|
+
"@astilba/harness": "0.0.0"
|
|
69
|
+
},
|
|
70
|
+
"peerDependencies": {
|
|
71
|
+
"react": "19.2.7",
|
|
72
|
+
"react-router": "8.3.0"
|
|
73
|
+
},
|
|
74
|
+
"peerDependenciesMeta": {
|
|
75
|
+
"react": {
|
|
76
|
+
"optional": true
|
|
77
|
+
},
|
|
78
|
+
"react-router": {
|
|
79
|
+
"optional": true
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"scripts": {
|
|
83
|
+
"build": "vp pack",
|
|
84
|
+
"build:apps": "pnpm --dir ../../fixtures/cache-react-router run build && pnpm --dir ../../apps/cache-demo run build",
|
|
85
|
+
"check": "for d in . ../cache-harness ../../apps/cache-demo; do (cd $d && oxfmt --config oxfmt.config.ts --disable-nested-config --check . && oxlint --config oxlint.config.ts --disable-nested-config --type-aware --type-check .) || exit 1; done",
|
|
86
|
+
"fix": "for d in . ../cache-harness ../../apps/cache-demo; do (cd $d && oxfmt --config oxfmt.config.ts --disable-nested-config --write . && oxlint --config oxlint.config.ts --disable-nested-config --type-aware --type-check --fix .) || exit 1; done",
|
|
87
|
+
"test": "vp test",
|
|
88
|
+
"test:unit": "vp test run --project unit --project harness",
|
|
89
|
+
"test:invariants": "vitest run --project invariants",
|
|
90
|
+
"test:mutation": "stryker run",
|
|
91
|
+
"typecheck": "tsc --noEmit && tsc -p tsconfig.config.json && tsc -p test/integration/tsconfig.json --noEmit && pnpm --filter @astilba/harness --filter @astilba/demo --filter @astilba/rr-fixture -r exec tsc --noEmit",
|
|
92
|
+
"types:integration": "cd test/integration && wrangler types",
|
|
93
|
+
"lint:publish": "node scripts/check-package.mjs",
|
|
94
|
+
"knip": "pnpm --dir ../.. exec knip --workspace packages/cache --workspace packages/cache-harness --workspace apps/cache-demo --workspace fixtures/cache-react-router",
|
|
95
|
+
"knip:production": "pnpm knip --production",
|
|
96
|
+
"verify:toolchain": "node scripts/verify-toolchain.mjs",
|
|
97
|
+
"verify": "pnpm verify:toolchain && pnpm check && pnpm typecheck && pnpm exec vitest run && pnpm exec vp test run --project unit --project harness --coverage && pnpm lint:publish && pnpm knip && pnpm knip:production && pnpm build:apps && node scripts/boot-smoke.mjs && node scripts/module-scope-boot.mjs && node scripts/demo-boot-witness.mjs && node scripts/demo-typed-routes.mjs"
|
|
98
|
+
}
|
|
6
99
|
}
|