@czap/edge 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.
@@ -0,0 +1,139 @@
1
+ /**
2
+ * EdgeHostAdapter -- canonical host-facing edge resolution path.
3
+ *
4
+ * Resolves client hints, tiering, optional theme compilation, and optional
5
+ * boundary compilation cache lookups in a single host-level operation.
6
+ *
7
+ * @module
8
+ */
9
+ import type { ContentAddress } from '@czap/core';
10
+ import type { ExtendedDeviceCapabilities } from '@czap/detect';
11
+ import type { ClientHintsHeaders } from './client-hints.js';
12
+ import type { EdgeTierResult } from './edge-tier.js';
13
+ import type { CompiledOutputs, KVNamespace } from './kv-cache.js';
14
+ import type { ThemeCompileConfig, ThemeCompileResult } from './theme-compiler.js';
15
+ /**
16
+ * Detected device context available to host callbacks before compile.
17
+ *
18
+ * Pairs the parsed {@link ExtendedDeviceCapabilities} with the resolved
19
+ * {@link EdgeTierResult} so a host can derive a theme config or compile
20
+ * decision without re-parsing headers.
21
+ */
22
+ export interface EdgeHostContext {
23
+ /** Capabilities parsed from Client Hints. */
24
+ readonly capabilities: ExtendedDeviceCapabilities;
25
+ /** Derived tier triple (cap, motion, design). */
26
+ readonly tier: EdgeTierResult;
27
+ }
28
+ /**
29
+ * Compile-time context passed to {@link EdgeHostCacheConfig.compile}.
30
+ *
31
+ * Extends {@link EdgeHostContext} with the already-resolved theme result
32
+ * (if any) so host compile callbacks can inject theme tokens into the
33
+ * compiled per-state outputs without recomputation.
34
+ */
35
+ export interface EdgeHostCompileContext extends EdgeHostContext {
36
+ /** Pre-compiled theme output, if the adapter resolved one for this request. */
37
+ readonly theme?: ThemeCompileResult;
38
+ }
39
+ /**
40
+ * Cache configuration for the edge host adapter.
41
+ *
42
+ * When set, per-boundary compiled outputs are memoized in the supplied KV
43
+ * namespace keyed by `(boundaryId, tier)`. `compile` is the user-provided
44
+ * function that produces the outputs on a cache miss; its result is
45
+ * written back to KV with the configured `ttl`.
46
+ */
47
+ export interface EdgeHostCacheConfig {
48
+ /** KV namespace backing the boundary cache. */
49
+ readonly kv: KVNamespace;
50
+ /** Content address of the boundary being compiled. */
51
+ readonly boundaryId: ContentAddress;
52
+ /** Compile function invoked on cache miss. */
53
+ readonly compile: (context: EdgeHostCompileContext) => Promise<CompiledOutputs> | CompiledOutputs;
54
+ /** Cache entry TTL in seconds. */
55
+ readonly ttl?: number;
56
+ /** Optional KV key prefix. */
57
+ readonly prefix?: string;
58
+ }
59
+ /**
60
+ * Configuration for {@link createEdgeHostAdapter}.
61
+ *
62
+ * `theme` may be a static {@link ThemeCompileConfig}, a per-request
63
+ * resolver function, or absent. `cache` enables a KV-backed boundary
64
+ * compile cache keyed by content address + tier.
65
+ */
66
+ export interface EdgeHostAdapterConfig {
67
+ /** Static theme config, or a resolver invoked with each request's context. */
68
+ readonly theme?: ThemeCompileConfig | ((context: EdgeHostContext) => ThemeCompileConfig | null | undefined);
69
+ /** KV-backed boundary output cache; omit to disable caching. */
70
+ readonly cache?: EdgeHostCacheConfig;
71
+ }
72
+ /** Cache lookup outcome reported in {@link EdgeHostResolution}. */
73
+ export type EdgeHostCacheStatus = 'disabled' | 'hit' | 'miss';
74
+ /**
75
+ * Full per-request resolution output from {@link EdgeHostAdapter.resolve}.
76
+ *
77
+ * Carries the device context, optional theme and compiled outputs, the
78
+ * `data-czap-*` attribute string for the root HTML element, and the
79
+ * `Accept-CH`/`Critical-CH` headers the response should send back.
80
+ */
81
+ export interface EdgeHostResolution extends EdgeHostContext {
82
+ /** Compiled theme result, if a theme config was resolved for this request. */
83
+ readonly theme?: ThemeCompileResult;
84
+ /** Compiled per-state outputs for the configured boundary, if caching is enabled. */
85
+ readonly compiledOutputs?: CompiledOutputs;
86
+ /** `data-czap-cap`/`data-czap-motion`/`data-czap-design` string for `<html>`. */
87
+ readonly htmlAttributes: string;
88
+ /** Response headers to send back so the browser will supply hints next time. */
89
+ readonly responseHeaders: {
90
+ /** `Accept-CH` header value. */
91
+ readonly acceptCH: string;
92
+ /** `Critical-CH` header value. */
93
+ readonly criticalCH: string;
94
+ };
95
+ /** Whether the boundary outputs came from cache, were computed and stored, or caching is off. */
96
+ readonly cacheStatus: EdgeHostCacheStatus;
97
+ }
98
+ /**
99
+ * Opaque host-facing adapter returned by {@link createEdgeHostAdapter}.
100
+ *
101
+ * Call `resolve(headers)` per request; the adapter drives tier detection,
102
+ * theme compilation, and boundary caching in a single pass.
103
+ */
104
+ export interface EdgeHostAdapter {
105
+ /** Resolve a request's device context, theme, and compiled outputs. */
106
+ resolve(headers: Headers | ClientHintsHeaders): Promise<EdgeHostResolution>;
107
+ }
108
+ /**
109
+ * Create an {@link EdgeHostAdapter} with optional theme and boundary cache.
110
+ *
111
+ * The returned adapter is designed to be instantiated once per worker and
112
+ * reused across requests; it caches a compiled static theme eagerly and
113
+ * only invokes the compile callback on cache miss when caching is enabled.
114
+ */
115
+ export declare function createEdgeHostAdapter(config?: EdgeHostAdapterConfig): EdgeHostAdapter;
116
+ /**
117
+ * Edge host adapter namespace.
118
+ *
119
+ * `EdgeHostAdapter.create(config)` builds a reusable adapter that resolves
120
+ * Client Hints, tiers, theme compilation, and KV-backed boundary caching
121
+ * in a single per-request pass.
122
+ */
123
+ export declare const EdgeHostAdapter: {
124
+ /** Alias for {@link createEdgeHostAdapter}. */
125
+ readonly create: typeof createEdgeHostAdapter;
126
+ };
127
+ export declare namespace EdgeHostAdapter {
128
+ /** Alias for {@link EdgeHostAdapterConfig}. */
129
+ type Config = EdgeHostAdapterConfig;
130
+ /** Alias for {@link EdgeHostResolution}. */
131
+ type Resolution = EdgeHostResolution;
132
+ /** Alias for {@link EdgeHostCacheStatus}. */
133
+ type CacheStatus = EdgeHostCacheStatus;
134
+ /** Alias for {@link EdgeHostContext}. */
135
+ type Context = EdgeHostContext;
136
+ /** Alias for {@link EdgeHostCompileContext}. */
137
+ type CompileContext = EdgeHostCompileContext;
138
+ }
139
+ //# sourceMappingURL=host-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-adapter.d.ts","sourceRoot":"","sources":["../src/host-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * EdgeHostAdapter -- canonical host-facing edge resolution path.
3
+ *
4
+ * Resolves client hints, tiering, optional theme compilation, and optional
5
+ * boundary compilation cache lookups in a single host-level operation.
6
+ *
7
+ * @module
8
+ */
9
+ import { ClientHints } from './client-hints.js';
10
+ import { EdgeTier } from './edge-tier.js';
11
+ import { createBoundaryCache } from './kv-cache.js';
12
+ import { compileTheme } from './theme-compiler.js';
13
+ function resolveThemeConfig(theme, context) {
14
+ if (typeof theme === 'function') {
15
+ return theme(context);
16
+ }
17
+ return theme;
18
+ }
19
+ /**
20
+ * Create an {@link EdgeHostAdapter} with optional theme and boundary cache.
21
+ *
22
+ * The returned adapter is designed to be instantiated once per worker and
23
+ * reused across requests; it caches a compiled static theme eagerly and
24
+ * only invokes the compile callback on cache miss when caching is enabled.
25
+ */
26
+ export function createEdgeHostAdapter(config = {}) {
27
+ let boundaryCache = null;
28
+ if (config.cache) {
29
+ boundaryCache = createBoundaryCache(config.cache.kv, {
30
+ ttl: config.cache.ttl,
31
+ prefix: config.cache.prefix,
32
+ });
33
+ }
34
+ const staticThemeConfig = typeof config.theme === 'function' ? undefined : config.theme;
35
+ let compiledStaticTheme;
36
+ if (staticThemeConfig) {
37
+ compiledStaticTheme = compileTheme(staticThemeConfig);
38
+ }
39
+ const responseHeaders = {
40
+ acceptCH: ClientHints.acceptCHHeader(),
41
+ criticalCH: ClientHints.criticalCHHeader(),
42
+ };
43
+ return {
44
+ async resolve(headers) {
45
+ const capabilities = ClientHints.parseClientHints(headers);
46
+ const tier = EdgeTier.detectTier(headers);
47
+ const context = { capabilities, tier };
48
+ const themeConfig = compiledStaticTheme ? undefined : resolveThemeConfig(config.theme, context);
49
+ let theme = compiledStaticTheme;
50
+ if (!theme && themeConfig) {
51
+ theme = compileTheme(themeConfig);
52
+ }
53
+ let compiledOutputs;
54
+ let cacheStatus = boundaryCache ? 'miss' : 'disabled';
55
+ if (boundaryCache && config.cache) {
56
+ const cached = await boundaryCache.getCompiledOutputs(config.cache.boundaryId, tier);
57
+ if (cached) {
58
+ compiledOutputs = cached;
59
+ cacheStatus = 'hit';
60
+ }
61
+ else {
62
+ compiledOutputs = await config.cache.compile({ capabilities, tier, theme });
63
+ await boundaryCache.putCompiledOutputs(config.cache.boundaryId, tier, compiledOutputs);
64
+ }
65
+ }
66
+ return {
67
+ capabilities,
68
+ tier,
69
+ theme,
70
+ compiledOutputs,
71
+ htmlAttributes: EdgeTier.tierDataAttributes(tier),
72
+ responseHeaders,
73
+ cacheStatus,
74
+ };
75
+ },
76
+ };
77
+ }
78
+ /**
79
+ * Edge host adapter namespace.
80
+ *
81
+ * `EdgeHostAdapter.create(config)` builds a reusable adapter that resolves
82
+ * Client Hints, tiers, theme compilation, and KV-backed boundary caching
83
+ * in a single per-request pass.
84
+ */
85
+ export const EdgeHostAdapter = {
86
+ /** Alias for {@link createEdgeHostAdapter}. */
87
+ create: createEdgeHostAdapter,
88
+ };
89
+ //# sourceMappingURL=host-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-adapter.js","sourceRoot":"","sources":["../src/host-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * `@czap/edge` — **LiteShip** edge-station: server-side tier detection,
3
+ * content-addressed boundary cache, and theme **casting** for first paint.
4
+ *
5
+ * Parses HTTP Client Hints headers into device capabilities, maps them
6
+ * to the same tier lattice used on the client, and provides helpers for
7
+ * HTML injection, KV-backed boundary caching, and per-tenant theme
8
+ * compilation.
9
+ *
10
+ * @module
11
+ */
12
+ export { ClientHints } from './client-hints.js';
13
+ export type { ClientHintsHeaders } from './client-hints.js';
14
+ export { EdgeTier } from './edge-tier.js';
15
+ export type { EdgeTierResult } from './edge-tier.js';
16
+ export { createBoundaryCache, KVCache } from './kv-cache.js';
17
+ export type { KVNamespace, BoundaryCache, CompiledOutputs } from './kv-cache.js';
18
+ export { compileTheme } from './theme-compiler.js';
19
+ export type { ThemeCompileConfig, ThemeCompileResult } from './theme-compiler.js';
20
+ export { createEdgeHostAdapter, EdgeHostAdapter } from './host-adapter.js';
21
+ export type { EdgeHostAdapterConfig, EdgeHostResolution, EdgeHostCacheConfig, EdgeHostCacheStatus, EdgeHostContext, EdgeHostCompileContext, } from './host-adapter.js';
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE5D,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7D,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEjF,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAElF,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC3E,YAAY,EACV,qBAAqB,EACrB,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EACf,sBAAsB,GACvB,MAAM,mBAAmB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * `@czap/edge` — **LiteShip** edge-station: server-side tier detection,
3
+ * content-addressed boundary cache, and theme **casting** for first paint.
4
+ *
5
+ * Parses HTTP Client Hints headers into device capabilities, maps them
6
+ * to the same tier lattice used on the client, and provides helpers for
7
+ * HTML injection, KV-backed boundary caching, and per-tenant theme
8
+ * compilation.
9
+ *
10
+ * @module
11
+ */
12
+ export { ClientHints } from './client-hints.js';
13
+ export { EdgeTier } from './edge-tier.js';
14
+ export { createBoundaryCache, KVCache } from './kv-cache.js';
15
+ export { compileTheme } from './theme-compiler.js';
16
+ export { createEdgeHostAdapter, EdgeHostAdapter } from './host-adapter.js';
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAG1C,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAG7D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnD,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Content-addressed boundary precomputation cache with a generic KV
3
+ * interface -- not coupled to any specific KV provider (Cloudflare,
4
+ * Deno KV, Vercel KV, etc.).
5
+ *
6
+ * Cache keys encode the boundary content address and the two-axis tier
7
+ * result so each tier combination gets its own cached compilation output.
8
+ *
9
+ * @module
10
+ */
11
+ import { type ContentAddress } from '@czap/core';
12
+ import type { EdgeTierResult } from './edge-tier.js';
13
+ /**
14
+ * Minimal KV namespace interface -- compatible with Cloudflare Workers KV,
15
+ * Deno KV, or any adapter that implements get/put with string values.
16
+ */
17
+ export interface KVNamespace {
18
+ get(key: string): Promise<string | null>;
19
+ put(key: string, value: string, options?: {
20
+ expirationTtl?: number;
21
+ }): Promise<void>;
22
+ }
23
+ /**
24
+ * Precompiled CSS outputs for a single boundary at a given tier.
25
+ */
26
+ export interface CompiledOutputs {
27
+ readonly css: string;
28
+ readonly propertyRegistrations: string;
29
+ readonly containerQueries: string;
30
+ }
31
+ /**
32
+ * Content-addressed cache for boundary compilation results keyed by
33
+ * tier combination.
34
+ */
35
+ export interface BoundaryCache {
36
+ getCompiledOutputs(boundaryId: ContentAddress, tierResult: EdgeTierResult): Promise<CompiledOutputs | null>;
37
+ putCompiledOutputs(boundaryId: ContentAddress, tierResult: EdgeTierResult, outputs: CompiledOutputs): Promise<void>;
38
+ }
39
+ interface CacheOptions {
40
+ readonly ttl?: number;
41
+ readonly prefix?: string;
42
+ }
43
+ /**
44
+ * Create a {@link BoundaryCache} backed by the provided KV namespace.
45
+ *
46
+ * Cache keys encode the boundary content address and the two-axis tier
47
+ * result so each tier combination gets its own cached compilation output.
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * import { KVCache } from '@czap/edge';
52
+ * import { ContentAddress } from '@czap/core';
53
+ *
54
+ * const kv = { get: async (k: string) => null, put: async (k: string, v: string) => {} };
55
+ * const cache = KVCache.createBoundaryCache(kv, { ttl: 3600, prefix: 'myapp' });
56
+ *
57
+ * const boundaryId = ContentAddress('fnv1a:abcd1234');
58
+ * const tierResult = {
59
+ * capLevel: 'reactive',
60
+ * motionTier: 'transitions',
61
+ * designTier: 'standard',
62
+ * } as const;
63
+ *
64
+ * // Store compiled outputs
65
+ * await cache.putCompiledOutputs(boundaryId, tierResult, {
66
+ * css: '...',
67
+ * propertyRegistrations: '...',
68
+ * containerQueries: '...',
69
+ * });
70
+ *
71
+ * // Retrieve cached outputs
72
+ * const cached = await cache.getCompiledOutputs(boundaryId, tierResult);
73
+ * ```
74
+ *
75
+ * @param kv - A generic KV namespace implementing get/put
76
+ * @param options - Optional TTL (seconds) and key prefix configuration
77
+ * @returns A {@link BoundaryCache} instance
78
+ */
79
+ export declare function createBoundaryCache(kv: KVNamespace, options?: CacheOptions): BoundaryCache;
80
+ /**
81
+ * KV cache namespace.
82
+ *
83
+ * Provides a content-addressed boundary precomputation cache backed by a
84
+ * generic KV interface (compatible with Cloudflare Workers KV, Deno KV,
85
+ * Vercel KV, etc.). Cache keys encode the boundary content address and
86
+ * the two-axis tier result (motion + design) so each tier combination
87
+ * gets its own cached CSS compilation output.
88
+ *
89
+ * @example
90
+ * ```ts
91
+ * import { KVCache } from '@czap/edge';
92
+ *
93
+ * const kv = { get: async (k: string) => null, put: async (k: string, v: string) => {} };
94
+ * const cache = KVCache.createBoundaryCache(kv, { ttl: 3600 });
95
+ * const outputs = await cache.getCompiledOutputs(boundaryId, tierResult);
96
+ * if (!outputs) {
97
+ * await cache.putCompiledOutputs(boundaryId, tierResult, compiled);
98
+ * }
99
+ * ```
100
+ */
101
+ export declare const KVCache: {
102
+ readonly createBoundaryCache: typeof createBoundaryCache;
103
+ };
104
+ export {};
105
+ //# sourceMappingURL=kv-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kv-cache.d.ts","sourceRoot":"","sources":["../src/kv-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAe,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAMrD;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACzC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtF;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACnC;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,kBAAkB,CAAC,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IAE5G,kBAAkB,CAAC,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACrH;AAMD,UAAU,YAAY;IACpB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAUD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,aAAa,CAgE1F;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,OAAO;;CAEV,CAAC"}
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Content-addressed boundary precomputation cache with a generic KV
3
+ * interface -- not coupled to any specific KV provider (Cloudflare,
4
+ * Deno KV, Vercel KV, etc.).
5
+ *
6
+ * Cache keys encode the boundary content address and the two-axis tier
7
+ * result so each tier combination gets its own cached compilation output.
8
+ *
9
+ * @module
10
+ */
11
+ import { Diagnostics } from '@czap/core';
12
+ function buildCacheKey(prefix, boundaryId, tierResult) {
13
+ return `${prefix}:boundary:${boundaryId}:${tierResult.motionTier}:${tierResult.designTier}`;
14
+ }
15
+ // ---------------------------------------------------------------------------
16
+ // Public API
17
+ // ---------------------------------------------------------------------------
18
+ /**
19
+ * Create a {@link BoundaryCache} backed by the provided KV namespace.
20
+ *
21
+ * Cache keys encode the boundary content address and the two-axis tier
22
+ * result so each tier combination gets its own cached compilation output.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * import { KVCache } from '@czap/edge';
27
+ * import { ContentAddress } from '@czap/core';
28
+ *
29
+ * const kv = { get: async (k: string) => null, put: async (k: string, v: string) => {} };
30
+ * const cache = KVCache.createBoundaryCache(kv, { ttl: 3600, prefix: 'myapp' });
31
+ *
32
+ * const boundaryId = ContentAddress('fnv1a:abcd1234');
33
+ * const tierResult = {
34
+ * capLevel: 'reactive',
35
+ * motionTier: 'transitions',
36
+ * designTier: 'standard',
37
+ * } as const;
38
+ *
39
+ * // Store compiled outputs
40
+ * await cache.putCompiledOutputs(boundaryId, tierResult, {
41
+ * css: '...',
42
+ * propertyRegistrations: '...',
43
+ * containerQueries: '...',
44
+ * });
45
+ *
46
+ * // Retrieve cached outputs
47
+ * const cached = await cache.getCompiledOutputs(boundaryId, tierResult);
48
+ * ```
49
+ *
50
+ * @param kv - A generic KV namespace implementing get/put
51
+ * @param options - Optional TTL (seconds) and key prefix configuration
52
+ * @returns A {@link BoundaryCache} instance
53
+ */
54
+ export function createBoundaryCache(kv, options) {
55
+ const prefix = options?.prefix ?? 'czap';
56
+ const ttl = options?.ttl;
57
+ return {
58
+ async getCompiledOutputs(boundaryId, tierResult) {
59
+ const key = buildCacheKey(prefix, boundaryId, tierResult);
60
+ const raw = await kv.get(key);
61
+ if (raw === null)
62
+ return null;
63
+ let parsed;
64
+ let invalidJson = false;
65
+ try {
66
+ parsed = JSON.parse(raw);
67
+ }
68
+ catch (error) {
69
+ if (error instanceof SyntaxError) {
70
+ invalidJson = true;
71
+ Diagnostics.warnOnce({
72
+ source: 'czap/edge.kv-cache',
73
+ code: 'invalid-cache-entry',
74
+ message: `Boundary cache entry "${key}" could not be parsed and will be treated as a cache miss.`,
75
+ cause: error,
76
+ });
77
+ }
78
+ else {
79
+ throw error;
80
+ }
81
+ }
82
+ if (invalidJson) {
83
+ return null;
84
+ }
85
+ if (typeof parsed === 'object' &&
86
+ parsed !== null &&
87
+ 'css' in parsed &&
88
+ 'propertyRegistrations' in parsed &&
89
+ 'containerQueries' in parsed) {
90
+ return {
91
+ css: String(parsed.css),
92
+ propertyRegistrations: String(parsed.propertyRegistrations),
93
+ containerQueries: String(parsed.containerQueries),
94
+ };
95
+ }
96
+ return null;
97
+ },
98
+ async putCompiledOutputs(boundaryId, tierResult, outputs) {
99
+ const key = buildCacheKey(prefix, boundaryId, tierResult);
100
+ const value = JSON.stringify({
101
+ css: outputs.css,
102
+ propertyRegistrations: outputs.propertyRegistrations,
103
+ containerQueries: outputs.containerQueries,
104
+ });
105
+ await kv.put(key, value, ttl !== undefined ? { expirationTtl: ttl } : undefined);
106
+ },
107
+ };
108
+ }
109
+ /**
110
+ * KV cache namespace.
111
+ *
112
+ * Provides a content-addressed boundary precomputation cache backed by a
113
+ * generic KV interface (compatible with Cloudflare Workers KV, Deno KV,
114
+ * Vercel KV, etc.). Cache keys encode the boundary content address and
115
+ * the two-axis tier result (motion + design) so each tier combination
116
+ * gets its own cached CSS compilation output.
117
+ *
118
+ * @example
119
+ * ```ts
120
+ * import { KVCache } from '@czap/edge';
121
+ *
122
+ * const kv = { get: async (k: string) => null, put: async (k: string, v: string) => {} };
123
+ * const cache = KVCache.createBoundaryCache(kv, { ttl: 3600 });
124
+ * const outputs = await cache.getCompiledOutputs(boundaryId, tierResult);
125
+ * if (!outputs) {
126
+ * await cache.putCompiledOutputs(boundaryId, tierResult, compiled);
127
+ * }
128
+ * ```
129
+ */
130
+ export const KVCache = {
131
+ createBoundaryCache,
132
+ };
133
+ //# sourceMappingURL=kv-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kv-cache.js","sourceRoot":"","sources":["../src/kv-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,WAAW,EAAuB,MAAM,YAAY,CAAC;AA4C9D,SAAS,aAAa,CAAC,MAAc,EAAE,UAA0B,EAAE,UAA0B;IAC3F,OAAO,GAAG,MAAM,aAAa,UAAU,IAAI,UAAU,CAAC,UAAU,IAAI,UAAU,CAAC,UAAU,EAAE,CAAC;AAC9F,CAAC;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAAe,EAAE,OAAsB;IACzE,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,MAAM,CAAC;IACzC,MAAM,GAAG,GAAG,OAAO,EAAE,GAAG,CAAC;IAEzB,OAAO;QACL,KAAK,CAAC,kBAAkB,CAAC,UAA0B,EAAE,UAA0B;YAC7E,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;YAC1D,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC9B,IAAI,GAAG,KAAK,IAAI;gBAAE,OAAO,IAAI,CAAC;YAE9B,IAAI,MAAe,CAAC;YACpB,IAAI,WAAW,GAAG,KAAK,CAAC;YACxB,IAAI,CAAC;gBACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC3B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;oBACjC,WAAW,GAAG,IAAI,CAAC;oBACnB,WAAW,CAAC,QAAQ,CAAC;wBACnB,MAAM,EAAE,oBAAoB;wBAC5B,IAAI,EAAE,qBAAqB;wBAC3B,OAAO,EAAE,yBAAyB,GAAG,4DAA4D;wBACjG,KAAK,EAAE,KAAK;qBACb,CAAC,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACN,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;YAED,IAAI,WAAW,EAAE,CAAC;gBAChB,OAAO,IAAI,CAAC;YACd,CAAC;YAED,IACE,OAAO,MAAM,KAAK,QAAQ;gBAC1B,MAAM,KAAK,IAAI;gBACf,KAAK,IAAI,MAAM;gBACf,uBAAuB,IAAI,MAAM;gBACjC,kBAAkB,IAAI,MAAM,EAC5B,CAAC;gBACD,OAAO;oBACL,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC;oBACvB,qBAAqB,EAAE,MAAM,CAAC,MAAM,CAAC,qBAAqB,CAAC;oBAC3D,gBAAgB,EAAE,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC;iBAClD,CAAC;YACJ,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;QAED,KAAK,CAAC,kBAAkB,CACtB,UAA0B,EAC1B,UAA0B,EAC1B,OAAwB;YAExB,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;YAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC;gBAC3B,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,qBAAqB,EAAE,OAAO,CAAC,qBAAqB;gBACpD,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;aAC3C,CAAC,CAAC;YAEH,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACnF,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,mBAAmB;CACX,CAAC"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Per-tenant theme compilation at the edge.
3
+ *
4
+ * Takes a flat map of design token definitions and produces CSS custom
5
+ * property declarations suitable for injection into the `<html>` element
6
+ * or a `<style>` block.
7
+ *
8
+ * This is a pure function with no side effects -- safe for edge runtime use.
9
+ *
10
+ * @module
11
+ */
12
+ /**
13
+ * Input to {@link compileTheme}.
14
+ *
15
+ * Tokens are flat key/value pairs — nested paths like `color.primary` are
16
+ * sanitized into CSS-safe custom property names. Numeric values are emitted
17
+ * bare so consumers can apply their own units downstream.
18
+ */
19
+ export interface ThemeCompileConfig {
20
+ /** Flat map of token name to value (string or numeric). */
21
+ readonly tokens: Readonly<Record<string, string | number>>;
22
+ /** CSS custom property prefix. Defaults to `'czap'`. */
23
+ readonly prefix?: string;
24
+ }
25
+ /**
26
+ * Output of {@link compileTheme}.
27
+ *
28
+ * Provides three views of the same declarations: structured, a full CSS
29
+ * rule, and an inline-style string — so hosts can pick whichever
30
+ * serialization best fits their HTML injection strategy.
31
+ */
32
+ export interface ThemeCompileResult {
33
+ /** Structured declarations suitable for serializer-specific output. */
34
+ readonly declarations: readonly ThemeDeclaration[];
35
+ /** Full CSS rule with custom property declarations inside `:root {}`. */
36
+ readonly css: string;
37
+ /** Inline style string for `<html style="...">` injection. */
38
+ readonly inlineStyle: string;
39
+ }
40
+ /** A single compiled CSS custom property declaration. */
41
+ export interface ThemeDeclaration {
42
+ /** Full CSS custom property name including the `--prefix-` prefix. */
43
+ readonly property: string;
44
+ /** Formatted value (numbers stringified bare, strings validated). */
45
+ readonly value: string;
46
+ }
47
+ /**
48
+ * Compile a set of design tokens into CSS custom property declarations.
49
+ *
50
+ * @param config - Token definitions and optional prefix.
51
+ * @returns CSS string and inline style string.
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * const result = compileTheme({
56
+ * tokens: { 'color.primary': '#3b82f6', 'spacing.base': 16 },
57
+ * prefix: 'czap',
58
+ * });
59
+ * // result.css =>
60
+ * // :root {
61
+ * // --czap-color-primary: #3b82f6;
62
+ * // --czap-spacing-base: 16;
63
+ * // }
64
+ * // result.inlineStyle =>
65
+ * // --czap-color-primary:#3b82f6;--czap-spacing-base:16
66
+ * ```
67
+ */
68
+ export declare function compileTheme(config: ThemeCompileConfig): ThemeCompileResult;
69
+ //# sourceMappingURL=theme-compiler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-compiler.d.ts","sourceRoot":"","sources":["../src/theme-compiler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC;IAC3D,wDAAwD;IACxD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,uEAAuE;IACvE,QAAQ,CAAC,YAAY,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACnD,yEAAyE;IACzE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,8DAA8D;IAC9D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,yDAAyD;AACzD,MAAM,WAAW,gBAAgB;IAC/B,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,qEAAqE;IACrE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAiDD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,kBAAkB,CA4B3E"}