@affectively/aeon-pages 1.3.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/CHANGELOG.md +112 -0
- package/README.md +625 -0
- package/examples/basic/aeon.config.ts +39 -0
- package/examples/basic/components/Cursor.tsx +86 -0
- package/examples/basic/components/OfflineIndicator.tsx +103 -0
- package/examples/basic/components/PresenceBar.tsx +77 -0
- package/examples/basic/package.json +20 -0
- package/examples/basic/pages/index.tsx +80 -0
- package/package.json +101 -0
- package/packages/analytics/README.md +309 -0
- package/packages/analytics/build.ts +35 -0
- package/packages/analytics/package.json +50 -0
- package/packages/analytics/src/click-tracker.ts +368 -0
- package/packages/analytics/src/context-bridge.ts +319 -0
- package/packages/analytics/src/data-layer.ts +302 -0
- package/packages/analytics/src/gtm-loader.ts +239 -0
- package/packages/analytics/src/index.ts +230 -0
- package/packages/analytics/src/merkle-tree.ts +489 -0
- package/packages/analytics/src/provider.tsx +300 -0
- package/packages/analytics/src/types.ts +320 -0
- package/packages/analytics/src/use-analytics.ts +296 -0
- package/packages/analytics/tsconfig.json +19 -0
- package/packages/benchmarks/src/benchmark.test.ts +691 -0
- package/packages/cli/dist/index.js +61899 -0
- package/packages/cli/package.json +43 -0
- package/packages/cli/src/commands/build.test.ts +682 -0
- package/packages/cli/src/commands/build.ts +890 -0
- package/packages/cli/src/commands/dev.ts +473 -0
- package/packages/cli/src/commands/init.ts +409 -0
- package/packages/cli/src/commands/start.ts +297 -0
- package/packages/cli/src/index.ts +105 -0
- package/packages/directives/src/use-aeon.ts +272 -0
- package/packages/mcp-server/package.json +51 -0
- package/packages/mcp-server/src/index.ts +178 -0
- package/packages/mcp-server/src/resources.ts +346 -0
- package/packages/mcp-server/src/tools/index.ts +36 -0
- package/packages/mcp-server/src/tools/navigation.ts +545 -0
- package/packages/mcp-server/tsconfig.json +21 -0
- package/packages/react/package.json +40 -0
- package/packages/react/src/Link.tsx +388 -0
- package/packages/react/src/components/InstallPrompt.tsx +286 -0
- package/packages/react/src/components/OfflineDiagnostics.tsx +677 -0
- package/packages/react/src/components/PushNotifications.tsx +453 -0
- package/packages/react/src/hooks/useAeonNavigation.ts +219 -0
- package/packages/react/src/hooks/useConflicts.ts +277 -0
- package/packages/react/src/hooks/useNetworkState.ts +209 -0
- package/packages/react/src/hooks/usePilotNavigation.ts +254 -0
- package/packages/react/src/hooks/useServiceWorker.ts +278 -0
- package/packages/react/src/hooks.ts +195 -0
- package/packages/react/src/index.ts +151 -0
- package/packages/react/src/provider.tsx +467 -0
- package/packages/react/tsconfig.json +19 -0
- package/packages/runtime/README.md +399 -0
- package/packages/runtime/build.ts +48 -0
- package/packages/runtime/package.json +71 -0
- package/packages/runtime/schema.sql +40 -0
- package/packages/runtime/src/api-routes.ts +465 -0
- package/packages/runtime/src/benchmark.ts +171 -0
- package/packages/runtime/src/cache.ts +479 -0
- package/packages/runtime/src/durable-object.ts +1341 -0
- package/packages/runtime/src/index.ts +360 -0
- package/packages/runtime/src/navigation.test.ts +421 -0
- package/packages/runtime/src/navigation.ts +422 -0
- package/packages/runtime/src/nextjs-adapter.ts +272 -0
- package/packages/runtime/src/offline/encrypted-queue.test.ts +607 -0
- package/packages/runtime/src/offline/encrypted-queue.ts +478 -0
- package/packages/runtime/src/offline/encryption.test.ts +412 -0
- package/packages/runtime/src/offline/encryption.ts +397 -0
- package/packages/runtime/src/offline/types.ts +465 -0
- package/packages/runtime/src/predictor.ts +371 -0
- package/packages/runtime/src/registry.ts +351 -0
- package/packages/runtime/src/router/context-extractor.ts +661 -0
- package/packages/runtime/src/router/esi-control-react.tsx +2053 -0
- package/packages/runtime/src/router/esi-control.ts +541 -0
- package/packages/runtime/src/router/esi-cyrano.ts +779 -0
- package/packages/runtime/src/router/esi-format-react.tsx +1744 -0
- package/packages/runtime/src/router/esi-react.tsx +1065 -0
- package/packages/runtime/src/router/esi-translate-observer.ts +476 -0
- package/packages/runtime/src/router/esi-translate-react.tsx +556 -0
- package/packages/runtime/src/router/esi-translate.ts +503 -0
- package/packages/runtime/src/router/esi.ts +666 -0
- package/packages/runtime/src/router/heuristic-adapter.test.ts +295 -0
- package/packages/runtime/src/router/heuristic-adapter.ts +557 -0
- package/packages/runtime/src/router/index.ts +298 -0
- package/packages/runtime/src/router/merkle-capability.ts +473 -0
- package/packages/runtime/src/router/speculation.ts +451 -0
- package/packages/runtime/src/router/types.ts +630 -0
- package/packages/runtime/src/router.test.ts +470 -0
- package/packages/runtime/src/router.ts +302 -0
- package/packages/runtime/src/server.ts +481 -0
- package/packages/runtime/src/service-worker-push.ts +319 -0
- package/packages/runtime/src/service-worker.ts +553 -0
- package/packages/runtime/src/skeleton-hydrate.ts +237 -0
- package/packages/runtime/src/speculation.test.ts +389 -0
- package/packages/runtime/src/speculation.ts +486 -0
- package/packages/runtime/src/storage.test.ts +1297 -0
- package/packages/runtime/src/storage.ts +1048 -0
- package/packages/runtime/src/sync/conflict-resolver.test.ts +528 -0
- package/packages/runtime/src/sync/conflict-resolver.ts +565 -0
- package/packages/runtime/src/sync/coordinator.test.ts +608 -0
- package/packages/runtime/src/sync/coordinator.ts +596 -0
- package/packages/runtime/src/tree-compiler.ts +295 -0
- package/packages/runtime/src/types.ts +728 -0
- package/packages/runtime/src/worker.ts +327 -0
- package/packages/runtime/tsconfig.json +20 -0
- package/packages/runtime/wasm/aeon_pages_runtime.d.ts +504 -0
- package/packages/runtime/wasm/aeon_pages_runtime.js +1657 -0
- package/packages/runtime/wasm/aeon_pages_runtime_bg.wasm +0 -0
- package/packages/runtime/wasm/aeon_pages_runtime_bg.wasm.d.ts +196 -0
- package/packages/runtime/wasm/package.json +21 -0
- package/packages/runtime/wrangler.toml +41 -0
- package/packages/runtime-wasm/Cargo.lock +436 -0
- package/packages/runtime-wasm/Cargo.toml +29 -0
- package/packages/runtime-wasm/pkg/aeon_pages_runtime.d.ts +480 -0
- package/packages/runtime-wasm/pkg/aeon_pages_runtime.js +1568 -0
- package/packages/runtime-wasm/pkg/aeon_pages_runtime_bg.wasm +0 -0
- package/packages/runtime-wasm/pkg/aeon_pages_runtime_bg.wasm.d.ts +192 -0
- package/packages/runtime-wasm/pkg/package.json +21 -0
- package/packages/runtime-wasm/src/hydrate.rs +352 -0
- package/packages/runtime-wasm/src/lib.rs +191 -0
- package/packages/runtime-wasm/src/render.rs +629 -0
- package/packages/runtime-wasm/src/router.rs +298 -0
- package/packages/runtime-wasm/src/skeleton.rs +430 -0
- package/rfcs/RFC-001-ZERO-DEPENDENCY-RENDERING.md +1446 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tree → TSX Compiler
|
|
3
|
+
*
|
|
4
|
+
* Converts component trees from the visual editor back to TSX source code.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
interface TreeNode {
|
|
8
|
+
id: string;
|
|
9
|
+
type: string;
|
|
10
|
+
props?: Record<string, unknown>;
|
|
11
|
+
children?: string[] | TreeNode[];
|
|
12
|
+
text?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface CompilerOptions {
|
|
16
|
+
/** Route path for the page */
|
|
17
|
+
route: string;
|
|
18
|
+
/** Include 'use aeon' directive */
|
|
19
|
+
useAeon?: boolean;
|
|
20
|
+
/** Component imports to add */
|
|
21
|
+
imports?: Record<string, string>; // { 'Hero': '@/components/Hero' }
|
|
22
|
+
/** Whether to format output */
|
|
23
|
+
format?: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Compile a tree to TSX source code
|
|
28
|
+
*/
|
|
29
|
+
export function compileTreeToTSX(
|
|
30
|
+
tree: TreeNode | TreeNode[],
|
|
31
|
+
options: CompilerOptions,
|
|
32
|
+
): string {
|
|
33
|
+
const { route, useAeon = true, imports = {}, format = true } = options;
|
|
34
|
+
|
|
35
|
+
// Collect all component types used
|
|
36
|
+
const usedComponents = new Set<string>();
|
|
37
|
+
collectComponents(tree, usedComponents);
|
|
38
|
+
|
|
39
|
+
// Build imports
|
|
40
|
+
const importLines: string[] = [];
|
|
41
|
+
|
|
42
|
+
// React import (if needed)
|
|
43
|
+
importLines.push("import type { FC } from 'react';");
|
|
44
|
+
|
|
45
|
+
// Component imports
|
|
46
|
+
for (const component of usedComponents) {
|
|
47
|
+
if (imports[component]) {
|
|
48
|
+
importLines.push(`import { ${component} } from '${imports[component]}';`);
|
|
49
|
+
} else if (!isHTMLElement(component)) {
|
|
50
|
+
// Default import path for unknown components
|
|
51
|
+
importLines.push(
|
|
52
|
+
`import { ${component} } from '@/components/${component}';`,
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Generate component name from route
|
|
58
|
+
const componentName = routeToComponentName(route);
|
|
59
|
+
|
|
60
|
+
// Generate JSX
|
|
61
|
+
const jsx = nodeToJSX(tree, 2);
|
|
62
|
+
|
|
63
|
+
// Assemble the file
|
|
64
|
+
const lines: string[] = [];
|
|
65
|
+
|
|
66
|
+
if (useAeon) {
|
|
67
|
+
lines.push("'use aeon';");
|
|
68
|
+
lines.push('');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
lines.push('/**');
|
|
72
|
+
lines.push(` * ${componentName}`);
|
|
73
|
+
lines.push(` * Route: ${route}`);
|
|
74
|
+
lines.push(' * ');
|
|
75
|
+
lines.push(' * @generated by aeon-flux visual editor');
|
|
76
|
+
lines.push(' */');
|
|
77
|
+
lines.push('');
|
|
78
|
+
|
|
79
|
+
lines.push(...importLines);
|
|
80
|
+
lines.push('');
|
|
81
|
+
|
|
82
|
+
lines.push(`const ${componentName}: FC = () => {`);
|
|
83
|
+
lines.push(' return (');
|
|
84
|
+
lines.push(jsx);
|
|
85
|
+
lines.push(' );');
|
|
86
|
+
lines.push('};');
|
|
87
|
+
lines.push('');
|
|
88
|
+
lines.push(`export default ${componentName};`);
|
|
89
|
+
lines.push('');
|
|
90
|
+
|
|
91
|
+
return lines.join('\n');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Collect all component types used in the tree
|
|
96
|
+
*/
|
|
97
|
+
function collectComponents(
|
|
98
|
+
node: TreeNode | TreeNode[],
|
|
99
|
+
set: Set<string>,
|
|
100
|
+
): void {
|
|
101
|
+
if (Array.isArray(node)) {
|
|
102
|
+
node.forEach((n) => collectComponents(n, set));
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (node.type && !isHTMLElement(node.type)) {
|
|
107
|
+
set.add(node.type);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (node.children) {
|
|
111
|
+
if (Array.isArray(node.children)) {
|
|
112
|
+
node.children.forEach((child) => {
|
|
113
|
+
if (typeof child === 'object') {
|
|
114
|
+
collectComponents(child, set);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Convert a tree node to JSX string
|
|
123
|
+
*/
|
|
124
|
+
function nodeToJSX(node: TreeNode | TreeNode[], indent: number = 0): string {
|
|
125
|
+
const spaces = ' '.repeat(indent);
|
|
126
|
+
|
|
127
|
+
if (Array.isArray(node)) {
|
|
128
|
+
if (node.length === 0) return `${spaces}{null}`;
|
|
129
|
+
if (node.length === 1) return nodeToJSX(node[0], indent);
|
|
130
|
+
return `${spaces}<>\n${node.map((n) => nodeToJSX(n, indent + 1)).join('\n')}\n${spaces}</>`;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const { type, props = {}, children, text } = node;
|
|
134
|
+
|
|
135
|
+
// Text node
|
|
136
|
+
if (type === 'text' || text) {
|
|
137
|
+
const content = text || props.content || props.text || '';
|
|
138
|
+
return `${spaces}${escapeJSX(String(content))}`;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Component/element name
|
|
142
|
+
const tagName = isHTMLElement(type) ? type.toLowerCase() : type;
|
|
143
|
+
|
|
144
|
+
// Props string
|
|
145
|
+
const propsStr = propsToString(props);
|
|
146
|
+
|
|
147
|
+
// No children - self-closing
|
|
148
|
+
if (!children || (Array.isArray(children) && children.length === 0)) {
|
|
149
|
+
return `${spaces}<${tagName}${propsStr} />`;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// With children
|
|
153
|
+
const childrenJSX = Array.isArray(children)
|
|
154
|
+
? children
|
|
155
|
+
.map((child) => {
|
|
156
|
+
if (typeof child === 'string') {
|
|
157
|
+
return `${spaces} ${escapeJSX(child)}`;
|
|
158
|
+
}
|
|
159
|
+
return nodeToJSX(child, indent + 1);
|
|
160
|
+
})
|
|
161
|
+
.join('\n')
|
|
162
|
+
: `${spaces} ${escapeJSX(String(children))}`;
|
|
163
|
+
|
|
164
|
+
return `${spaces}<${tagName}${propsStr}>\n${childrenJSX}\n${spaces}</${tagName}>`;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Convert props object to JSX props string
|
|
169
|
+
*/
|
|
170
|
+
function propsToString(props: Record<string, unknown>): string {
|
|
171
|
+
const entries = Object.entries(props).filter(
|
|
172
|
+
([key]) => !['children', 'id', 'text', 'content'].includes(key),
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
if (entries.length === 0) return '';
|
|
176
|
+
|
|
177
|
+
const propsArr = entries
|
|
178
|
+
.map(([key, value]) => {
|
|
179
|
+
// Handle different value types
|
|
180
|
+
if (typeof value === 'string') {
|
|
181
|
+
return `${key}="${escapeAttr(value)}"`;
|
|
182
|
+
}
|
|
183
|
+
if (typeof value === 'boolean') {
|
|
184
|
+
return value ? key : `${key}={false}`;
|
|
185
|
+
}
|
|
186
|
+
if (typeof value === 'number') {
|
|
187
|
+
return `${key}={${value}}`;
|
|
188
|
+
}
|
|
189
|
+
if (value === null || value === undefined) {
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
// Objects/arrays as JSX expressions
|
|
193
|
+
return `${key}={${JSON.stringify(value)}}`;
|
|
194
|
+
})
|
|
195
|
+
.filter(Boolean);
|
|
196
|
+
|
|
197
|
+
return propsArr.length > 0 ? ' ' + propsArr.join(' ') : '';
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Convert route to component name
|
|
202
|
+
*/
|
|
203
|
+
function routeToComponentName(route: string): string {
|
|
204
|
+
if (route === '/' || route === '') return 'IndexPage';
|
|
205
|
+
|
|
206
|
+
const parts = route
|
|
207
|
+
.replace(/^\/|\/$/g, '')
|
|
208
|
+
.split('/')
|
|
209
|
+
.map((part) => {
|
|
210
|
+
// Handle dynamic segments
|
|
211
|
+
if (part.startsWith('[') && part.endsWith(']')) {
|
|
212
|
+
return 'Dynamic' + capitalize(part.slice(1, -1));
|
|
213
|
+
}
|
|
214
|
+
return capitalize(part);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
return parts.join('') + 'Page';
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Check if a type is an HTML element
|
|
222
|
+
*/
|
|
223
|
+
function isHTMLElement(type: string): boolean {
|
|
224
|
+
const htmlElements = [
|
|
225
|
+
'div',
|
|
226
|
+
'span',
|
|
227
|
+
'p',
|
|
228
|
+
'a',
|
|
229
|
+
'button',
|
|
230
|
+
'input',
|
|
231
|
+
'form',
|
|
232
|
+
'h1',
|
|
233
|
+
'h2',
|
|
234
|
+
'h3',
|
|
235
|
+
'h4',
|
|
236
|
+
'h5',
|
|
237
|
+
'h6',
|
|
238
|
+
'ul',
|
|
239
|
+
'ol',
|
|
240
|
+
'li',
|
|
241
|
+
'nav',
|
|
242
|
+
'header',
|
|
243
|
+
'footer',
|
|
244
|
+
'main',
|
|
245
|
+
'section',
|
|
246
|
+
'article',
|
|
247
|
+
'aside',
|
|
248
|
+
'img',
|
|
249
|
+
'video',
|
|
250
|
+
'audio',
|
|
251
|
+
'canvas',
|
|
252
|
+
'svg',
|
|
253
|
+
'table',
|
|
254
|
+
'thead',
|
|
255
|
+
'tbody',
|
|
256
|
+
'tr',
|
|
257
|
+
'td',
|
|
258
|
+
'th',
|
|
259
|
+
'label',
|
|
260
|
+
'select',
|
|
261
|
+
'option',
|
|
262
|
+
'textarea',
|
|
263
|
+
'strong',
|
|
264
|
+
'em',
|
|
265
|
+
'code',
|
|
266
|
+
'pre',
|
|
267
|
+
'blockquote',
|
|
268
|
+
];
|
|
269
|
+
return htmlElements.includes(type.toLowerCase());
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Capitalize first letter
|
|
274
|
+
*/
|
|
275
|
+
function capitalize(str: string): string {
|
|
276
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Escape string for JSX content
|
|
281
|
+
*/
|
|
282
|
+
function escapeJSX(str: string): string {
|
|
283
|
+
return str
|
|
284
|
+
.replace(/\{/g, '{')
|
|
285
|
+
.replace(/\}/g, '}')
|
|
286
|
+
.replace(/</g, '<')
|
|
287
|
+
.replace(/>/g, '>');
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Escape string for JSX attribute
|
|
292
|
+
*/
|
|
293
|
+
function escapeAttr(str: string): string {
|
|
294
|
+
return str.replace(/"/g, '"').replace(/'/g, ''');
|
|
295
|
+
}
|