@nuraly/lumenjs 0.1.4 → 0.2.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.
Files changed (76) hide show
  1. package/dist/auth/native-auth.d.ts +9 -0
  2. package/dist/auth/native-auth.js +49 -2
  3. package/dist/auth/routes/login.js +24 -1
  4. package/dist/auth/routes/totp.d.ts +22 -0
  5. package/dist/auth/routes/totp.js +232 -0
  6. package/dist/auth/routes.js +14 -0
  7. package/dist/auth/token.js +2 -2
  8. package/dist/build/build-server.d.ts +2 -1
  9. package/dist/build/build-server.js +10 -1
  10. package/dist/build/build.js +13 -4
  11. package/dist/build/scan.d.ts +1 -0
  12. package/dist/build/scan.js +2 -1
  13. package/dist/build/serve.js +131 -11
  14. package/dist/dev-server/config.js +18 -1
  15. package/dist/dev-server/index-html.d.ts +1 -0
  16. package/dist/dev-server/index-html.js +4 -1
  17. package/dist/dev-server/plugins/vite-plugin-routes.js +3 -2
  18. package/dist/dev-server/plugins/vite-plugin-virtual-modules.js +34 -6
  19. package/dist/dev-server/server.js +146 -88
  20. package/dist/dev-server/ssr-render.js +10 -2
  21. package/dist/editor/ai/backend.js +11 -2
  22. package/dist/editor/ai/deepseek-client.d.ts +7 -0
  23. package/dist/editor/ai/deepseek-client.js +113 -0
  24. package/dist/editor/ai/opencode-client.d.ts +1 -1
  25. package/dist/editor/ai/opencode-client.js +21 -47
  26. package/dist/editor/ai-chat-panel.js +27 -1
  27. package/dist/editor/editor-bridge.js +2 -1
  28. package/dist/editor/overlay-hmr.js +2 -1
  29. package/dist/runtime/app-shell.d.ts +1 -1
  30. package/dist/runtime/app-shell.js +1 -0
  31. package/dist/runtime/island.d.ts +16 -0
  32. package/dist/runtime/island.js +80 -0
  33. package/dist/runtime/router-hydration.js +9 -2
  34. package/dist/runtime/router.d.ts +3 -1
  35. package/dist/runtime/router.js +49 -1
  36. package/dist/runtime/webrtc.d.ts +44 -0
  37. package/dist/runtime/webrtc.js +263 -13
  38. package/dist/shared/dom-shims.js +4 -2
  39. package/dist/shared/types.d.ts +1 -0
  40. package/dist/storage/adapters/s3.js +6 -3
  41. package/package.json +33 -7
  42. package/templates/social/api/posts/[id].ts +0 -14
  43. package/templates/social/api/posts.ts +0 -11
  44. package/templates/social/api/profile/[username].ts +0 -10
  45. package/templates/social/api/upload.ts +0 -19
  46. package/templates/social/data/migrations/001_init.sql +0 -78
  47. package/templates/social/data/migrations/002_add_image_url.sql +0 -1
  48. package/templates/social/data/migrations/003_auth.sql +0 -7
  49. package/templates/social/docs/architecture.md +0 -76
  50. package/templates/social/docs/components.md +0 -100
  51. package/templates/social/docs/data.md +0 -89
  52. package/templates/social/docs/pages.md +0 -96
  53. package/templates/social/docs/theming.md +0 -52
  54. package/templates/social/lib/media.ts +0 -130
  55. package/templates/social/lumenjs.auth.ts +0 -21
  56. package/templates/social/lumenjs.config.ts +0 -3
  57. package/templates/social/package.json +0 -5
  58. package/templates/social/pages/_layout.ts +0 -239
  59. package/templates/social/pages/apps/[id].ts +0 -173
  60. package/templates/social/pages/apps/index.ts +0 -116
  61. package/templates/social/pages/auth/login.ts +0 -92
  62. package/templates/social/pages/bookmarks.ts +0 -57
  63. package/templates/social/pages/explore.ts +0 -73
  64. package/templates/social/pages/index.ts +0 -351
  65. package/templates/social/pages/messages.ts +0 -298
  66. package/templates/social/pages/new.ts +0 -77
  67. package/templates/social/pages/notifications.ts +0 -73
  68. package/templates/social/pages/post/[id].ts +0 -124
  69. package/templates/social/pages/profile/[username].ts +0 -100
  70. package/templates/social/pages/settings/accessibility.ts +0 -153
  71. package/templates/social/pages/settings/account.ts +0 -260
  72. package/templates/social/pages/settings/help.ts +0 -141
  73. package/templates/social/pages/settings/language.ts +0 -103
  74. package/templates/social/pages/settings/privacy.ts +0 -183
  75. package/templates/social/pages/settings/security.ts +0 -133
  76. package/templates/social/pages/settings.ts +0 -185
