@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.
- package/LICENSE +21 -0
- package/README.md +19 -0
- package/dist/client-hints.d.ts +145 -0
- package/dist/client-hints.d.ts.map +1 -0
- package/dist/client-hints.js +268 -0
- package/dist/client-hints.js.map +1 -0
- package/dist/edge-tier.d.ts +67 -0
- package/dist/edge-tier.d.ts.map +1 -0
- package/dist/edge-tier.js +60 -0
- package/dist/edge-tier.js.map +1 -0
- package/dist/host-adapter.d.ts +139 -0
- package/dist/host-adapter.d.ts.map +1 -0
- package/dist/host-adapter.js +89 -0
- package/dist/host-adapter.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/kv-cache.d.ts +105 -0
- package/dist/kv-cache.d.ts.map +1 -0
- package/dist/kv-cache.js +133 -0
- package/dist/kv-cache.js.map +1 -0
- package/dist/theme-compiler.d.ts +69 -0
- package/dist/theme-compiler.d.ts.map +1 -0
- package/dist/theme-compiler.js +94 -0
- package/dist/theme-compiler.js.map +1 -0
- package/package.json +55 -0
- package/src/client-hints.ts +338 -0
- package/src/edge-tier.ts +93 -0
- package/src/host-adapter.ts +217 -0
- package/src/index.ts +33 -0
- package/src/kv-cache.ts +189 -0
- package/src/theme-compiler.ts +151 -0
|
@@ -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":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAE/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAElE,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAElF;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,6CAA6C;IAC7C,QAAQ,CAAC,YAAY,EAAE,0BAA0B,CAAC;IAClD,iDAAiD;IACjD,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;CAC/B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,sBAAuB,SAAQ,eAAe;IAC7D,+EAA+E;IAC/E,QAAQ,CAAC,KAAK,CAAC,EAAE,kBAAkB,CAAC;CACrC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,mBAAmB;IAClC,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,EAAE,WAAW,CAAC;IACzB,sDAAsD;IACtD,QAAQ,CAAC,UAAU,EAAE,cAAc,CAAC;IACpC,8CAA8C;IAC9C,QAAQ,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,sBAAsB,KAAK,OAAO,CAAC,eAAe,CAAC,GAAG,eAAe,CAAC;IAClG,kCAAkC;IAClC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,8BAA8B;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,CAAC,EAAE,kBAAkB,GAAG,CAAC,CAAC,OAAO,EAAE,eAAe,KAAK,kBAAkB,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAC5G,gEAAgE;IAChE,QAAQ,CAAC,KAAK,CAAC,EAAE,mBAAmB,CAAC;CACtC;AAED,mEAAmE;AACnE,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,KAAK,GAAG,MAAM,CAAC;AAE9D;;;;;;GAMG;AACH,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IACzD,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,CAAC,EAAE,kBAAkB,CAAC;IACpC,qFAAqF;IACrF,QAAQ,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC;IAC3C,iFAAiF;IACjF,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,gFAAgF;IAChF,QAAQ,CAAC,eAAe,EAAE;QACxB,gCAAgC;QAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,kCAAkC;QAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;KAC7B,CAAC;IACF,iGAAiG;IACjG,QAAQ,CAAC,WAAW,EAAE,mBAAmB,CAAC;CAC3C;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAC7E;AAYD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,GAAE,qBAA0B,GAAG,eAAe,CAsDzF;AAED;;;;;;GAMG;AACH,eAAO,MAAM,eAAe;IAC1B,+CAA+C;;CAEvC,CAAC;AAEX,MAAM,CAAC,OAAO,WAAW,eAAe,CAAC;IACvC,+CAA+C;IAC/C,KAAY,MAAM,GAAG,qBAAqB,CAAC;IAC3C,4CAA4C;IAC5C,KAAY,UAAU,GAAG,kBAAkB,CAAC;IAC5C,6CAA6C;IAC7C,KAAY,WAAW,GAAG,mBAAmB,CAAC;IAC9C,yCAAyC;IACzC,KAAY,OAAO,GAAG,eAAe,CAAC;IACtC,gDAAgD;IAChD,KAAY,cAAc,GAAG,sBAAsB,CAAC;CACrD"}
|
|
@@ -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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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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"}
|
package/dist/kv-cache.js
ADDED
|
@@ -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":"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"}
|
|
@@ -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"}
|