@decantr/registry 1.0.0-beta.1 → 1.0.0-beta.10
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/dist/index.d.ts +233 -31
- package/dist/index.js +236 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -34,9 +34,17 @@ interface Pattern {
|
|
|
34
34
|
}
|
|
35
35
|
interface ArchetypePage {
|
|
36
36
|
id: string;
|
|
37
|
-
default_layout: string
|
|
37
|
+
default_layout: (string | {
|
|
38
|
+
pattern: string;
|
|
39
|
+
preset?: string;
|
|
40
|
+
as?: string;
|
|
41
|
+
})[];
|
|
38
42
|
shell: string;
|
|
39
43
|
}
|
|
44
|
+
interface SeoHints {
|
|
45
|
+
schema_org?: string[];
|
|
46
|
+
meta_priorities?: string[];
|
|
47
|
+
}
|
|
40
48
|
interface Archetype {
|
|
41
49
|
id: string;
|
|
42
50
|
version: string;
|
|
@@ -47,24 +55,24 @@ interface Archetype {
|
|
|
47
55
|
features: string[];
|
|
48
56
|
dependencies: {
|
|
49
57
|
patterns: Record<string, string>;
|
|
50
|
-
recipes: Record<string, string>;
|
|
51
58
|
};
|
|
59
|
+
seo_hints?: SeoHints;
|
|
52
60
|
}
|
|
53
|
-
interface
|
|
61
|
+
interface ThemeSpatial {
|
|
54
62
|
density_bias: number;
|
|
55
63
|
content_gap_shift: number;
|
|
56
64
|
section_padding: string;
|
|
57
65
|
card_wrapping: 'always' | 'minimal' | 'none';
|
|
58
66
|
surface_override: string | null;
|
|
59
67
|
}
|
|
60
|
-
interface
|
|
68
|
+
interface ThemeEffects {
|
|
61
69
|
enabled: boolean;
|
|
62
70
|
intensity: 'subtle' | 'moderate' | 'bold';
|
|
63
71
|
type_mapping: Record<string, string[]>;
|
|
64
72
|
component_fallback: Record<string, string>;
|
|
65
73
|
intensity_values?: Record<string, Record<string, string>>;
|
|
66
74
|
}
|
|
67
|
-
interface
|
|
75
|
+
interface ThemeShell {
|
|
68
76
|
preferred: string[];
|
|
69
77
|
nav_style: string;
|
|
70
78
|
root?: string;
|
|
@@ -75,40 +83,168 @@ interface RecipeShell {
|
|
|
75
83
|
headerHeight?: string;
|
|
76
84
|
};
|
|
77
85
|
}
|
|
78
|
-
|
|
86
|
+
type ArchetypeRole = 'primary' | 'gateway' | 'public' | 'auxiliary';
|
|
87
|
+
type ComposeEntry = string | {
|
|
88
|
+
archetype: string;
|
|
89
|
+
prefix: string;
|
|
90
|
+
role?: ArchetypeRole;
|
|
91
|
+
};
|
|
92
|
+
interface Blueprint {
|
|
79
93
|
id: string;
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
avoid: string[];
|
|
89
|
-
default_presets?: Record<string, string>;
|
|
94
|
+
name: string;
|
|
95
|
+
description?: string;
|
|
96
|
+
archetype: string;
|
|
97
|
+
compose?: ComposeEntry[];
|
|
98
|
+
theme: {
|
|
99
|
+
id: string;
|
|
100
|
+
mode?: string;
|
|
101
|
+
shape?: string;
|
|
90
102
|
};
|
|
91
|
-
|
|
92
|
-
|
|
103
|
+
personality?: string;
|
|
104
|
+
pages: Array<{
|
|
105
|
+
id: string;
|
|
106
|
+
layout: string[];
|
|
107
|
+
shell?: string;
|
|
93
108
|
}>;
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
109
|
+
features?: string[];
|
|
110
|
+
version?: string;
|
|
111
|
+
}
|
|
112
|
+
interface Shell {
|
|
113
|
+
id: string;
|
|
114
|
+
name: string;
|
|
115
|
+
description?: string;
|
|
116
|
+
root?: string;
|
|
117
|
+
nav?: string;
|
|
118
|
+
header?: string;
|
|
119
|
+
nav_style?: string;
|
|
120
|
+
dimensions?: {
|
|
121
|
+
navWidth?: string;
|
|
122
|
+
headerHeight?: string;
|
|
97
123
|
};
|
|
98
124
|
}
|
|
99
|
-
type ContentType = 'pattern' | 'archetype' | '
|
|
125
|
+
type ContentType = 'pattern' | 'archetype' | 'theme' | 'blueprint';
|
|
100
126
|
interface ResolvedContent<T> {
|
|
101
127
|
item: T;
|
|
102
|
-
source: 'local' | '
|
|
128
|
+
source: 'local' | 'core';
|
|
103
129
|
path: string;
|
|
104
130
|
}
|
|
131
|
+
type CvdMode = 'deuteranopia' | 'protanopia' | 'tritanopia' | 'achromatopsia';
|
|
132
|
+
interface ThemeTokens {
|
|
133
|
+
base?: Record<string, string>;
|
|
134
|
+
cvd?: Partial<Record<CvdMode, Record<string, string>>>;
|
|
135
|
+
}
|
|
136
|
+
interface Theme {
|
|
137
|
+
id: string;
|
|
138
|
+
name: string;
|
|
139
|
+
description?: string;
|
|
140
|
+
tags?: string[];
|
|
141
|
+
personality?: string;
|
|
142
|
+
seed?: Record<string, string>;
|
|
143
|
+
palette?: Record<string, Record<string, string>>;
|
|
144
|
+
modes?: string[];
|
|
145
|
+
shapes?: string[];
|
|
146
|
+
cvd_support?: CvdMode[];
|
|
147
|
+
tokens?: ThemeTokens;
|
|
148
|
+
decantr_compat?: string;
|
|
149
|
+
source?: string;
|
|
150
|
+
decorators?: Record<string, string>;
|
|
151
|
+
treatments?: Record<string, Record<string, string>>;
|
|
152
|
+
spatial?: ThemeSpatial;
|
|
153
|
+
shell?: ThemeShell;
|
|
154
|
+
effects?: ThemeEffects;
|
|
155
|
+
motion?: {
|
|
156
|
+
preference?: string;
|
|
157
|
+
reduce_motion?: boolean;
|
|
158
|
+
entrance?: string;
|
|
159
|
+
timing?: string;
|
|
160
|
+
durations?: Record<string, string>;
|
|
161
|
+
};
|
|
162
|
+
typography?: {
|
|
163
|
+
scale?: string;
|
|
164
|
+
heading_weight?: number;
|
|
165
|
+
body_weight?: number;
|
|
166
|
+
mono?: string;
|
|
167
|
+
};
|
|
168
|
+
radius?: {
|
|
169
|
+
philosophy?: string;
|
|
170
|
+
base?: number;
|
|
171
|
+
};
|
|
172
|
+
compositions?: Record<string, {
|
|
173
|
+
shell: string;
|
|
174
|
+
description: string;
|
|
175
|
+
effects?: string[];
|
|
176
|
+
}>;
|
|
177
|
+
pattern_preferences?: {
|
|
178
|
+
prefer: string[];
|
|
179
|
+
avoid: string[];
|
|
180
|
+
default_presets?: Record<string, string>;
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
type ApiContentType = 'patterns' | 'themes' | 'blueprints' | 'archetypes' | 'shells';
|
|
184
|
+
interface ContentListResponse<T = Record<string, unknown>> {
|
|
185
|
+
items: T[];
|
|
186
|
+
total: number;
|
|
187
|
+
}
|
|
188
|
+
interface ContentItem {
|
|
189
|
+
id: string;
|
|
190
|
+
slug: string;
|
|
191
|
+
namespace: string;
|
|
192
|
+
type: string;
|
|
193
|
+
version: string;
|
|
194
|
+
data: Record<string, unknown>;
|
|
195
|
+
visibility: 'public' | 'private';
|
|
196
|
+
status: 'pending' | 'approved' | 'rejected' | 'published';
|
|
197
|
+
created_at: string;
|
|
198
|
+
updated_at: string;
|
|
199
|
+
published_at?: string;
|
|
200
|
+
}
|
|
201
|
+
interface PublishPayload {
|
|
202
|
+
type: ApiContentType;
|
|
203
|
+
slug: string;
|
|
204
|
+
namespace: string;
|
|
205
|
+
version: string;
|
|
206
|
+
data: Record<string, unknown>;
|
|
207
|
+
visibility?: 'public' | 'private';
|
|
208
|
+
}
|
|
209
|
+
interface PublishResponse {
|
|
210
|
+
id: string;
|
|
211
|
+
slug: string;
|
|
212
|
+
namespace: string;
|
|
213
|
+
type: string;
|
|
214
|
+
status: string;
|
|
215
|
+
}
|
|
216
|
+
interface SearchParams {
|
|
217
|
+
q: string;
|
|
218
|
+
type?: string;
|
|
219
|
+
namespace?: string;
|
|
220
|
+
limit?: number;
|
|
221
|
+
offset?: number;
|
|
222
|
+
}
|
|
223
|
+
interface SearchResponse {
|
|
224
|
+
results: Array<{
|
|
225
|
+
id: string;
|
|
226
|
+
type: string;
|
|
227
|
+
slug: string;
|
|
228
|
+
namespace: string;
|
|
229
|
+
name: string;
|
|
230
|
+
description: string;
|
|
231
|
+
version: string;
|
|
232
|
+
}>;
|
|
233
|
+
total: number;
|
|
234
|
+
}
|
|
235
|
+
interface UserProfile {
|
|
236
|
+
id: string;
|
|
237
|
+
email: string;
|
|
238
|
+
tier: 'free' | 'pro' | 'team' | 'enterprise';
|
|
239
|
+
reputation_score: number;
|
|
240
|
+
trusted: boolean;
|
|
241
|
+
}
|
|
105
242
|
|
|
106
243
|
type ContentMap = {
|
|
107
244
|
pattern: Pattern;
|
|
108
245
|
archetype: Archetype;
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
blueprint: Record<string, unknown>;
|
|
246
|
+
theme: Theme;
|
|
247
|
+
blueprint: Blueprint;
|
|
112
248
|
};
|
|
113
249
|
interface ResolverOptions {
|
|
114
250
|
contentRoot: string;
|
|
@@ -124,7 +260,7 @@ interface ResolvedPreset {
|
|
|
124
260
|
layout: PatternPreset['layout'];
|
|
125
261
|
code: PatternPreset['code'];
|
|
126
262
|
}
|
|
127
|
-
declare function resolvePatternPreset(pattern: Pattern, explicitPreset?: string,
|
|
263
|
+
declare function resolvePatternPreset(pattern: Pattern, explicitPreset?: string, themeDefaultPresets?: Record<string, string>): ResolvedPreset;
|
|
128
264
|
|
|
129
265
|
type HookType = 'search' | 'filter' | 'selection' | 'sort';
|
|
130
266
|
interface WiringSignal {
|
|
@@ -144,13 +280,79 @@ interface WiringResult {
|
|
|
144
280
|
props: Record<string, Record<string, string>>;
|
|
145
281
|
hookProps: Record<string, Record<string, string>>;
|
|
146
282
|
}
|
|
283
|
+
/**
|
|
284
|
+
* IO declaration for a pattern, used by the data-driven wiring system.
|
|
285
|
+
*/
|
|
286
|
+
interface PatternIOEntry {
|
|
287
|
+
id: string;
|
|
288
|
+
io: PatternIO;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* A dynamically derived wiring edge between two patterns based on shared IO signals.
|
|
292
|
+
*/
|
|
293
|
+
interface IOWiringEdge {
|
|
294
|
+
producer: string;
|
|
295
|
+
consumer: string;
|
|
296
|
+
signals: string[];
|
|
297
|
+
}
|
|
147
298
|
declare const WIRING_RULES: WiringRule[];
|
|
148
|
-
|
|
299
|
+
/**
|
|
300
|
+
* Derive wiring edges from pattern IO declarations.
|
|
301
|
+
* If pattern A produces signal X and pattern B consumes signal X, an edge is created.
|
|
302
|
+
* Only patterns present in the layout are considered.
|
|
303
|
+
*/
|
|
304
|
+
declare function deriveIOWirings(layoutIds: string[], patternIOMap: Map<string, PatternIO>): IOWiringEdge[];
|
|
305
|
+
/**
|
|
306
|
+
* Build a PatternIO map from an array of PatternIOEntry objects.
|
|
307
|
+
*/
|
|
308
|
+
declare function buildIOMap(entries: PatternIOEntry[]): Map<string, PatternIO>;
|
|
309
|
+
/**
|
|
310
|
+
* Detect wirings from a layout. Uses hardcoded WIRING_RULES for detailed
|
|
311
|
+
* signal/prop information. When a patternIOMap is provided, also derives
|
|
312
|
+
* IO-based wirings and merges them (hardcoded rules take precedence for
|
|
313
|
+
* pairs they cover).
|
|
314
|
+
*/
|
|
315
|
+
declare function detectWirings(layout: LayoutItem[], patternIOMap?: Map<string, PatternIO>): WiringResult[];
|
|
149
316
|
|
|
317
|
+
interface RegistryAPIClientOptions {
|
|
318
|
+
baseUrl?: string;
|
|
319
|
+
apiKey?: string;
|
|
320
|
+
timeoutMs?: number;
|
|
321
|
+
cacheTtlMs?: number;
|
|
322
|
+
}
|
|
323
|
+
declare class RegistryAPIClient {
|
|
324
|
+
private baseUrl;
|
|
325
|
+
private apiKey;
|
|
326
|
+
private timeoutMs;
|
|
327
|
+
private cacheTtlMs;
|
|
328
|
+
private cache;
|
|
329
|
+
constructor(options?: RegistryAPIClientOptions);
|
|
330
|
+
private buildHeaders;
|
|
331
|
+
private fetchWithTimeout;
|
|
332
|
+
private request;
|
|
333
|
+
private getCached;
|
|
334
|
+
private setCache;
|
|
335
|
+
clearCache(): void;
|
|
336
|
+
checkHealth(): Promise<boolean>;
|
|
337
|
+
listContent<T = Record<string, unknown>>(type: ApiContentType, params?: {
|
|
338
|
+
namespace?: string;
|
|
339
|
+
limit?: number;
|
|
340
|
+
offset?: number;
|
|
341
|
+
}): Promise<ContentListResponse<T>>;
|
|
342
|
+
getContent<T = Record<string, unknown>>(type: ApiContentType, namespace: string, slug: string): Promise<T>;
|
|
343
|
+
getPattern(namespace: string, slug: string): Promise<Pattern>;
|
|
344
|
+
getArchetype(namespace: string, slug: string): Promise<Archetype>;
|
|
345
|
+
getTheme(namespace: string, slug: string): Promise<Theme>;
|
|
346
|
+
getBlueprint(namespace: string, slug: string): Promise<Blueprint>;
|
|
347
|
+
getShell(namespace: string, slug: string): Promise<Shell>;
|
|
348
|
+
search(params: SearchParams): Promise<SearchResponse>;
|
|
349
|
+
getProfile(): Promise<UserProfile>;
|
|
350
|
+
publishContent(payload: PublishPayload): Promise<PublishResponse>;
|
|
351
|
+
getMyContent(): Promise<ContentListResponse<ContentItem>>;
|
|
352
|
+
getSchema(name?: string): Promise<Record<string, unknown>>;
|
|
353
|
+
}
|
|
150
354
|
interface RegistryClientOptions {
|
|
151
355
|
baseUrl?: string;
|
|
152
|
-
cacheDir?: string;
|
|
153
|
-
cacheTtl?: number;
|
|
154
356
|
}
|
|
155
357
|
interface SearchResult {
|
|
156
358
|
id: string;
|
|
@@ -166,4 +368,4 @@ interface RegistryClient {
|
|
|
166
368
|
}
|
|
167
369
|
declare function createRegistryClient(options?: RegistryClientOptions): RegistryClient;
|
|
168
370
|
|
|
169
|
-
export { type Archetype, type ArchetypePage, type ContentResolver, type ContentType, type HookType, type Pattern, type PatternIO, type
|
|
371
|
+
export { type ApiContentType, type Archetype, type ArchetypePage, type ArchetypeRole, type Blueprint, type ComposeEntry, type ContentItem, type ContentListResponse, type ContentResolver, type ContentType, type CvdMode, type HookType, type IOWiringEdge, type Pattern, type PatternIO, type PatternIOEntry, type PatternPreset, type PublishPayload, type PublishResponse, RegistryAPIClient, type RegistryAPIClientOptions, type RegistryClient, type RegistryClientOptions, type ResolvedContent, type ResolvedPreset, type ResolverOptions, type SearchParams, type SearchResponse, type SearchResult, type Shell, type Theme, type ThemeEffects, type ThemeShell, type ThemeSpatial, type ThemeTokens, type UserProfile, WIRING_RULES, type WiringResult, type WiringRule, type WiringSignal, buildIOMap, createRegistryClient, createResolver, deriveIOWirings, detectWirings, resolvePatternPreset };
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,6 @@ import { join } from "path";
|
|
|
4
4
|
var TYPE_DIRS = {
|
|
5
5
|
pattern: "patterns",
|
|
6
6
|
archetype: "archetypes",
|
|
7
|
-
recipe: "recipes",
|
|
8
7
|
theme: "themes",
|
|
9
8
|
blueprint: "blueprints"
|
|
10
9
|
};
|
|
@@ -27,7 +26,10 @@ function createResolver(options) {
|
|
|
27
26
|
const item = await tryLoadJson(filePath);
|
|
28
27
|
if (item) return { item, source: "local", path: filePath };
|
|
29
28
|
}
|
|
30
|
-
const
|
|
29
|
+
const mainPath = join(contentRoot, dir, fileName);
|
|
30
|
+
const mainItem = await tryLoadJson(mainPath);
|
|
31
|
+
if (mainItem) return { item: mainItem, source: "core", path: mainPath };
|
|
32
|
+
const corePath = join(contentRoot, "core", dir, fileName);
|
|
31
33
|
const coreItem = await tryLoadJson(corePath);
|
|
32
34
|
if (coreItem) return { item: coreItem, source: "core", path: corePath };
|
|
33
35
|
return null;
|
|
@@ -36,7 +38,7 @@ function createResolver(options) {
|
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
// src/pattern.ts
|
|
39
|
-
function resolvePatternPreset(pattern, explicitPreset,
|
|
41
|
+
function resolvePatternPreset(pattern, explicitPreset, themeDefaultPresets) {
|
|
40
42
|
const presets = pattern.presets;
|
|
41
43
|
const hasPresets = Object.keys(presets).length > 0;
|
|
42
44
|
if (!hasPresets) {
|
|
@@ -48,9 +50,9 @@ function resolvePatternPreset(pattern, explicitPreset, recipeDefaultPresets) {
|
|
|
48
50
|
}
|
|
49
51
|
let presetName = explicitPreset;
|
|
50
52
|
if (presetName && !presets[presetName]) presetName = void 0;
|
|
51
|
-
if (!presetName &&
|
|
52
|
-
const
|
|
53
|
-
if (presets[
|
|
53
|
+
if (!presetName && themeDefaultPresets?.[pattern.id]) {
|
|
54
|
+
const themeName = themeDefaultPresets[pattern.id];
|
|
55
|
+
if (presets[themeName]) presetName = themeName;
|
|
54
56
|
}
|
|
55
57
|
if (!presetName) presetName = pattern.default_preset;
|
|
56
58
|
if (!presetName || !presets[presetName]) presetName = Object.keys(presets)[0];
|
|
@@ -110,28 +112,249 @@ function getPatternId(item) {
|
|
|
110
112
|
if ("pattern" in item) return item.pattern;
|
|
111
113
|
return null;
|
|
112
114
|
}
|
|
113
|
-
function
|
|
115
|
+
function deriveIOWirings(layoutIds, patternIOMap) {
|
|
116
|
+
const edges = [];
|
|
117
|
+
const layoutSet = new Set(layoutIds);
|
|
118
|
+
for (const producerId of layoutIds) {
|
|
119
|
+
const producerIO = patternIOMap.get(producerId);
|
|
120
|
+
if (!producerIO?.produces?.length) continue;
|
|
121
|
+
for (const consumerId of layoutIds) {
|
|
122
|
+
if (producerId === consumerId) continue;
|
|
123
|
+
if (!layoutSet.has(consumerId)) continue;
|
|
124
|
+
const consumerIO = patternIOMap.get(consumerId);
|
|
125
|
+
if (!consumerIO?.consumes?.length) continue;
|
|
126
|
+
const shared = producerIO.produces.filter(
|
|
127
|
+
(signal) => consumerIO.consumes.includes(signal)
|
|
128
|
+
);
|
|
129
|
+
if (shared.length > 0) {
|
|
130
|
+
edges.push({ producer: producerId, consumer: consumerId, signals: shared });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return edges;
|
|
135
|
+
}
|
|
136
|
+
function buildIOMap(entries) {
|
|
137
|
+
const map = /* @__PURE__ */ new Map();
|
|
138
|
+
for (const entry of entries) {
|
|
139
|
+
map.set(entry.id, entry.io);
|
|
140
|
+
}
|
|
141
|
+
return map;
|
|
142
|
+
}
|
|
143
|
+
function detectWirings(layout, patternIOMap) {
|
|
114
144
|
const patternIds = layout.map(getPatternId).filter((id) => id !== null);
|
|
115
145
|
const results = [];
|
|
146
|
+
const coveredPairs = /* @__PURE__ */ new Set();
|
|
116
147
|
for (const rule of WIRING_RULES) {
|
|
117
148
|
const [a, b] = rule.pair;
|
|
118
149
|
if (patternIds.includes(a) && patternIds.includes(b)) {
|
|
119
150
|
results.push({ rule, signals: rule.signals, props: rule.props, hookProps: rule.hookProps });
|
|
151
|
+
coveredPairs.add(`${a}:${b}`);
|
|
152
|
+
coveredPairs.add(`${b}:${a}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (patternIOMap) {
|
|
156
|
+
const ioEdges = deriveIOWirings(patternIds, patternIOMap);
|
|
157
|
+
for (const edge of ioEdges) {
|
|
158
|
+
const pairKey = `${edge.producer}:${edge.consumer}`;
|
|
159
|
+
if (coveredPairs.has(pairKey)) continue;
|
|
160
|
+
coveredPairs.add(pairKey);
|
|
161
|
+
const signals = edge.signals.map((sig) => {
|
|
162
|
+
const camel = toCamelCase(sig);
|
|
163
|
+
return {
|
|
164
|
+
name: `page${capitalize(camel)}`,
|
|
165
|
+
init: "''",
|
|
166
|
+
hookType: classifySignal(sig)
|
|
167
|
+
};
|
|
168
|
+
});
|
|
169
|
+
const producerProps = {};
|
|
170
|
+
const consumerProps = {};
|
|
171
|
+
const producerHookProps = {};
|
|
172
|
+
const consumerHookProps = {};
|
|
173
|
+
for (const sig of edge.signals) {
|
|
174
|
+
const camel = toCamelCase(sig);
|
|
175
|
+
const stateName = `page${capitalize(camel)}`;
|
|
176
|
+
const setterName = `set${capitalize(stateName)}`;
|
|
177
|
+
producerProps[`on${capitalize(camel)}`] = setterName;
|
|
178
|
+
consumerProps[sig] = stateName;
|
|
179
|
+
producerHookProps[sig] = sig;
|
|
180
|
+
consumerHookProps[sig] = sig;
|
|
181
|
+
}
|
|
182
|
+
const rule = {
|
|
183
|
+
pair: [edge.producer, edge.consumer],
|
|
184
|
+
signals,
|
|
185
|
+
props: { [edge.producer]: producerProps, [edge.consumer]: consumerProps },
|
|
186
|
+
hookProps: { [edge.producer]: producerHookProps, [edge.consumer]: consumerHookProps }
|
|
187
|
+
};
|
|
188
|
+
results.push({ rule, signals, props: rule.props, hookProps: rule.hookProps });
|
|
120
189
|
}
|
|
121
190
|
}
|
|
122
191
|
return results;
|
|
123
192
|
}
|
|
193
|
+
function toCamelCase(str) {
|
|
194
|
+
return str.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
195
|
+
}
|
|
196
|
+
function capitalize(str) {
|
|
197
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
198
|
+
}
|
|
199
|
+
function classifySignal(signal) {
|
|
200
|
+
const normalized = toCamelCase(signal);
|
|
201
|
+
if (normalized === "search") return "search";
|
|
202
|
+
if (normalized === "selection") return "selection";
|
|
203
|
+
if (normalized === "sort") return "sort";
|
|
204
|
+
return "filter";
|
|
205
|
+
}
|
|
124
206
|
|
|
125
|
-
// src/client.ts
|
|
207
|
+
// src/api-client.ts
|
|
208
|
+
var DEFAULT_BASE_URL = "https://api.decantr.ai/v1";
|
|
209
|
+
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
210
|
+
var DEFAULT_CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
211
|
+
var RegistryAPIClient = class {
|
|
212
|
+
baseUrl;
|
|
213
|
+
apiKey;
|
|
214
|
+
timeoutMs;
|
|
215
|
+
cacheTtlMs;
|
|
216
|
+
cache = /* @__PURE__ */ new Map();
|
|
217
|
+
constructor(options = {}) {
|
|
218
|
+
this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
|
|
219
|
+
this.apiKey = options.apiKey;
|
|
220
|
+
this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
221
|
+
this.cacheTtlMs = options.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS;
|
|
222
|
+
}
|
|
223
|
+
// ── HTTP helpers ──
|
|
224
|
+
buildHeaders() {
|
|
225
|
+
const headers = {
|
|
226
|
+
"Accept": "application/json"
|
|
227
|
+
};
|
|
228
|
+
if (this.apiKey) {
|
|
229
|
+
headers["X-API-Key"] = this.apiKey;
|
|
230
|
+
}
|
|
231
|
+
return headers;
|
|
232
|
+
}
|
|
233
|
+
async fetchWithTimeout(url, init) {
|
|
234
|
+
const controller = new AbortController();
|
|
235
|
+
const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
236
|
+
try {
|
|
237
|
+
return await fetch(url, { ...init, signal: controller.signal });
|
|
238
|
+
} finally {
|
|
239
|
+
clearTimeout(timeout);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
async request(path, init) {
|
|
243
|
+
const url = `${this.baseUrl}${path}`;
|
|
244
|
+
const response = await this.fetchWithTimeout(url, {
|
|
245
|
+
...init,
|
|
246
|
+
headers: { ...this.buildHeaders(), ...init?.headers }
|
|
247
|
+
});
|
|
248
|
+
if (!response.ok) {
|
|
249
|
+
const body = await response.text().catch(() => "");
|
|
250
|
+
throw new Error(`API ${response.status}: ${body || response.statusText}`);
|
|
251
|
+
}
|
|
252
|
+
return response.json();
|
|
253
|
+
}
|
|
254
|
+
// ── Cache helpers ──
|
|
255
|
+
getCached(key) {
|
|
256
|
+
const entry = this.cache.get(key);
|
|
257
|
+
if (!entry) return null;
|
|
258
|
+
if (Date.now() - entry.timestamp > this.cacheTtlMs) {
|
|
259
|
+
this.cache.delete(key);
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
return entry.data;
|
|
263
|
+
}
|
|
264
|
+
setCache(key, data) {
|
|
265
|
+
this.cache.set(key, { data, timestamp: Date.now() });
|
|
266
|
+
}
|
|
267
|
+
clearCache() {
|
|
268
|
+
this.cache.clear();
|
|
269
|
+
}
|
|
270
|
+
// ── Health ──
|
|
271
|
+
async checkHealth() {
|
|
272
|
+
try {
|
|
273
|
+
const url = this.baseUrl.replace(/\/v1$/, "/health");
|
|
274
|
+
const response = await this.fetchWithTimeout(url);
|
|
275
|
+
return response.ok;
|
|
276
|
+
} catch {
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
// ── Content fetching (public) ──
|
|
281
|
+
async listContent(type, params) {
|
|
282
|
+
const cacheKey = `list:${type}:${JSON.stringify(params ?? {})}`;
|
|
283
|
+
const cached = this.getCached(cacheKey);
|
|
284
|
+
if (cached) return cached;
|
|
285
|
+
const searchParams = new URLSearchParams();
|
|
286
|
+
if (params?.namespace) searchParams.set("namespace", params.namespace);
|
|
287
|
+
if (params?.limit) searchParams.set("limit", String(params.limit));
|
|
288
|
+
if (params?.offset) searchParams.set("offset", String(params.offset));
|
|
289
|
+
const query = searchParams.toString();
|
|
290
|
+
const path = `/${type}${query ? `?${query}` : ""}`;
|
|
291
|
+
const result = await this.request(path);
|
|
292
|
+
this.setCache(cacheKey, result);
|
|
293
|
+
return result;
|
|
294
|
+
}
|
|
295
|
+
async getContent(type, namespace, slug) {
|
|
296
|
+
const cacheKey = `get:${type}:${namespace}:${slug}`;
|
|
297
|
+
const cached = this.getCached(cacheKey);
|
|
298
|
+
if (cached) return cached;
|
|
299
|
+
const result = await this.request(`/${type}/${namespace}/${slug}`);
|
|
300
|
+
this.setCache(cacheKey, result);
|
|
301
|
+
return result;
|
|
302
|
+
}
|
|
303
|
+
// ── Typed convenience methods ──
|
|
304
|
+
async getPattern(namespace, slug) {
|
|
305
|
+
return this.getContent("patterns", namespace, slug);
|
|
306
|
+
}
|
|
307
|
+
async getArchetype(namespace, slug) {
|
|
308
|
+
return this.getContent("archetypes", namespace, slug);
|
|
309
|
+
}
|
|
310
|
+
async getTheme(namespace, slug) {
|
|
311
|
+
return this.getContent("themes", namespace, slug);
|
|
312
|
+
}
|
|
313
|
+
async getBlueprint(namespace, slug) {
|
|
314
|
+
return this.getContent("blueprints", namespace, slug);
|
|
315
|
+
}
|
|
316
|
+
async getShell(namespace, slug) {
|
|
317
|
+
return this.getContent("shells", namespace, slug);
|
|
318
|
+
}
|
|
319
|
+
// ── Search ──
|
|
320
|
+
async search(params) {
|
|
321
|
+
const searchParams = new URLSearchParams({ q: params.q });
|
|
322
|
+
if (params.type) searchParams.set("type", params.type);
|
|
323
|
+
if (params.namespace) searchParams.set("namespace", params.namespace);
|
|
324
|
+
if (params.limit) searchParams.set("limit", String(params.limit));
|
|
325
|
+
if (params.offset) searchParams.set("offset", String(params.offset));
|
|
326
|
+
return this.request(`/search?${searchParams}`);
|
|
327
|
+
}
|
|
328
|
+
// ── Authenticated endpoints ──
|
|
329
|
+
async getProfile() {
|
|
330
|
+
return this.request("/me");
|
|
331
|
+
}
|
|
332
|
+
async publishContent(payload) {
|
|
333
|
+
return this.request("/content", {
|
|
334
|
+
method: "POST",
|
|
335
|
+
headers: { "Content-Type": "application/json" },
|
|
336
|
+
body: JSON.stringify(payload)
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
async getMyContent() {
|
|
340
|
+
return this.request("/my/content");
|
|
341
|
+
}
|
|
342
|
+
// ── Schema ──
|
|
343
|
+
async getSchema(name = "essence.v3.json") {
|
|
344
|
+
return this.request(`/schema/${name}`);
|
|
345
|
+
}
|
|
346
|
+
};
|
|
126
347
|
function createRegistryClient(options = {}) {
|
|
127
|
-
const baseUrl = options.baseUrl ?? "https://decantr
|
|
348
|
+
const baseUrl = options.baseUrl ?? "https://api.decantr.ai/v1";
|
|
128
349
|
return {
|
|
129
350
|
async search(query, type) {
|
|
130
351
|
const params = new URLSearchParams({ q: query });
|
|
131
352
|
if (type) params.set("type", type);
|
|
132
353
|
const res = await fetch(`${baseUrl}/search?${params}`);
|
|
133
354
|
if (!res.ok) return [];
|
|
134
|
-
|
|
355
|
+
const data = await res.json();
|
|
356
|
+
if (Array.isArray(data)) return data;
|
|
357
|
+
return data.results ?? [];
|
|
135
358
|
},
|
|
136
359
|
async fetch(type, id, version) {
|
|
137
360
|
const url = version ? `${baseUrl}/content/${type}/${id}/${version}` : `${baseUrl}/content/${type}/${id}`;
|
|
@@ -142,9 +365,12 @@ function createRegistryClient(options = {}) {
|
|
|
142
365
|
};
|
|
143
366
|
}
|
|
144
367
|
export {
|
|
368
|
+
RegistryAPIClient,
|
|
145
369
|
WIRING_RULES,
|
|
370
|
+
buildIOMap,
|
|
146
371
|
createRegistryClient,
|
|
147
372
|
createResolver,
|
|
373
|
+
deriveIOWirings,
|
|
148
374
|
detectWirings,
|
|
149
375
|
resolvePatternPreset
|
|
150
376
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/resolver.ts","../src/pattern.ts","../src/wiring.ts","../src/client.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { Pattern, Archetype, Recipe, ContentType, ResolvedContent } from './types.js';\n\ntype ContentMap = {\n pattern: Pattern;\n archetype: Archetype;\n recipe: Recipe;\n theme: Record<string, unknown>;\n blueprint: Record<string, unknown>;\n};\n\nexport interface ResolverOptions {\n contentRoot: string;\n overridePaths?: string[];\n}\n\nexport interface ContentResolver {\n resolve<T extends ContentType>(type: T, id: string): Promise<ResolvedContent<ContentMap[T]> | null>;\n}\n\nconst TYPE_DIRS: Record<ContentType, string> = {\n pattern: 'patterns',\n archetype: 'archetypes',\n recipe: 'recipes',\n theme: 'themes',\n blueprint: 'blueprints',\n};\n\nasync function tryLoadJson<T>(filePath: string): Promise<T | null> {\n try {\n const content = await readFile(filePath, 'utf-8');\n return JSON.parse(content) as T;\n } catch {\n return null;\n }\n}\n\nexport function createResolver(options: ResolverOptions): ContentResolver {\n const { contentRoot, overridePaths = [] } = options;\n return {\n async resolve<T extends ContentType>(type: T, id: string): Promise<ResolvedContent<ContentMap[T]> | null> {\n const dir = TYPE_DIRS[type];\n const fileName = `${id}.json`;\n for (const overridePath of overridePaths) {\n const filePath = join(overridePath, dir, fileName);\n const item = await tryLoadJson<ContentMap[T]>(filePath);\n if (item) return { item, source: 'local', path: filePath };\n }\n const corePath = join(contentRoot, dir, fileName);\n const coreItem = await tryLoadJson<ContentMap[T]>(corePath);\n if (coreItem) return { item: coreItem, source: 'core', path: corePath };\n return null;\n },\n };\n}\n","import type { Pattern, PatternPreset } from './types.js';\n\nexport interface ResolvedPreset {\n preset: string;\n layout: PatternPreset['layout'];\n code: PatternPreset['code'];\n}\n\nexport function resolvePatternPreset(\n pattern: Pattern,\n explicitPreset?: string,\n recipeDefaultPresets?: Record<string, string>,\n): ResolvedPreset {\n const presets = pattern.presets;\n const hasPresets = Object.keys(presets).length > 0;\n\n if (!hasPresets) {\n return {\n preset: '',\n layout: { layout: 'row', atoms: '' },\n code: pattern.code ?? { imports: '', example: '' },\n };\n }\n\n let presetName = explicitPreset;\n if (presetName && !presets[presetName]) presetName = undefined;\n if (!presetName && recipeDefaultPresets?.[pattern.id]) {\n const recipeName = recipeDefaultPresets[pattern.id];\n if (presets[recipeName]) presetName = recipeName;\n }\n if (!presetName) presetName = pattern.default_preset;\n if (!presetName || !presets[presetName]) presetName = Object.keys(presets)[0];\n\n const preset = presets[presetName];\n return { preset: presetName, layout: preset.layout, code: preset.code };\n}\n","import type { LayoutItem, PatternRef } from '@decantr/essence-spec';\n\n// AUTO: hookType classifies each signal for custom hook generation\nexport type HookType = 'search' | 'filter' | 'selection' | 'sort';\n\nexport interface WiringSignal { name: string; init: string; hookType: HookType }\n\nexport interface WiringRule {\n pair: [string, string];\n signals: WiringSignal[];\n props: Record<string, Record<string, string>>;\n // AUTO: hookProps maps pattern IDs to hook variable names passed as props\n hookProps: Record<string, Record<string, string>>;\n}\n\nexport interface WiringResult {\n rule: WiringRule;\n signals: WiringSignal[];\n props: Record<string, Record<string, string>>;\n hookProps: Record<string, Record<string, string>>;\n}\n\nexport const WIRING_RULES: WiringRule[] = [\n {\n pair: ['filter-bar', 'data-table'],\n signals: [\n { name: 'pageSearch', init: \"''\", hookType: 'search' },\n { name: 'pageStatus', init: \"'all'\", hookType: 'filter' },\n ],\n props: {\n 'filter-bar': { onSearch: 'setPageSearch', onCategory: 'setPageStatus' },\n 'data-table': { search: 'pageSearch', status: 'pageStatus' },\n },\n hookProps: {\n 'filter-bar': { search: 'search', filters: 'filters' },\n 'data-table': { search: 'search', filters: 'filters' },\n },\n },\n {\n pair: ['filter-bar', 'activity-feed'],\n signals: [\n { name: 'pageSearch', init: \"''\", hookType: 'search' },\n { name: 'pageView', init: \"'all'\", hookType: 'filter' },\n ],\n props: {\n 'filter-bar': { onSearch: 'setPageSearch', onView: 'setPageView' },\n 'activity-feed': { search: 'pageSearch', view: 'pageView' },\n },\n hookProps: {\n 'filter-bar': { search: 'search', filters: 'filters' },\n 'activity-feed': { search: 'search', filters: 'filters' },\n },\n },\n {\n pair: ['filter-bar', 'card-grid'],\n signals: [\n { name: 'pageSearch', init: \"''\", hookType: 'search' },\n ],\n props: {\n 'filter-bar': { onSearch: 'setPageSearch' },\n 'card-grid': { search: 'pageSearch' },\n },\n hookProps: {\n 'filter-bar': { search: 'search' },\n 'card-grid': { search: 'search' },\n },\n },\n];\n\nfunction getPatternId(item: LayoutItem): string | null {\n if (typeof item === 'string') return item;\n if ('pattern' in item) return (item as PatternRef).pattern;\n return null;\n}\n\nexport function detectWirings(layout: LayoutItem[]): WiringResult[] {\n const patternIds = layout.map(getPatternId).filter((id): id is string => id !== null);\n const results: WiringResult[] = [];\n for (const rule of WIRING_RULES) {\n const [a, b] = rule.pair;\n if (patternIds.includes(a) && patternIds.includes(b)) {\n results.push({ rule, signals: rule.signals, props: rule.props, hookProps: rule.hookProps });\n }\n }\n return results;\n}\n","export interface RegistryClientOptions {\n baseUrl?: string;\n cacheDir?: string;\n cacheTtl?: number;\n}\n\nexport interface SearchResult {\n id: string;\n type: string;\n name: string;\n description: string;\n version: string;\n tags: string[];\n}\n\nexport interface RegistryClient {\n search(query: string, type?: string): Promise<SearchResult[]>;\n fetch(type: string, id: string, version?: string): Promise<unknown>;\n}\n\nexport function createRegistryClient(options: RegistryClientOptions = {}): RegistryClient {\n const baseUrl = options.baseUrl ?? 'https://decantr-registry.fly.dev/v1';\n return {\n async search(query: string, type?: string): Promise<SearchResult[]> {\n const params = new URLSearchParams({ q: query });\n if (type) params.set('type', type);\n const res = await fetch(`${baseUrl}/search?${params}`);\n if (!res.ok) return [];\n return res.json() as Promise<SearchResult[]>;\n },\n async fetch(type: string, id: string, version?: string): Promise<unknown> {\n const url = version ? `${baseUrl}/content/${type}/${id}/${version}` : `${baseUrl}/content/${type}/${id}`;\n const res = await fetch(url);\n if (!res.ok) return null;\n return res.json();\n },\n };\n}\n"],"mappings":";AAAA,SAAS,gBAAgB;AACzB,SAAS,YAAY;AAoBrB,IAAM,YAAyC;AAAA,EAC7C,SAAS;AAAA,EACT,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,WAAW;AACb;AAEA,eAAe,YAAe,UAAqC;AACjE,MAAI;AACF,UAAM,UAAU,MAAM,SAAS,UAAU,OAAO;AAChD,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,eAAe,SAA2C;AACxE,QAAM,EAAE,aAAa,gBAAgB,CAAC,EAAE,IAAI;AAC5C,SAAO;AAAA,IACL,MAAM,QAA+B,MAAS,IAA4D;AACxG,YAAM,MAAM,UAAU,IAAI;AAC1B,YAAM,WAAW,GAAG,EAAE;AACtB,iBAAW,gBAAgB,eAAe;AACxC,cAAM,WAAW,KAAK,cAAc,KAAK,QAAQ;AACjD,cAAM,OAAO,MAAM,YAA2B,QAAQ;AACtD,YAAI,KAAM,QAAO,EAAE,MAAM,QAAQ,SAAS,MAAM,SAAS;AAAA,MAC3D;AACA,YAAM,WAAW,KAAK,aAAa,KAAK,QAAQ;AAChD,YAAM,WAAW,MAAM,YAA2B,QAAQ;AAC1D,UAAI,SAAU,QAAO,EAAE,MAAM,UAAU,QAAQ,QAAQ,MAAM,SAAS;AACtE,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AC/CO,SAAS,qBACd,SACA,gBACA,sBACgB;AAChB,QAAM,UAAU,QAAQ;AACxB,QAAM,aAAa,OAAO,KAAK,OAAO,EAAE,SAAS;AAEjD,MAAI,CAAC,YAAY;AACf,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,QAAQ,EAAE,QAAQ,OAAO,OAAO,GAAG;AAAA,MACnC,MAAM,QAAQ,QAAQ,EAAE,SAAS,IAAI,SAAS,GAAG;AAAA,IACnD;AAAA,EACF;AAEA,MAAI,aAAa;AACjB,MAAI,cAAc,CAAC,QAAQ,UAAU,EAAG,cAAa;AACrD,MAAI,CAAC,cAAc,uBAAuB,QAAQ,EAAE,GAAG;AACrD,UAAM,aAAa,qBAAqB,QAAQ,EAAE;AAClD,QAAI,QAAQ,UAAU,EAAG,cAAa;AAAA,EACxC;AACA,MAAI,CAAC,WAAY,cAAa,QAAQ;AACtC,MAAI,CAAC,cAAc,CAAC,QAAQ,UAAU,EAAG,cAAa,OAAO,KAAK,OAAO,EAAE,CAAC;AAE5E,QAAM,SAAS,QAAQ,UAAU;AACjC,SAAO,EAAE,QAAQ,YAAY,QAAQ,OAAO,QAAQ,MAAM,OAAO,KAAK;AACxE;;;ACbO,IAAM,eAA6B;AAAA,EACxC;AAAA,IACE,MAAM,CAAC,cAAc,YAAY;AAAA,IACjC,SAAS;AAAA,MACP,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,SAAS;AAAA,MACrD,EAAE,MAAM,cAAc,MAAM,SAAS,UAAU,SAAS;AAAA,IAC1D;AAAA,IACA,OAAO;AAAA,MACL,cAAc,EAAE,UAAU,iBAAiB,YAAY,gBAAgB;AAAA,MACvE,cAAc,EAAE,QAAQ,cAAc,QAAQ,aAAa;AAAA,IAC7D;AAAA,IACA,WAAW;AAAA,MACT,cAAc,EAAE,QAAQ,UAAU,SAAS,UAAU;AAAA,MACrD,cAAc,EAAE,QAAQ,UAAU,SAAS,UAAU;AAAA,IACvD;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM,CAAC,cAAc,eAAe;AAAA,IACpC,SAAS;AAAA,MACP,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,SAAS;AAAA,MACrD,EAAE,MAAM,YAAY,MAAM,SAAS,UAAU,SAAS;AAAA,IACxD;AAAA,IACA,OAAO;AAAA,MACL,cAAc,EAAE,UAAU,iBAAiB,QAAQ,cAAc;AAAA,MACjE,iBAAiB,EAAE,QAAQ,cAAc,MAAM,WAAW;AAAA,IAC5D;AAAA,IACA,WAAW;AAAA,MACT,cAAc,EAAE,QAAQ,UAAU,SAAS,UAAU;AAAA,MACrD,iBAAiB,EAAE,QAAQ,UAAU,SAAS,UAAU;AAAA,IAC1D;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM,CAAC,cAAc,WAAW;AAAA,IAChC,SAAS;AAAA,MACP,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,SAAS;AAAA,IACvD;AAAA,IACA,OAAO;AAAA,MACL,cAAc,EAAE,UAAU,gBAAgB;AAAA,MAC1C,aAAa,EAAE,QAAQ,aAAa;AAAA,IACtC;AAAA,IACA,WAAW;AAAA,MACT,cAAc,EAAE,QAAQ,SAAS;AAAA,MACjC,aAAa,EAAE,QAAQ,SAAS;AAAA,IAClC;AAAA,EACF;AACF;AAEA,SAAS,aAAa,MAAiC;AACrD,MAAI,OAAO,SAAS,SAAU,QAAO;AACrC,MAAI,aAAa,KAAM,QAAQ,KAAoB;AACnD,SAAO;AACT;AAEO,SAAS,cAAc,QAAsC;AAClE,QAAM,aAAa,OAAO,IAAI,YAAY,EAAE,OAAO,CAAC,OAAqB,OAAO,IAAI;AACpF,QAAM,UAA0B,CAAC;AACjC,aAAW,QAAQ,cAAc;AAC/B,UAAM,CAAC,GAAG,CAAC,IAAI,KAAK;AACpB,QAAI,WAAW,SAAS,CAAC,KAAK,WAAW,SAAS,CAAC,GAAG;AACpD,cAAQ,KAAK,EAAE,MAAM,SAAS,KAAK,SAAS,OAAO,KAAK,OAAO,WAAW,KAAK,UAAU,CAAC;AAAA,IAC5F;AAAA,EACF;AACA,SAAO;AACT;;;ACjEO,SAAS,qBAAqB,UAAiC,CAAC,GAAmB;AACxF,QAAM,UAAU,QAAQ,WAAW;AACnC,SAAO;AAAA,IACL,MAAM,OAAO,OAAe,MAAwC;AAClE,YAAM,SAAS,IAAI,gBAAgB,EAAE,GAAG,MAAM,CAAC;AAC/C,UAAI,KAAM,QAAO,IAAI,QAAQ,IAAI;AACjC,YAAM,MAAM,MAAM,MAAM,GAAG,OAAO,WAAW,MAAM,EAAE;AACrD,UAAI,CAAC,IAAI,GAAI,QAAO,CAAC;AACrB,aAAO,IAAI,KAAK;AAAA,IAClB;AAAA,IACA,MAAM,MAAM,MAAc,IAAY,SAAoC;AACxE,YAAM,MAAM,UAAU,GAAG,OAAO,YAAY,IAAI,IAAI,EAAE,IAAI,OAAO,KAAK,GAAG,OAAO,YAAY,IAAI,IAAI,EAAE;AACtG,YAAM,MAAM,MAAM,MAAM,GAAG;AAC3B,UAAI,CAAC,IAAI,GAAI,QAAO;AACpB,aAAO,IAAI,KAAK;AAAA,IAClB;AAAA,EACF;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/resolver.ts","../src/pattern.ts","../src/wiring.ts","../src/api-client.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { Pattern, Archetype, Theme, Blueprint, ContentType, ResolvedContent } from './types.js';\n\ntype ContentMap = {\n pattern: Pattern;\n archetype: Archetype;\n theme: Theme;\n blueprint: Blueprint;\n};\n\nexport interface ResolverOptions {\n contentRoot: string;\n overridePaths?: string[];\n}\n\nexport interface ContentResolver {\n resolve<T extends ContentType>(type: T, id: string): Promise<ResolvedContent<ContentMap[T]> | null>;\n}\n\nconst TYPE_DIRS: Record<ContentType, string> = {\n pattern: 'patterns',\n archetype: 'archetypes',\n theme: 'themes',\n blueprint: 'blueprints',\n};\n\nasync function tryLoadJson<T>(filePath: string): Promise<T | null> {\n try {\n const content = await readFile(filePath, 'utf-8');\n return JSON.parse(content) as T;\n } catch {\n return null;\n }\n}\n\nexport function createResolver(options: ResolverOptions): ContentResolver {\n const { contentRoot, overridePaths = [] } = options;\n return {\n async resolve<T extends ContentType>(type: T, id: string): Promise<ResolvedContent<ContentMap[T]> | null> {\n const dir = TYPE_DIRS[type];\n const fileName = `${id}.json`;\n for (const overridePath of overridePaths) {\n const filePath = join(overridePath, dir, fileName);\n const item = await tryLoadJson<ContentMap[T]>(filePath);\n if (item) return { item, source: 'local', path: filePath };\n }\n // Check main content directory\n const mainPath = join(contentRoot, dir, fileName);\n const mainItem = await tryLoadJson<ContentMap[T]>(mainPath);\n if (mainItem) return { item: mainItem, source: 'core', path: mainPath };\n\n // Check content/core/{type}/ as fallback\n const corePath = join(contentRoot, 'core', dir, fileName);\n const coreItem = await tryLoadJson<ContentMap[T]>(corePath);\n if (coreItem) return { item: coreItem, source: 'core', path: corePath };\n\n return null;\n },\n };\n}\n","import type { Pattern, PatternPreset } from './types.js';\n\nexport interface ResolvedPreset {\n preset: string;\n layout: PatternPreset['layout'];\n code: PatternPreset['code'];\n}\n\nexport function resolvePatternPreset(\n pattern: Pattern,\n explicitPreset?: string,\n themeDefaultPresets?: Record<string, string>,\n): ResolvedPreset {\n const presets = pattern.presets;\n const hasPresets = Object.keys(presets).length > 0;\n\n if (!hasPresets) {\n return {\n preset: '',\n layout: { layout: 'row', atoms: '' },\n code: pattern.code ?? { imports: '', example: '' },\n };\n }\n\n let presetName = explicitPreset;\n if (presetName && !presets[presetName]) presetName = undefined;\n if (!presetName && themeDefaultPresets?.[pattern.id]) {\n const themeName = themeDefaultPresets[pattern.id];\n if (presets[themeName]) presetName = themeName;\n }\n if (!presetName) presetName = pattern.default_preset;\n if (!presetName || !presets[presetName]) presetName = Object.keys(presets)[0];\n\n const preset = presets[presetName];\n return { preset: presetName, layout: preset.layout, code: preset.code };\n}\n","import type { LayoutItem, PatternRef } from '@decantr/essence-spec';\nimport type { PatternIO } from './types.js';\n\n// AUTO: hookType classifies each signal for custom hook generation\nexport type HookType = 'search' | 'filter' | 'selection' | 'sort';\n\nexport interface WiringSignal { name: string; init: string; hookType: HookType }\n\nexport interface WiringRule {\n pair: [string, string];\n signals: WiringSignal[];\n props: Record<string, Record<string, string>>;\n // AUTO: hookProps maps pattern IDs to hook variable names passed as props\n hookProps: Record<string, Record<string, string>>;\n}\n\nexport interface WiringResult {\n rule: WiringRule;\n signals: WiringSignal[];\n props: Record<string, Record<string, string>>;\n hookProps: Record<string, Record<string, string>>;\n}\n\n/**\n * IO declaration for a pattern, used by the data-driven wiring system.\n */\nexport interface PatternIOEntry {\n id: string;\n io: PatternIO;\n}\n\n/**\n * A dynamically derived wiring edge between two patterns based on shared IO signals.\n */\nexport interface IOWiringEdge {\n producer: string;\n consumer: string;\n signals: string[];\n}\n\nexport const WIRING_RULES: WiringRule[] = [\n {\n pair: ['filter-bar', 'data-table'],\n signals: [\n { name: 'pageSearch', init: \"''\", hookType: 'search' },\n { name: 'pageStatus', init: \"'all'\", hookType: 'filter' },\n ],\n props: {\n 'filter-bar': { onSearch: 'setPageSearch', onCategory: 'setPageStatus' },\n 'data-table': { search: 'pageSearch', status: 'pageStatus' },\n },\n hookProps: {\n 'filter-bar': { search: 'search', filters: 'filters' },\n 'data-table': { search: 'search', filters: 'filters' },\n },\n },\n {\n pair: ['filter-bar', 'activity-feed'],\n signals: [\n { name: 'pageSearch', init: \"''\", hookType: 'search' },\n { name: 'pageView', init: \"'all'\", hookType: 'filter' },\n ],\n props: {\n 'filter-bar': { onSearch: 'setPageSearch', onView: 'setPageView' },\n 'activity-feed': { search: 'pageSearch', view: 'pageView' },\n },\n hookProps: {\n 'filter-bar': { search: 'search', filters: 'filters' },\n 'activity-feed': { search: 'search', filters: 'filters' },\n },\n },\n {\n pair: ['filter-bar', 'card-grid'],\n signals: [\n { name: 'pageSearch', init: \"''\", hookType: 'search' },\n ],\n props: {\n 'filter-bar': { onSearch: 'setPageSearch' },\n 'card-grid': { search: 'pageSearch' },\n },\n hookProps: {\n 'filter-bar': { search: 'search' },\n 'card-grid': { search: 'search' },\n },\n },\n];\n\nfunction getPatternId(item: LayoutItem): string | null {\n if (typeof item === 'string') return item;\n if ('pattern' in item) return (item as PatternRef).pattern;\n return null;\n}\n\n/**\n * Derive wiring edges from pattern IO declarations.\n * If pattern A produces signal X and pattern B consumes signal X, an edge is created.\n * Only patterns present in the layout are considered.\n */\nexport function deriveIOWirings(\n layoutIds: string[],\n patternIOMap: Map<string, PatternIO>,\n): IOWiringEdge[] {\n const edges: IOWiringEdge[] = [];\n const layoutSet = new Set(layoutIds);\n\n for (const producerId of layoutIds) {\n const producerIO = patternIOMap.get(producerId);\n if (!producerIO?.produces?.length) continue;\n\n for (const consumerId of layoutIds) {\n if (producerId === consumerId) continue;\n if (!layoutSet.has(consumerId)) continue;\n const consumerIO = patternIOMap.get(consumerId);\n if (!consumerIO?.consumes?.length) continue;\n\n const shared = producerIO.produces.filter(\n (signal) => consumerIO.consumes!.includes(signal),\n );\n if (shared.length > 0) {\n edges.push({ producer: producerId, consumer: consumerId, signals: shared });\n }\n }\n }\n\n return edges;\n}\n\n/**\n * Build a PatternIO map from an array of PatternIOEntry objects.\n */\nexport function buildIOMap(entries: PatternIOEntry[]): Map<string, PatternIO> {\n const map = new Map<string, PatternIO>();\n for (const entry of entries) {\n map.set(entry.id, entry.io);\n }\n return map;\n}\n\n/**\n * Detect wirings from a layout. Uses hardcoded WIRING_RULES for detailed\n * signal/prop information. When a patternIOMap is provided, also derives\n * IO-based wirings and merges them (hardcoded rules take precedence for\n * pairs they cover).\n */\nexport function detectWirings(\n layout: LayoutItem[],\n patternIOMap?: Map<string, PatternIO>,\n): WiringResult[] {\n const patternIds = layout.map(getPatternId).filter((id): id is string => id !== null);\n const results: WiringResult[] = [];\n const coveredPairs = new Set<string>();\n\n // Apply hardcoded rules first (these have detailed signal/prop info)\n for (const rule of WIRING_RULES) {\n const [a, b] = rule.pair;\n if (patternIds.includes(a) && patternIds.includes(b)) {\n results.push({ rule, signals: rule.signals, props: rule.props, hookProps: rule.hookProps });\n coveredPairs.add(`${a}:${b}`);\n coveredPairs.add(`${b}:${a}`);\n }\n }\n\n // If IO map provided, derive additional wirings from IO declarations\n if (patternIOMap) {\n const ioEdges = deriveIOWirings(patternIds, patternIOMap);\n for (const edge of ioEdges) {\n const pairKey = `${edge.producer}:${edge.consumer}`;\n if (coveredPairs.has(pairKey)) continue;\n coveredPairs.add(pairKey);\n\n // Generate a synthetic WiringRule from IO signals\n const signals: WiringSignal[] = edge.signals.map((sig) => {\n const camel = toCamelCase(sig);\n return {\n name: `page${capitalize(camel)}`,\n init: \"''\",\n hookType: classifySignal(sig),\n };\n });\n\n const producerProps: Record<string, string> = {};\n const consumerProps: Record<string, string> = {};\n const producerHookProps: Record<string, string> = {};\n const consumerHookProps: Record<string, string> = {};\n\n for (const sig of edge.signals) {\n const camel = toCamelCase(sig);\n const stateName = `page${capitalize(camel)}`;\n const setterName = `set${capitalize(stateName)}`;\n producerProps[`on${capitalize(camel)}`] = setterName;\n consumerProps[sig] = stateName;\n producerHookProps[sig] = sig;\n consumerHookProps[sig] = sig;\n }\n\n const rule: WiringRule = {\n pair: [edge.producer, edge.consumer],\n signals,\n props: { [edge.producer]: producerProps, [edge.consumer]: consumerProps },\n hookProps: { [edge.producer]: producerHookProps, [edge.consumer]: consumerHookProps },\n };\n\n results.push({ rule, signals, props: rule.props, hookProps: rule.hookProps });\n }\n }\n\n return results;\n}\n\n/**\n * Convert a kebab-case string to camelCase.\n */\nfunction toCamelCase(str: string): string {\n return str.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase());\n}\n\n/**\n * Capitalize the first letter of a string.\n */\nfunction capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\n/**\n * Classify a signal name into a HookType for code generation.\n */\nfunction classifySignal(signal: string): HookType {\n const normalized = toCamelCase(signal);\n if (normalized === 'search') return 'search';\n if (normalized === 'selection') return 'selection';\n if (normalized === 'sort') return 'sort';\n return 'filter';\n}\n","import type {\n Pattern,\n Archetype,\n Theme,\n Blueprint,\n Shell,\n ApiContentType,\n ContentListResponse,\n ContentItem,\n PublishPayload,\n PublishResponse,\n SearchParams,\n SearchResponse,\n UserProfile,\n} from './types.js';\n\nconst DEFAULT_BASE_URL = 'https://api.decantr.ai/v1';\nconst DEFAULT_TIMEOUT_MS = 30000;\nconst DEFAULT_CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes\n\ninterface CacheEntry<T> {\n data: T;\n timestamp: number;\n}\n\nexport interface RegistryAPIClientOptions {\n baseUrl?: string;\n apiKey?: string;\n timeoutMs?: number;\n cacheTtlMs?: number;\n}\n\nexport class RegistryAPIClient {\n private baseUrl: string;\n private apiKey: string | undefined;\n private timeoutMs: number;\n private cacheTtlMs: number;\n private cache = new Map<string, CacheEntry<unknown>>();\n\n constructor(options: RegistryAPIClientOptions = {}) {\n this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;\n this.apiKey = options.apiKey;\n this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n this.cacheTtlMs = options.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS;\n }\n\n // ── HTTP helpers ──\n\n private buildHeaders(): Record<string, string> {\n const headers: Record<string, string> = {\n 'Accept': 'application/json',\n };\n if (this.apiKey) {\n headers['X-API-Key'] = this.apiKey;\n }\n return headers;\n }\n\n private async fetchWithTimeout(url: string, init?: RequestInit): Promise<Response> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), this.timeoutMs);\n try {\n return await fetch(url, { ...init, signal: controller.signal });\n } finally {\n clearTimeout(timeout);\n }\n }\n\n private async request<T>(path: string, init?: RequestInit): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const response = await this.fetchWithTimeout(url, {\n ...init,\n headers: { ...this.buildHeaders(), ...init?.headers },\n });\n if (!response.ok) {\n const body = await response.text().catch(() => '');\n throw new Error(`API ${response.status}: ${body || response.statusText}`);\n }\n return response.json() as Promise<T>;\n }\n\n // ── Cache helpers ──\n\n private getCached<T>(key: string): T | null {\n const entry = this.cache.get(key) as CacheEntry<T> | undefined;\n if (!entry) return null;\n if (Date.now() - entry.timestamp > this.cacheTtlMs) {\n this.cache.delete(key);\n return null;\n }\n return entry.data;\n }\n\n private setCache<T>(key: string, data: T): void {\n this.cache.set(key, { data, timestamp: Date.now() });\n }\n\n clearCache(): void {\n this.cache.clear();\n }\n\n // ── Health ──\n\n async checkHealth(): Promise<boolean> {\n try {\n const url = this.baseUrl.replace(/\\/v1$/, '/health');\n const response = await this.fetchWithTimeout(url);\n return response.ok;\n } catch {\n return false;\n }\n }\n\n // ── Content fetching (public) ──\n\n async listContent<T = Record<string, unknown>>(\n type: ApiContentType,\n params?: { namespace?: string; limit?: number; offset?: number }\n ): Promise<ContentListResponse<T>> {\n const cacheKey = `list:${type}:${JSON.stringify(params ?? {})}`;\n const cached = this.getCached<ContentListResponse<T>>(cacheKey);\n if (cached) return cached;\n\n const searchParams = new URLSearchParams();\n if (params?.namespace) searchParams.set('namespace', params.namespace);\n if (params?.limit) searchParams.set('limit', String(params.limit));\n if (params?.offset) searchParams.set('offset', String(params.offset));\n\n const query = searchParams.toString();\n const path = `/${type}${query ? `?${query}` : ''}`;\n const result = await this.request<ContentListResponse<T>>(path);\n this.setCache(cacheKey, result);\n return result;\n }\n\n async getContent<T = Record<string, unknown>>(\n type: ApiContentType,\n namespace: string,\n slug: string\n ): Promise<T> {\n const cacheKey = `get:${type}:${namespace}:${slug}`;\n const cached = this.getCached<T>(cacheKey);\n if (cached) return cached;\n\n const result = await this.request<T>(`/${type}/${namespace}/${slug}`);\n this.setCache(cacheKey, result);\n return result;\n }\n\n // ── Typed convenience methods ──\n\n async getPattern(namespace: string, slug: string): Promise<Pattern> {\n return this.getContent<Pattern>('patterns', namespace, slug);\n }\n\n async getArchetype(namespace: string, slug: string): Promise<Archetype> {\n return this.getContent<Archetype>('archetypes', namespace, slug);\n }\n\n async getTheme(namespace: string, slug: string): Promise<Theme> {\n return this.getContent<Theme>('themes', namespace, slug);\n }\n\n async getBlueprint(namespace: string, slug: string): Promise<Blueprint> {\n return this.getContent<Blueprint>('blueprints', namespace, slug);\n }\n\n async getShell(namespace: string, slug: string): Promise<Shell> {\n return this.getContent<Shell>('shells', namespace, slug);\n }\n\n // ── Search ──\n\n async search(params: SearchParams): Promise<SearchResponse> {\n const searchParams = new URLSearchParams({ q: params.q });\n if (params.type) searchParams.set('type', params.type);\n if (params.namespace) searchParams.set('namespace', params.namespace);\n if (params.limit) searchParams.set('limit', String(params.limit));\n if (params.offset) searchParams.set('offset', String(params.offset));\n\n return this.request<SearchResponse>(`/search?${searchParams}`);\n }\n\n // ── Authenticated endpoints ──\n\n async getProfile(): Promise<UserProfile> {\n return this.request<UserProfile>('/me');\n }\n\n async publishContent(payload: PublishPayload): Promise<PublishResponse> {\n return this.request<PublishResponse>('/content', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n });\n }\n\n async getMyContent(): Promise<ContentListResponse<ContentItem>> {\n return this.request<ContentListResponse<ContentItem>>('/my/content');\n }\n\n // ── Schema ──\n\n async getSchema(name: string = 'essence.v3.json'): Promise<Record<string, unknown>> {\n return this.request<Record<string, unknown>>(`/schema/${name}`);\n }\n}\n\n// ── Lightweight registry client (merged from client.ts) ──\n\nexport interface RegistryClientOptions {\n baseUrl?: string;\n}\n\nexport interface SearchResult {\n id: string;\n type: string;\n name: string;\n description: string;\n version: string;\n tags: string[];\n}\n\nexport interface RegistryClient {\n search(query: string, type?: string): Promise<SearchResult[]>;\n fetch(type: string, id: string, version?: string): Promise<unknown>;\n}\n\nexport function createRegistryClient(options: RegistryClientOptions = {}): RegistryClient {\n const baseUrl = options.baseUrl ?? 'https://api.decantr.ai/v1';\n return {\n async search(query: string, type?: string): Promise<SearchResult[]> {\n const params = new URLSearchParams({ q: query });\n if (type) params.set('type', type);\n const res = await fetch(`${baseUrl}/search?${params}`);\n if (!res.ok) return [];\n const data = await res.json() as { results?: SearchResult[]; total?: number } | SearchResult[];\n // API returns { total, results } wrapper\n if (Array.isArray(data)) return data;\n return (data as { results: SearchResult[] }).results ?? [];\n },\n async fetch(type: string, id: string, version?: string): Promise<unknown> {\n const url = version ? `${baseUrl}/content/${type}/${id}/${version}` : `${baseUrl}/content/${type}/${id}`;\n const res = await fetch(url);\n if (!res.ok) return null;\n return res.json();\n },\n };\n}\n"],"mappings":";AAAA,SAAS,gBAAgB;AACzB,SAAS,YAAY;AAmBrB,IAAM,YAAyC;AAAA,EAC7C,SAAS;AAAA,EACT,WAAW;AAAA,EACX,OAAO;AAAA,EACP,WAAW;AACb;AAEA,eAAe,YAAe,UAAqC;AACjE,MAAI;AACF,UAAM,UAAU,MAAM,SAAS,UAAU,OAAO;AAChD,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,eAAe,SAA2C;AACxE,QAAM,EAAE,aAAa,gBAAgB,CAAC,EAAE,IAAI;AAC5C,SAAO;AAAA,IACL,MAAM,QAA+B,MAAS,IAA4D;AACxG,YAAM,MAAM,UAAU,IAAI;AAC1B,YAAM,WAAW,GAAG,EAAE;AACtB,iBAAW,gBAAgB,eAAe;AACxC,cAAM,WAAW,KAAK,cAAc,KAAK,QAAQ;AACjD,cAAM,OAAO,MAAM,YAA2B,QAAQ;AACtD,YAAI,KAAM,QAAO,EAAE,MAAM,QAAQ,SAAS,MAAM,SAAS;AAAA,MAC3D;AAEA,YAAM,WAAW,KAAK,aAAa,KAAK,QAAQ;AAChD,YAAM,WAAW,MAAM,YAA2B,QAAQ;AAC1D,UAAI,SAAU,QAAO,EAAE,MAAM,UAAU,QAAQ,QAAQ,MAAM,SAAS;AAGtE,YAAM,WAAW,KAAK,aAAa,QAAQ,KAAK,QAAQ;AACxD,YAAM,WAAW,MAAM,YAA2B,QAAQ;AAC1D,UAAI,SAAU,QAAO,EAAE,MAAM,UAAU,QAAQ,QAAQ,MAAM,SAAS;AAEtE,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;ACpDO,SAAS,qBACd,SACA,gBACA,qBACgB;AAChB,QAAM,UAAU,QAAQ;AACxB,QAAM,aAAa,OAAO,KAAK,OAAO,EAAE,SAAS;AAEjD,MAAI,CAAC,YAAY;AACf,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,QAAQ,EAAE,QAAQ,OAAO,OAAO,GAAG;AAAA,MACnC,MAAM,QAAQ,QAAQ,EAAE,SAAS,IAAI,SAAS,GAAG;AAAA,IACnD;AAAA,EACF;AAEA,MAAI,aAAa;AACjB,MAAI,cAAc,CAAC,QAAQ,UAAU,EAAG,cAAa;AACrD,MAAI,CAAC,cAAc,sBAAsB,QAAQ,EAAE,GAAG;AACpD,UAAM,YAAY,oBAAoB,QAAQ,EAAE;AAChD,QAAI,QAAQ,SAAS,EAAG,cAAa;AAAA,EACvC;AACA,MAAI,CAAC,WAAY,cAAa,QAAQ;AACtC,MAAI,CAAC,cAAc,CAAC,QAAQ,UAAU,EAAG,cAAa,OAAO,KAAK,OAAO,EAAE,CAAC;AAE5E,QAAM,SAAS,QAAQ,UAAU;AACjC,SAAO,EAAE,QAAQ,YAAY,QAAQ,OAAO,QAAQ,MAAM,OAAO,KAAK;AACxE;;;ACKO,IAAM,eAA6B;AAAA,EACxC;AAAA,IACE,MAAM,CAAC,cAAc,YAAY;AAAA,IACjC,SAAS;AAAA,MACP,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,SAAS;AAAA,MACrD,EAAE,MAAM,cAAc,MAAM,SAAS,UAAU,SAAS;AAAA,IAC1D;AAAA,IACA,OAAO;AAAA,MACL,cAAc,EAAE,UAAU,iBAAiB,YAAY,gBAAgB;AAAA,MACvE,cAAc,EAAE,QAAQ,cAAc,QAAQ,aAAa;AAAA,IAC7D;AAAA,IACA,WAAW;AAAA,MACT,cAAc,EAAE,QAAQ,UAAU,SAAS,UAAU;AAAA,MACrD,cAAc,EAAE,QAAQ,UAAU,SAAS,UAAU;AAAA,IACvD;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM,CAAC,cAAc,eAAe;AAAA,IACpC,SAAS;AAAA,MACP,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,SAAS;AAAA,MACrD,EAAE,MAAM,YAAY,MAAM,SAAS,UAAU,SAAS;AAAA,IACxD;AAAA,IACA,OAAO;AAAA,MACL,cAAc,EAAE,UAAU,iBAAiB,QAAQ,cAAc;AAAA,MACjE,iBAAiB,EAAE,QAAQ,cAAc,MAAM,WAAW;AAAA,IAC5D;AAAA,IACA,WAAW;AAAA,MACT,cAAc,EAAE,QAAQ,UAAU,SAAS,UAAU;AAAA,MACrD,iBAAiB,EAAE,QAAQ,UAAU,SAAS,UAAU;AAAA,IAC1D;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM,CAAC,cAAc,WAAW;AAAA,IAChC,SAAS;AAAA,MACP,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,SAAS;AAAA,IACvD;AAAA,IACA,OAAO;AAAA,MACL,cAAc,EAAE,UAAU,gBAAgB;AAAA,MAC1C,aAAa,EAAE,QAAQ,aAAa;AAAA,IACtC;AAAA,IACA,WAAW;AAAA,MACT,cAAc,EAAE,QAAQ,SAAS;AAAA,MACjC,aAAa,EAAE,QAAQ,SAAS;AAAA,IAClC;AAAA,EACF;AACF;AAEA,SAAS,aAAa,MAAiC;AACrD,MAAI,OAAO,SAAS,SAAU,QAAO;AACrC,MAAI,aAAa,KAAM,QAAQ,KAAoB;AACnD,SAAO;AACT;AAOO,SAAS,gBACd,WACA,cACgB;AAChB,QAAM,QAAwB,CAAC;AAC/B,QAAM,YAAY,IAAI,IAAI,SAAS;AAEnC,aAAW,cAAc,WAAW;AAClC,UAAM,aAAa,aAAa,IAAI,UAAU;AAC9C,QAAI,CAAC,YAAY,UAAU,OAAQ;AAEnC,eAAW,cAAc,WAAW;AAClC,UAAI,eAAe,WAAY;AAC/B,UAAI,CAAC,UAAU,IAAI,UAAU,EAAG;AAChC,YAAM,aAAa,aAAa,IAAI,UAAU;AAC9C,UAAI,CAAC,YAAY,UAAU,OAAQ;AAEnC,YAAM,SAAS,WAAW,SAAS;AAAA,QACjC,CAAC,WAAW,WAAW,SAAU,SAAS,MAAM;AAAA,MAClD;AACA,UAAI,OAAO,SAAS,GAAG;AACrB,cAAM,KAAK,EAAE,UAAU,YAAY,UAAU,YAAY,SAAS,OAAO,CAAC;AAAA,MAC5E;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,WAAW,SAAmD;AAC5E,QAAM,MAAM,oBAAI,IAAuB;AACvC,aAAW,SAAS,SAAS;AAC3B,QAAI,IAAI,MAAM,IAAI,MAAM,EAAE;AAAA,EAC5B;AACA,SAAO;AACT;AAQO,SAAS,cACd,QACA,cACgB;AAChB,QAAM,aAAa,OAAO,IAAI,YAAY,EAAE,OAAO,CAAC,OAAqB,OAAO,IAAI;AACpF,QAAM,UAA0B,CAAC;AACjC,QAAM,eAAe,oBAAI,IAAY;AAGrC,aAAW,QAAQ,cAAc;AAC/B,UAAM,CAAC,GAAG,CAAC,IAAI,KAAK;AACpB,QAAI,WAAW,SAAS,CAAC,KAAK,WAAW,SAAS,CAAC,GAAG;AACpD,cAAQ,KAAK,EAAE,MAAM,SAAS,KAAK,SAAS,OAAO,KAAK,OAAO,WAAW,KAAK,UAAU,CAAC;AAC1F,mBAAa,IAAI,GAAG,CAAC,IAAI,CAAC,EAAE;AAC5B,mBAAa,IAAI,GAAG,CAAC,IAAI,CAAC,EAAE;AAAA,IAC9B;AAAA,EACF;AAGA,MAAI,cAAc;AAChB,UAAM,UAAU,gBAAgB,YAAY,YAAY;AACxD,eAAW,QAAQ,SAAS;AAC1B,YAAM,UAAU,GAAG,KAAK,QAAQ,IAAI,KAAK,QAAQ;AACjD,UAAI,aAAa,IAAI,OAAO,EAAG;AAC/B,mBAAa,IAAI,OAAO;AAGxB,YAAM,UAA0B,KAAK,QAAQ,IAAI,CAAC,QAAQ;AACxD,cAAM,QAAQ,YAAY,GAAG;AAC7B,eAAO;AAAA,UACL,MAAM,OAAO,WAAW,KAAK,CAAC;AAAA,UAC9B,MAAM;AAAA,UACN,UAAU,eAAe,GAAG;AAAA,QAC9B;AAAA,MACF,CAAC;AAED,YAAM,gBAAwC,CAAC;AAC/C,YAAM,gBAAwC,CAAC;AAC/C,YAAM,oBAA4C,CAAC;AACnD,YAAM,oBAA4C,CAAC;AAEnD,iBAAW,OAAO,KAAK,SAAS;AAC9B,cAAM,QAAQ,YAAY,GAAG;AAC7B,cAAM,YAAY,OAAO,WAAW,KAAK,CAAC;AAC1C,cAAM,aAAa,MAAM,WAAW,SAAS,CAAC;AAC9C,sBAAc,KAAK,WAAW,KAAK,CAAC,EAAE,IAAI;AAC1C,sBAAc,GAAG,IAAI;AACrB,0BAAkB,GAAG,IAAI;AACzB,0BAAkB,GAAG,IAAI;AAAA,MAC3B;AAEA,YAAM,OAAmB;AAAA,QACvB,MAAM,CAAC,KAAK,UAAU,KAAK,QAAQ;AAAA,QACnC;AAAA,QACA,OAAO,EAAE,CAAC,KAAK,QAAQ,GAAG,eAAe,CAAC,KAAK,QAAQ,GAAG,cAAc;AAAA,QACxE,WAAW,EAAE,CAAC,KAAK,QAAQ,GAAG,mBAAmB,CAAC,KAAK,QAAQ,GAAG,kBAAkB;AAAA,MACtF;AAEA,cAAQ,KAAK,EAAE,MAAM,SAAS,OAAO,KAAK,OAAO,WAAW,KAAK,UAAU,CAAC;AAAA,IAC9E;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,YAAY,KAAqB;AACxC,SAAO,IAAI,QAAQ,aAAa,CAAC,GAAG,MAAc,EAAE,YAAY,CAAC;AACnE;AAKA,SAAS,WAAW,KAAqB;AACvC,SAAO,IAAI,OAAO,CAAC,EAAE,YAAY,IAAI,IAAI,MAAM,CAAC;AAClD;AAKA,SAAS,eAAe,QAA0B;AAChD,QAAM,aAAa,YAAY,MAAM;AACrC,MAAI,eAAe,SAAU,QAAO;AACpC,MAAI,eAAe,YAAa,QAAO;AACvC,MAAI,eAAe,OAAQ,QAAO;AAClC,SAAO;AACT;;;ACxNA,IAAM,mBAAmB;AACzB,IAAM,qBAAqB;AAC3B,IAAM,uBAAuB,IAAI,KAAK;AAc/B,IAAM,oBAAN,MAAwB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ,oBAAI,IAAiC;AAAA,EAErD,YAAY,UAAoC,CAAC,GAAG;AAClD,SAAK,UAAU,QAAQ,WAAW;AAClC,SAAK,SAAS,QAAQ;AACtB,SAAK,YAAY,QAAQ,aAAa;AACtC,SAAK,aAAa,QAAQ,cAAc;AAAA,EAC1C;AAAA;AAAA,EAIQ,eAAuC;AAC7C,UAAM,UAAkC;AAAA,MACtC,UAAU;AAAA,IACZ;AACA,QAAI,KAAK,QAAQ;AACf,cAAQ,WAAW,IAAI,KAAK;AAAA,IAC9B;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,iBAAiB,KAAa,MAAuC;AACjF,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,SAAS;AACnE,QAAI;AACF,aAAO,MAAM,MAAM,KAAK,EAAE,GAAG,MAAM,QAAQ,WAAW,OAAO,CAAC;AAAA,IAChE,UAAE;AACA,mBAAa,OAAO;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,MAAc,QAAW,MAAc,MAAgC;AACrE,UAAM,MAAM,GAAG,KAAK,OAAO,GAAG,IAAI;AAClC,UAAM,WAAW,MAAM,KAAK,iBAAiB,KAAK;AAAA,MAChD,GAAG;AAAA,MACH,SAAS,EAAE,GAAG,KAAK,aAAa,GAAG,GAAG,MAAM,QAAQ;AAAA,IACtD,CAAC;AACD,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,OAAO,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,EAAE;AACjD,YAAM,IAAI,MAAM,OAAO,SAAS,MAAM,KAAK,QAAQ,SAAS,UAAU,EAAE;AAAA,IAC1E;AACA,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA;AAAA,EAIQ,UAAa,KAAuB;AAC1C,UAAM,QAAQ,KAAK,MAAM,IAAI,GAAG;AAChC,QAAI,CAAC,MAAO,QAAO;AACnB,QAAI,KAAK,IAAI,IAAI,MAAM,YAAY,KAAK,YAAY;AAClD,WAAK,MAAM,OAAO,GAAG;AACrB,aAAO;AAAA,IACT;AACA,WAAO,MAAM;AAAA,EACf;AAAA,EAEQ,SAAY,KAAa,MAAe;AAC9C,SAAK,MAAM,IAAI,KAAK,EAAE,MAAM,WAAW,KAAK,IAAI,EAAE,CAAC;AAAA,EACrD;AAAA,EAEA,aAAmB;AACjB,SAAK,MAAM,MAAM;AAAA,EACnB;AAAA;AAAA,EAIA,MAAM,cAAgC;AACpC,QAAI;AACF,YAAM,MAAM,KAAK,QAAQ,QAAQ,SAAS,SAAS;AACnD,YAAM,WAAW,MAAM,KAAK,iBAAiB,GAAG;AAChD,aAAO,SAAS;AAAA,IAClB,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA,EAIA,MAAM,YACJ,MACA,QACiC;AACjC,UAAM,WAAW,QAAQ,IAAI,IAAI,KAAK,UAAU,UAAU,CAAC,CAAC,CAAC;AAC7D,UAAM,SAAS,KAAK,UAAkC,QAAQ;AAC9D,QAAI,OAAQ,QAAO;AAEnB,UAAM,eAAe,IAAI,gBAAgB;AACzC,QAAI,QAAQ,UAAW,cAAa,IAAI,aAAa,OAAO,SAAS;AACrE,QAAI,QAAQ,MAAO,cAAa,IAAI,SAAS,OAAO,OAAO,KAAK,CAAC;AACjE,QAAI,QAAQ,OAAQ,cAAa,IAAI,UAAU,OAAO,OAAO,MAAM,CAAC;AAEpE,UAAM,QAAQ,aAAa,SAAS;AACpC,UAAM,OAAO,IAAI,IAAI,GAAG,QAAQ,IAAI,KAAK,KAAK,EAAE;AAChD,UAAM,SAAS,MAAM,KAAK,QAAgC,IAAI;AAC9D,SAAK,SAAS,UAAU,MAAM;AAC9B,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,WACJ,MACA,WACA,MACY;AACZ,UAAM,WAAW,OAAO,IAAI,IAAI,SAAS,IAAI,IAAI;AACjD,UAAM,SAAS,KAAK,UAAa,QAAQ;AACzC,QAAI,OAAQ,QAAO;AAEnB,UAAM,SAAS,MAAM,KAAK,QAAW,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,EAAE;AACpE,SAAK,SAAS,UAAU,MAAM;AAC9B,WAAO;AAAA,EACT;AAAA;AAAA,EAIA,MAAM,WAAW,WAAmB,MAAgC;AAClE,WAAO,KAAK,WAAoB,YAAY,WAAW,IAAI;AAAA,EAC7D;AAAA,EAEA,MAAM,aAAa,WAAmB,MAAkC;AACtE,WAAO,KAAK,WAAsB,cAAc,WAAW,IAAI;AAAA,EACjE;AAAA,EAEA,MAAM,SAAS,WAAmB,MAA8B;AAC9D,WAAO,KAAK,WAAkB,UAAU,WAAW,IAAI;AAAA,EACzD;AAAA,EAEA,MAAM,aAAa,WAAmB,MAAkC;AACtE,WAAO,KAAK,WAAsB,cAAc,WAAW,IAAI;AAAA,EACjE;AAAA,EAEA,MAAM,SAAS,WAAmB,MAA8B;AAC9D,WAAO,KAAK,WAAkB,UAAU,WAAW,IAAI;AAAA,EACzD;AAAA;AAAA,EAIA,MAAM,OAAO,QAA+C;AAC1D,UAAM,eAAe,IAAI,gBAAgB,EAAE,GAAG,OAAO,EAAE,CAAC;AACxD,QAAI,OAAO,KAAM,cAAa,IAAI,QAAQ,OAAO,IAAI;AACrD,QAAI,OAAO,UAAW,cAAa,IAAI,aAAa,OAAO,SAAS;AACpE,QAAI,OAAO,MAAO,cAAa,IAAI,SAAS,OAAO,OAAO,KAAK,CAAC;AAChE,QAAI,OAAO,OAAQ,cAAa,IAAI,UAAU,OAAO,OAAO,MAAM,CAAC;AAEnE,WAAO,KAAK,QAAwB,WAAW,YAAY,EAAE;AAAA,EAC/D;AAAA;AAAA,EAIA,MAAM,aAAmC;AACvC,WAAO,KAAK,QAAqB,KAAK;AAAA,EACxC;AAAA,EAEA,MAAM,eAAe,SAAmD;AACtE,WAAO,KAAK,QAAyB,YAAY;AAAA,MAC/C,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,OAAO;AAAA,IAC9B,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,eAA0D;AAC9D,WAAO,KAAK,QAA0C,aAAa;AAAA,EACrE;AAAA;AAAA,EAIA,MAAM,UAAU,OAAe,mBAAqD;AAClF,WAAO,KAAK,QAAiC,WAAW,IAAI,EAAE;AAAA,EAChE;AACF;AAsBO,SAAS,qBAAqB,UAAiC,CAAC,GAAmB;AACxF,QAAM,UAAU,QAAQ,WAAW;AACnC,SAAO;AAAA,IACL,MAAM,OAAO,OAAe,MAAwC;AAClE,YAAM,SAAS,IAAI,gBAAgB,EAAE,GAAG,MAAM,CAAC;AAC/C,UAAI,KAAM,QAAO,IAAI,QAAQ,IAAI;AACjC,YAAM,MAAM,MAAM,MAAM,GAAG,OAAO,WAAW,MAAM,EAAE;AACrD,UAAI,CAAC,IAAI,GAAI,QAAO,CAAC;AACrB,YAAM,OAAO,MAAM,IAAI,KAAK;AAE5B,UAAI,MAAM,QAAQ,IAAI,EAAG,QAAO;AAChC,aAAQ,KAAqC,WAAW,CAAC;AAAA,IAC3D;AAAA,IACA,MAAM,MAAM,MAAc,IAAY,SAAoC;AACxE,YAAM,MAAM,UAAU,GAAG,OAAO,YAAY,IAAI,IAAI,EAAE,IAAI,OAAO,KAAK,GAAG,OAAO,YAAY,IAAI,IAAI,EAAE;AACtG,YAAM,MAAM,MAAM,MAAM,GAAG;AAC3B,UAAI,CAAC,IAAI,GAAI,QAAO;AACpB,aAAO,IAAI,KAAK;AAAA,IAClB;AAAA,EACF;AACF;","names":[]}
|