@@ -1,116 +0,0 @@
1
- import { LitElement, html, css } from 'lit';
2
-
3
- const svg = {
4
- search: html`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>`,
5
- };
6
-
7
- export async function loader() {
8
- return {
9
- featured: [
10
- { id: 'poll', name: 'Polls', desc: 'Create polls and surveys for your community', color: '#7c3aed', icon: 'bar-chart' },
11
- { id: 'calendar', name: 'Calendar', desc: 'Track events, meetings, and deadlines', color: '#3b49df', icon: 'calendar' },
12
- { id: 'notes', name: 'Quick Notes', desc: 'Markdown notes that sync across devices', color: '#22c55e', icon: 'file-text' },
13
- ],
14
- categories: ['Productivity', 'Entertainment', 'Finance', 'Social', 'Developer Tools', 'Health'],
15
- apps: [
16
- { id: 'poll', name: 'Poll Creator', desc: 'Create polls and surveys for your feed', category: 'Social', color: '#7c3aed' },
17
- { id: 'calendar', name: 'Mini Calendar', desc: 'Track events and meetings', category: 'Productivity', color: '#3b49df' },
18
- { id: 'notes', name: 'Quick Notes', desc: 'Markdown notes with cloud sync', category: 'Productivity', color: '#22c55e' },
19
- { id: 'timer', name: 'Focus Timer', desc: 'Pomodoro timer for deep work', category: 'Productivity', color: '#ef4444' },
20
- { id: 'weather', name: 'Weather', desc: 'Local weather and forecasts', category: 'Entertainment', color: '#f59e0b' },
21
- { id: 'stocks', name: 'Stock Tracker', desc: 'Watch your portfolio in real-time', category: 'Finance', color: '#10b981' },
22
- { id: 'news', name: 'News Feed', desc: 'Curated tech news from top sources', category: 'Entertainment', color: '#6366f1' },
23
- { id: 'tasks', name: 'Task Board', desc: 'Kanban-style task management', category: 'Productivity', color: '#8b5cf6' },
24
- { id: 'translate', name: 'Translator', desc: 'Translate text between languages', category: 'Developer Tools', color: '#06b6d4' },
25
- { id: 'code', name: 'Code Snippets', desc: 'Save and share code snippets', category: 'Developer Tools', color: '#0f172a' },
26
- { id: 'fitness', name: 'Step Counter', desc: 'Track daily steps and activity', category: 'Health', color: '#ec4899' },
27
- { id: 'budget', name: 'Budget Tracker', desc: 'Track expenses and income', category: 'Finance', color: '#14b8a6' },
28
- ],
29
- };
30
- }
31
-
32
- export class PageApps extends LitElement {
33
- static properties = { loaderData: { type: Object }, _category: { state: true } };
34
- loaderData: any = {};
35
- _category: string = '';
36
-
37
- static styles = css`
38
- :host { display: block; }
39
- .card { background: var(--bg); border-radius: 6px; border: 1px solid var(--border); overflow: hidden; margin-bottom: 12px; }
40
- h2 { font-size: 20px; font-weight: 700; padding: 16px 20px 8px; margin: 0; }
41
-
42
- .search-wrap { padding: 0 20px 16px; position: relative; }
43
- .search-icon { position: absolute; left: 32px; top: 50%; transform: translateY(-50%); color: var(--text-secondary); display: flex; }
44
- .search { width: 100%; padding: 10px 12px 10px 36px; border: 1px solid var(--border); border-radius: 9999px; font-size: 14px; outline: none; background: var(--input-bg); }
45
- .search:focus { border-color: var(--accent); background: var(--bg); }
46
-
47
- .featured { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; padding: 0 20px 16px; }
48
- .feat-card { border: 1px solid var(--border); border-radius: 12px; padding: 16px; cursor: pointer; text-decoration: none; color: inherit; transition: box-shadow 0.15s; }
49
- .feat-card:hover { box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
50
- .feat-icon { width: 40px; height: 40px; border-radius: 10px; display: flex; align-items: center; justify-content: center; color: #fff; font-size: 18px; font-weight: 700; }
51
- .feat-name { font-size: 15px; font-weight: 700; margin-top: 10px; }
52
- .feat-desc { font-size: 12px; color: var(--text-secondary); margin-top: 4px; line-height: 1.3; }
53
-
54
- .categories { display: flex; gap: 6px; padding: 0 20px 12px; overflow-x: auto; scrollbar-width: none; }
55
- .categories::-webkit-scrollbar { display: none; }
56
- .cat-btn { padding: 6px 14px; border-radius: 9999px; border: 1px solid var(--border); background: var(--bg); font-size: 13px; color: var(--text-secondary); cursor: pointer; white-space: nowrap; font-weight: 500; }
57
- .cat-btn:hover { border-color: var(--accent); color: var(--accent); }
58
- .cat-btn.active { background: var(--accent); color: #fff; border-color: var(--accent); }
59
-
60
- .app-list { padding: 0 20px 8px; }
61
- .app-item { display: flex; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--border-light); align-items: center; }
62
- .app-item:last-child { border-bottom: none; }
63
- .app-icon { width: 40px; height: 40px; border-radius: 10px; display: flex; align-items: center; justify-content: center; color: #fff; font-size: 16px; font-weight: 700; flex-shrink: 0; }
64
- .app-info { flex: 1; min-width: 0; }
65
- .app-name { font-size: 14px; font-weight: 700; }
66
- .app-desc { font-size: 12px; color: var(--text-secondary); margin-top: 1px; }
67
- .app-cat { font-size: 11px; color: var(--text-tertiary); margin-top: 2px; }
68
- .open-btn { padding: 5px 14px; border-radius: 9999px; border: 1px solid var(--accent); color: var(--accent); background: var(--bg); font-size: 12px; font-weight: 600; cursor: pointer; text-decoration: none; }
69
- .open-btn:hover { background: rgba(124,58,237,0.1); }
70
-
71
- @media (max-width: 640px) { .featured { grid-template-columns: 1fr; } }
72
- `;
73
-
74
- render() {
75
- const { featured, categories, apps } = this.loaderData;
76
- const filtered = this._category ? apps?.filter((a: any) => a.category === this._category) : apps;
77
- return html`
78
- <div class="card">
79
- <h2>Apps</h2>
80
- <div class="search-wrap">
81
- <span class="search-icon">${svg.search}</span>
82
- <input class="search" type="text" placeholder="Search apps...">
83
- </div>
84
- <h2 style="font-size:16px;padding-top:0">Featured</h2>
85
- <div class="featured">
86
- ${(featured || []).map((f: any) => html`
87
- <a class="feat-card" href="/apps/${f.id}">
88
- <div class="feat-icon" style="background:${f.color}">${f.name.charAt(0)}</div>
89
- <div class="feat-name">${f.name}</div>
90
- <div class="feat-desc">${f.desc}</div>
91
- </a>
92
- `)}
93
- </div>
94
- <div class="categories">
95
- <button class="cat-btn ${this._category === '' ? 'active' : ''}" @click=${() => this._category = ''}>All</button>
96
- ${(categories || []).map((c: string) => html`
97
- <button class="cat-btn ${this._category === c ? 'active' : ''}" @click=${() => this._category = c}>${c}</button>
98
- `)}
99
- </div>
100
- <div class="app-list">
101
- ${(filtered || []).map((a: any) => html`
102
- <div class="app-item">
103
- <div class="app-icon" style="background:${a.color}">${a.name.charAt(0)}</div>
104
- <div class="app-info">
105
- <div class="app-name">${a.name}</div>
106
- <div class="app-desc">${a.desc}</div>
107
- <div class="app-cat">${a.category}</div>
108
- </div>
109
- <a class="open-btn" href="/apps/${a.id}">Open</a>
110
- </div>
111
- `)}
112
- </div>
113
- </div>
114
- `;
115
- }
116
- }
@@ -1,92 +0,0 @@
1
- import { LitElement, html, css } from 'lit';
2
-
3
- // Google 'G' logo SVG (official colors)
4
- const googleLogo = html`<svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
5
- <path d="M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844a4.14 4.14 0 01-1.796 2.716v2.259h2.908c1.702-1.567 2.684-3.875 2.684-6.615z" fill="#4285F4"/>
6
- <path d="M9 18c2.43 0 4.467-.806 5.956-2.18l-2.908-2.259c-.806.54-1.837.86-3.048.86-2.344 0-4.328-1.584-5.036-3.711H.957v2.332A8.997 8.997 0 009 18z" fill="#34A853"/>
7
- <path d="M3.964 10.71A5.41 5.41 0 013.682 9c0-.593.102-1.17.282-1.71V4.958H.957A8.996 8.996 0 000 9c0 1.452.348 2.827.957 4.042l3.007-2.332z" fill="#FBBC05"/>
8
- <path d="M9 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.463.891 11.426 0 9 0A8.997 8.997 0 00.957 4.958L3.964 6.29C4.672 4.163 6.656 3.58 9 3.58z" fill="#EA4335"/>
9
- </svg>`;
10
-
11
- export async function loader({ query }: any) {
12
- return {
13
- error: query?.error ?? null,
14
- returnTo: query?.returnTo ?? '/',
15
- };
16
- }
17
-
18
- export class PageAuthLogin extends LitElement {
19
- static properties = { loaderData: { type: Object } };
20
- loaderData: any = {};
21
-
22
- static styles = css`
23
- :host { display: flex; align-items: center; justify-content: center; min-height: 80vh; padding: 24px 16px; }
24
-
25
- .card {
26
- width: 100%; max-width: 380px;
27
- background: var(--bg); border: 1px solid var(--border);
28
- border-radius: 16px; padding: 40px 32px;
29
- text-align: center;
30
- box-shadow: 0 4px 24px rgba(0,0,0,0.06);
31
- }
32
-
33
- .logo {
34
- width: 52px; height: 52px; border-radius: 50%;
35
- background: var(--accent); color: #fff;
36
- font-size: 24px; font-weight: 900;
37
- display: flex; align-items: center; justify-content: center;
38
- margin: 0 auto 20px;
39
- }
40
-
41
- h1 { font-size: 22px; font-weight: 800; margin: 0 0 6px; color: var(--text); }
42
- p { font-size: 14px; color: var(--text-secondary); margin: 0 0 28px; }
43
-
44
- .error {
45
- background: #fef2f2; border: 1px solid #fecaca; border-radius: 8px;
46
- color: #dc2626; font-size: 13px; padding: 10px 14px;
47
- margin-bottom: 20px; text-align: left;
48
- }
49
-
50
- .google-btn {
51
- display: flex; align-items: center; justify-content: center; gap: 10px;
52
- width: 100%; padding: 11px 20px;
53
- background: var(--bg); color: var(--text);
54
- border: 1px solid var(--border); border-radius: 8px;
55
- font-size: 14px; font-weight: 600;
56
- text-decoration: none; cursor: pointer;
57
- transition: background 0.15s, border-color 0.15s;
58
- }
59
- .google-btn:hover { background: var(--bg-secondary); border-color: var(--accent); }
60
-
61
- .divider { display: flex; align-items: center; gap: 12px; margin: 20px 0; color: var(--text-tertiary); font-size: 12px; }
62
- .divider::before, .divider::after { content: ''; flex: 1; height: 1px; background: var(--border); }
63
-
64
- .terms { font-size: 12px; color: var(--text-tertiary); margin-top: 20px; line-height: 1.5; }
65
- `;
66
-
67
- render() {
68
- const { error, returnTo } = this.loaderData;
69
- const loginUrl = `/__nk_auth/login/google?returnTo=${encodeURIComponent(returnTo ?? '/')}`;
70
- const errorMsg = error === 'access_denied' ? 'Access was denied. Please try again.'
71
- : error === 'state_mismatch' ? 'Login session expired. Please try again.'
72
- : error ? 'Authentication failed. Please try again.'
73
- : null;
74
-
75
- return html`
76
- <div class="card">
77
- <div class="logo">N</div>
78
- <h1>Sign in</h1>
79
- <p>Welcome back — sign in to continue</p>
80
-
81
- ${errorMsg ? html`<div class="error">${errorMsg}</div>` : ''}
82
-
83
- <a class="google-btn" href="${loginUrl}">
84
- ${googleLogo}
85
- Continue with Google
86
- </a>
87
-
88
- <p class="terms">By signing in you agree to our Terms of Service and Privacy Policy.</p>
89
- </div>
90
- `;
91
- }
92
- }
@@ -1,57 +0,0 @@
1
- import { LitElement, html, css } from 'lit';
2
-
3
- const svg = {
4
- bookmark: html`<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" stroke="none"><path d="M19 21l-7-5-7 5V5a2 2 0 012-2h10a2 2 0 012 2z"/></svg>`,
5
- };
6
-
7
- export async function loader() {
8
- return {
9
- bookmarks: [
10
- { id: 1, username: 'aymen', display_name: 'Aymen Labidi', initials: 'AL', color: '#7c3aed', title: 'Why file-based routing changes everything', saved: '2 hours ago' },
11
- { id: 7, username: 'emma_data', display_name: 'Emma Williams', initials: 'EW', color: '#3572a5', title: 'Polars vs Pandas: a practical comparison', saved: '1 day ago' },
12
- { id: 4, username: 'mike_ops', display_name: 'Mike Johnson', initials: 'MJ', color: '#22c55e', title: 'Migrating CI/CD to GitHub Actions: a retrospective', saved: '3 days ago' },
13
- ],
14
- };
15
- }
16
-
17
- export class PageBookmarks extends LitElement {
18
- static properties = { loaderData: { type: Object } };
19
- loaderData: any = {};
20
-
21
- static styles = css`
22
- :host { display: block; }
23
- .card { background: var(--bg); border-radius: 6px; border: 1px solid var(--border); overflow: hidden; }
24
- h2 { font-size: 20px; font-weight: 700; padding: 16px 20px; margin: 0; border-bottom: 1px solid var(--border-light); }
25
- .item { display: flex; gap: 10px; padding: 12px 20px; border-bottom: 1px solid var(--border-light); cursor: pointer; }
26
- .item:hover { background: var(--bg-hover); }
27
- .item:last-child { border-bottom: none; }
28
- .item-icon { width: 36px; height: 36px; border-radius: 8px; background: var(--bg-secondary); display: flex; align-items: center; justify-content: center; color: var(--accent); flex-shrink: 0; }
29
- .item-body { flex: 1; }
30
- .item-title { font-size: 15px; font-weight: 600; }
31
- .item-title a { color: var(--text); text-decoration: none; }
32
- .item-title a:hover { color: var(--accent); }
33
- .item-meta { font-size: 12px; color: var(--text-secondary); margin-top: 2px; }
34
- .empty { padding: 48px 20px; text-align: center; color: var(--text-secondary); font-size: 14px; }
35
- `;
36
-
37
- render() {
38
- const bookmarks = this.loaderData.bookmarks || [];
39
- return html`
40
- <div class="card">
41
- <h2>Bookmarks</h2>
42
- ${bookmarks.length === 0
43
- ? html`<div class="empty">No bookmarks yet</div>`
44
- : bookmarks.map((b: any) => html`
45
- <div class="item">
46
- <div class="item-icon">${svg.bookmark}</div>
47
- <div class="item-body">
48
- <div class="item-title"><a href="/post/${b.id}">${b.title}</a></div>
49
- <div class="item-meta">${b.display_name} · Saved ${b.saved}</div>
50
- </div>
51
- </div>
52
- `)
53
- }
54
- </div>
55
- `;
56
- }
57
- }
@@ -1,73 +0,0 @@
1
- import { LitElement, html, css } from 'lit';
2
-
3
- export async function loader() {
4
- return {
5
- tags: [
6
- { name: 'webcomponents', count: 1250, color: '#3b49df' },
7
- { name: 'typescript', count: 3400, color: '#3178c6' },
8
- { name: 'devops', count: 890, color: '#e44d26' },
9
- { name: 'machinelearning', count: 2100, color: '#f7df1e' },
10
- { name: 'opensource', count: 1800, color: '#22c55e' },
11
- { name: 'css', count: 4200, color: '#a855f7' },
12
- { name: 'python', count: 5100, color: '#3572a5' },
13
- { name: 'beginners', count: 6300, color: '#ef4444' },
14
- ],
15
- topPosts: [
16
- { id: 9, display_name: 'Aymen Labidi', title: 'Building a commit message generator with Claude', likes: 112, comments: 18, time: '4 days ago' },
17
- { id: 7, display_name: 'Emma Williams', title: 'Polars vs Pandas: a practical comparison', likes: 93, comments: 15, time: '3 days ago' },
18
- { id: 5, display_name: 'Aymen Labidi', title: 'TypeScript\'s type system is secretly a language', likes: 85, comments: 12, time: '2 days ago' },
19
- ],
20
- };
21
- }
22
-
23
- export class PageExplore extends LitElement {
24
- static properties = { loaderData: { type: Object } };
25
- loaderData: any = {};
26
-
27
- static styles = css`
28
- :host { display: block; }
29
- .card { background: var(--bg); border-radius: 6px; border: 1px solid var(--border); padding: 20px; margin-bottom: 12px; }
30
- h2 { font-size: 20px; font-weight: 700; margin: 0 0 16px; }
31
-
32
- .tags-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 8px; }
33
- .tag-card { border: 1px solid var(--border); border-radius: 6px; padding: 12px 16px; cursor: pointer; transition: all 0.15s; }
34
- .tag-card:hover { border-color: #d0d0d0; box-shadow: 0 2px 4px rgba(0,0,0,0.04); }
35
- .tag-top { width: 100%; height: 6px; border-radius: 3px; margin-bottom: 8px; }
36
- .tag-name { font-size: 16px; font-weight: 600; }
37
- .tag-count { font-size: 12px; color: var(--text-secondary); margin-top: 2px; }
38
-
39
- .top-post { padding: 10px 0; border-bottom: 1px solid var(--border-light); }
40
- .top-post:last-child { border-bottom: none; }
41
- .top-title { font-size: 15px; font-weight: 600; }
42
- .top-title a { color: var(--text); text-decoration: none; }
43
- .top-title a:hover { color: var(--accent); }
44
- .top-meta { font-size: 12px; color: var(--text-secondary); margin-top: 4px; }
45
- `;
46
-
47
- render() {
48
- const { tags, topPosts } = this.loaderData;
49
- return html`
50
- <div class="card">
51
- <h2>Popular Tags</h2>
52
- <div class="tags-grid">
53
- ${(tags || []).map((t: any) => html`
54
- <div class="tag-card">
55
- <div class="tag-top" style="background:${t.color}"></div>
56
- <div class="tag-name">#${t.name}</div>
57
- <div class="tag-count">${t.count.toLocaleString()} posts published</div>
58
- </div>
59
- `)}
60
- </div>
61
- </div>
62
- <div class="card">
63
- <h2>Top Posts This Week</h2>
64
- ${(topPosts || []).map((p: any) => html`
65
- <div class="top-post">
66
- <div class="top-title"><a href="/post/${p.id}">${p.title}</a></div>
67
- <div class="top-meta">${p.display_name} · ${p.likes} reactions · ${p.comments} comments · ${p.time}</div>
68
- </div>
69
- `)}
70
- </div>
71
- `;
72
- }
73
- }