@lumerahq/cli 0.9.3 → 0.9.4
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/README.md +8 -8
- package/dist/index.js +1 -1
- package/dist/{init-LVO3ZMG7.js → init-EDSRR3YM.js} +9 -0
- package/package.json +1 -1
- package/templates/default/ARCHITECTURE.md +80 -0
- package/templates/default/CLAUDE.md +13 -13
- package/templates/default/README.md +5 -5
- package/templates/default/biome.json +5 -0
- package/templates/default/package.json.hbs +5 -4
- package/templates/default/platform/collections/example_items.json +1 -3
- package/templates/default/scripts/seed-demo.py +1 -1
- package/templates/default/src/components/Sidebar.tsx +3 -5
- package/templates/default/src/components/StatCard.tsx +2 -8
- package/templates/default/src/lib/queries.ts +1 -1
- package/templates/default/src/main.tsx +4 -10
- package/templates/default/src/routes/__root.tsx +1 -1
- package/templates/default/src/routes/index.tsx +3 -5
- package/templates/default/src/routes/settings.tsx +2 -6
- package/templates/default/src/styles.css +6 -2
- package/templates/default/vite.config.ts +3 -2
package/README.md
CHANGED
|
@@ -19,14 +19,14 @@ lumera logout # Clear stored credentials
|
|
|
19
19
|
lumera whoami # Show current user
|
|
20
20
|
lumera status # Show project info
|
|
21
21
|
|
|
22
|
-
lumera
|
|
23
|
-
lumera app
|
|
24
|
-
lumera app
|
|
22
|
+
lumera dev # Start dev server
|
|
23
|
+
lumera apply app # Deploy frontend
|
|
24
|
+
lumera destroy app # Delete app from Lumera
|
|
25
25
|
|
|
26
|
-
lumera
|
|
27
|
-
lumera
|
|
28
|
-
lumera
|
|
29
|
-
lumera
|
|
26
|
+
lumera plan # Preview infrastructure changes
|
|
27
|
+
lumera apply # Apply collections, automations, hooks
|
|
28
|
+
lumera pull # Pull remote state to local
|
|
29
|
+
lumera destroy # Delete remote resources
|
|
30
30
|
|
|
31
31
|
lumera run <script> # Run Python scripts locally
|
|
32
32
|
```
|
|
@@ -84,7 +84,7 @@ For automated environments, use the `LUMERA_TOKEN` environment variable:
|
|
|
84
84
|
|
|
85
85
|
```bash
|
|
86
86
|
export LUMERA_TOKEN=your_api_token
|
|
87
|
-
lumera app
|
|
87
|
+
lumera apply app
|
|
88
88
|
```
|
|
89
89
|
|
|
90
90
|
The CLI checks for credentials in this order:
|
package/dist/index.js
CHANGED
|
@@ -118,7 +118,7 @@ async function main() {
|
|
|
118
118
|
break;
|
|
119
119
|
// Project
|
|
120
120
|
case "init":
|
|
121
|
-
await import("./init-
|
|
121
|
+
await import("./init-EDSRR3YM.js").then((m) => m.init(args.slice(1)));
|
|
122
122
|
break;
|
|
123
123
|
case "status":
|
|
124
124
|
await import("./status-E4IHEUKO.js").then((m) => m.status(args.slice(1)));
|
|
@@ -332,6 +332,15 @@ async function init(args) {
|
|
|
332
332
|
console.log(pc.green(" \u2713"), pc.dim(`${installed} Lumera skills installed`));
|
|
333
333
|
}
|
|
334
334
|
syncClaudeMd(targetDir);
|
|
335
|
+
if (isGitInstalled()) {
|
|
336
|
+
try {
|
|
337
|
+
execSync('git add -A && git commit -m "chore: install lumera skills"', {
|
|
338
|
+
cwd: targetDir,
|
|
339
|
+
stdio: "ignore"
|
|
340
|
+
});
|
|
341
|
+
} catch {
|
|
342
|
+
}
|
|
343
|
+
}
|
|
335
344
|
} catch (err) {
|
|
336
345
|
console.log(pc.yellow(" \u26A0"), pc.dim(`Failed to install skills: ${err}`));
|
|
337
346
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# {{projectTitle}} — Architecture
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
{{projectTitle}} is a Lumera embedded app — a React frontend served inside the Lumera platform iframe, backed by collections, hooks, and automations managed through the Lumera CLI.
|
|
6
|
+
|
|
7
|
+
## System Diagram
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
┌─────────────────────────────────────────────────┐
|
|
11
|
+
│ Lumera Platform │
|
|
12
|
+
│ │
|
|
13
|
+
│ ┌───────────┐ postMessage ┌────────────┐ │
|
|
14
|
+
│ │ Host UI │ ◄──────────────► │ App │ │
|
|
15
|
+
│ │ │ (auth, init) │ (iframe) │ │
|
|
16
|
+
│ └─────┬─────┘ └─────┬──────┘ │
|
|
17
|
+
│ │ │ │
|
|
18
|
+
│ │ REST API │ │
|
|
19
|
+
│ ▼ ▼ │
|
|
20
|
+
│ ┌──────────────────────────────────────────┐ │
|
|
21
|
+
│ │ Lumera API │ │
|
|
22
|
+
│ │ - Collections (CRUD, SQL, search) │ │
|
|
23
|
+
│ │ - Automations (run, poll, cancel) │ │
|
|
24
|
+
│ │ - File storage (upload, download) │ │
|
|
25
|
+
│ └──────────────┬───────────────────────────┘ │
|
|
26
|
+
│ │ │
|
|
27
|
+
│ ▼ │
|
|
28
|
+
│ ┌──────────────────────────────────────────┐ │
|
|
29
|
+
│ │ Tenant Database (PocketBase/SQLite) │ │
|
|
30
|
+
│ │ - example_items │ │
|
|
31
|
+
│ │ - (add your collections here) │ │
|
|
32
|
+
│ └──────────────────────────────────────────┘ │
|
|
33
|
+
└─────────────────────────────────────────────────┘
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Frontend (`src/`)
|
|
37
|
+
|
|
38
|
+
React app using TanStack Router (file-based routing) and TanStack Query for data fetching. Embedded in Lumera via iframe with postMessage bridge for authentication.
|
|
39
|
+
|
|
40
|
+
| Directory | Purpose |
|
|
41
|
+
|------------------|--------------------------------------|
|
|
42
|
+
| `src/routes/` | Pages — file names map to URL paths |
|
|
43
|
+
| `src/components/`| Shared React components |
|
|
44
|
+
| `src/lib/` | API helpers, query functions |
|
|
45
|
+
| `src/main.tsx` | App entry — auth bridge, router init |
|
|
46
|
+
|
|
47
|
+
**Key patterns:**
|
|
48
|
+
- Auth context flows from `main.tsx` via `AuthContext`
|
|
49
|
+
- Data fetching uses `pbList`, `pbSql` from `@lumerahq/ui/lib`
|
|
50
|
+
- Styling via Tailwind CSS 4 with theme tokens in `styles.css`
|
|
51
|
+
|
|
52
|
+
## Platform Resources (`platform/`)
|
|
53
|
+
|
|
54
|
+
Declarative definitions deployed via `lumera apply`.
|
|
55
|
+
|
|
56
|
+
| Directory | Purpose |
|
|
57
|
+
|--------------------------|----------------------------------|
|
|
58
|
+
| `platform/collections/` | Collection schemas (JSON) |
|
|
59
|
+
| `platform/automations/` | Background Python scripts |
|
|
60
|
+
| `platform/hooks/` | Server-side JS on collection events |
|
|
61
|
+
|
|
62
|
+
## Scripts (`scripts/`)
|
|
63
|
+
|
|
64
|
+
Local Python scripts run via `lumera run`. Used for seeding data, migrations, and ad-hoc operations. All scripts should be idempotent.
|
|
65
|
+
|
|
66
|
+
## Data Flow
|
|
67
|
+
|
|
68
|
+
1. **User opens app** → Lumera host sends auth payload via postMessage
|
|
69
|
+
2. **App authenticates** → Stores session token in `AuthContext`
|
|
70
|
+
3. **App fetches data** → Calls Lumera API via `@lumerahq/ui/lib` helpers
|
|
71
|
+
4. **Data mutations** → API calls trigger collection hooks if configured
|
|
72
|
+
5. **Background work** → Automations run async via `createRun` / `pollRun`
|
|
73
|
+
|
|
74
|
+
## Collections
|
|
75
|
+
|
|
76
|
+
| Collection | Purpose |
|
|
77
|
+
|------------------|----------------------------|
|
|
78
|
+
| `example_items` | Starter collection (replace with your own) |
|
|
79
|
+
|
|
80
|
+
_Update this table as you add collections._
|
|
@@ -33,9 +33,9 @@ pnpm dev # Start dev server
|
|
|
33
33
|
pnpm deploy # Deploy frontend
|
|
34
34
|
|
|
35
35
|
# All other commands
|
|
36
|
-
pnpm dlx @lumerahq/cli
|
|
37
|
-
pnpm dlx @lumerahq/cli
|
|
38
|
-
pnpm dlx @lumerahq/cli
|
|
36
|
+
pnpm dlx @lumerahq/cli plan
|
|
37
|
+
pnpm dlx @lumerahq/cli apply
|
|
38
|
+
pnpm dlx @lumerahq/cli destroy
|
|
39
39
|
pnpm dlx @lumerahq/cli run scripts/seed-demo.py
|
|
40
40
|
pnpm dlx @lumerahq/cli status
|
|
41
41
|
```
|
|
@@ -50,10 +50,10 @@ lumera login
|
|
|
50
50
|
pnpm dev
|
|
51
51
|
|
|
52
52
|
# With custom port
|
|
53
|
-
lumera
|
|
53
|
+
lumera dev --port 3000
|
|
54
54
|
|
|
55
55
|
# With ngrok tunnel
|
|
56
|
-
lumera
|
|
56
|
+
lumera dev --url https://my-tunnel.ngrok.io
|
|
57
57
|
|
|
58
58
|
# Plain vite (no Lumera registration)
|
|
59
59
|
pnpm dev:vite
|
|
@@ -71,21 +71,21 @@ pnpm lint
|
|
|
71
71
|
# Format code
|
|
72
72
|
pnpm format
|
|
73
73
|
|
|
74
|
-
# Run all checks (lint + typecheck) - use in CI
|
|
74
|
+
# Run all checks (lint + format + typecheck) - use in CI
|
|
75
75
|
pnpm check:ci
|
|
76
76
|
```
|
|
77
77
|
|
|
78
78
|
### Deploying
|
|
79
79
|
|
|
80
80
|
```bash
|
|
81
|
-
# Deploy frontend
|
|
82
|
-
lumera app
|
|
81
|
+
# Deploy frontend
|
|
82
|
+
lumera apply app
|
|
83
83
|
|
|
84
|
-
# Apply
|
|
85
|
-
lumera
|
|
84
|
+
# Apply all resources (collections, automations, hooks, app)
|
|
85
|
+
lumera apply
|
|
86
86
|
|
|
87
|
-
# Preview
|
|
88
|
-
lumera
|
|
87
|
+
# Preview changes first
|
|
88
|
+
lumera plan
|
|
89
89
|
```
|
|
90
90
|
|
|
91
91
|
### Running Scripts
|
|
@@ -129,7 +129,7 @@ EOF
|
|
|
129
129
|
|
|
130
130
|
## Important Rules
|
|
131
131
|
|
|
132
|
-
1. **Authenticate first** - Before running any CLI or SDK commands, ensure the user has run `lumera login
|
|
132
|
+
1. **Authenticate first** - Before running any CLI or SDK commands, ensure the user has run `lumera login`. This stores credentials in `.lumera/credentials.json` which the SDK reads automatically.
|
|
133
133
|
|
|
134
134
|
2. **Source of truth is code** - `platform/` contains all schemas, automations, hooks. Update local code first, then deploy.
|
|
135
135
|
|
|
@@ -23,13 +23,13 @@ Lumera custom embedded app.
|
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
25
|
# Development
|
|
26
|
-
lumera
|
|
27
|
-
lumera
|
|
26
|
+
lumera dev # Start dev server
|
|
27
|
+
lumera dev --port 3000 # Custom port
|
|
28
28
|
|
|
29
29
|
# Deployment
|
|
30
|
-
lumera app
|
|
31
|
-
lumera
|
|
32
|
-
lumera
|
|
30
|
+
lumera apply app # Build and deploy frontend
|
|
31
|
+
lumera apply # Apply all resources
|
|
32
|
+
lumera plan # Preview changes
|
|
33
33
|
|
|
34
34
|
# Scripts
|
|
35
35
|
lumera run scripts/seed-demo.py # Run seed script
|
|
@@ -12,16 +12,16 @@
|
|
|
12
12
|
"name": "{{projectTitle}}"
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
|
-
"dev": "pnpm dlx @lumerahq/cli
|
|
16
|
-
"deploy": "pnpm dlx @lumerahq/cli app
|
|
15
|
+
"dev": "pnpm dlx @lumerahq/cli dev",
|
|
16
|
+
"deploy": "pnpm dlx @lumerahq/cli apply app",
|
|
17
17
|
"dev:vite": "vite",
|
|
18
18
|
"build": "vite build && tsc",
|
|
19
19
|
"preview": "vite preview",
|
|
20
|
-
"typecheck": "tsc --noEmit",
|
|
20
|
+
"typecheck": "tsr generate && tsc --noEmit",
|
|
21
21
|
"lint": "biome lint --write .",
|
|
22
22
|
"format": "biome format --write .",
|
|
23
23
|
"check": "biome check --write .",
|
|
24
|
-
"check:ci": "biome check . && tsc --noEmit"
|
|
24
|
+
"check:ci": "biome check . && tsr generate && tsc --noEmit"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@lumerahq/ui": "^0.5.0",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@biomejs/biome": "^2.0.0",
|
|
39
39
|
"@tailwindcss/vite": "^4.0.6",
|
|
40
|
+
"@tanstack/router-cli": "1.155.0",
|
|
40
41
|
"@types/react": "^19.2.0",
|
|
41
42
|
"@types/react-dom": "^19.2.0",
|
|
42
43
|
"@vitejs/plugin-react": "^5.0.4",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { cn } from '@lumerahq/ui/lib';
|
|
1
2
|
import { Link, useRouterState } from '@tanstack/react-router';
|
|
2
|
-
import {
|
|
3
|
+
import { ChevronLeft, ChevronRight, LayoutDashboard, Settings } from 'lucide-react';
|
|
3
4
|
import { useState } from 'react';
|
|
4
|
-
import { cn } from '@lumerahq/ui/lib';
|
|
5
5
|
|
|
6
6
|
type NavItem = {
|
|
7
7
|
to: string;
|
|
@@ -37,9 +37,7 @@ export function Sidebar() {
|
|
|
37
37
|
<div className="size-8 rounded-lg bg-primary flex items-center justify-center text-primary-foreground font-bold text-sm">
|
|
38
38
|
{{projectInitial}}
|
|
39
39
|
</div>
|
|
40
|
-
{!collapsed &&
|
|
41
|
-
<span className="font-semibold text-sm">{{projectTitle}}</span>
|
|
42
|
-
)}
|
|
40
|
+
{!collapsed && <span className="font-semibold text-sm">{{projectTitle}}</span>}
|
|
43
41
|
</Link>
|
|
44
42
|
</div>
|
|
45
43
|
|
|
@@ -16,15 +16,9 @@ export function StatCard({ title, value, subtitle, icon, className }: StatCardPr
|
|
|
16
16
|
<div className="space-y-1">
|
|
17
17
|
<p className="text-sm font-medium text-muted-foreground">{title}</p>
|
|
18
18
|
<p className="text-2xl font-semibold tracking-tight">{value}</p>
|
|
19
|
-
{subtitle &&
|
|
20
|
-
<p className="text-sm text-muted-foreground">{subtitle}</p>
|
|
21
|
-
)}
|
|
19
|
+
{subtitle && <p className="text-sm text-muted-foreground">{subtitle}</p>}
|
|
22
20
|
</div>
|
|
23
|
-
{icon &&
|
|
24
|
-
<div className="rounded-lg bg-muted p-2.5 text-muted-foreground">
|
|
25
|
-
{icon}
|
|
26
|
-
</div>
|
|
27
|
-
)}
|
|
21
|
+
{icon && <div className="rounded-lg bg-muted p-2.5 text-muted-foreground">{icon}</div>}
|
|
28
22
|
</div>
|
|
29
23
|
</div>
|
|
30
24
|
);
|
|
@@ -1,16 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import ReactDOM from 'react-dom/client';
|
|
1
|
+
import { type HostPayload, isEmbedded, onInitMessage, postReadyMessage } from '@lumerahq/ui/lib';
|
|
3
2
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
4
|
-
import {
|
|
3
|
+
import { createHashHistory, createRouter, RouterProvider } from '@tanstack/react-router';
|
|
4
|
+
import { createContext, StrictMode, useEffect, useRef, useState } from 'react';
|
|
5
|
+
import ReactDOM from 'react-dom/client';
|
|
5
6
|
import { Toaster } from 'sonner';
|
|
6
7
|
|
|
7
|
-
import {
|
|
8
|
-
isEmbedded,
|
|
9
|
-
onInitMessage,
|
|
10
|
-
postReadyMessage,
|
|
11
|
-
type HostPayload,
|
|
12
|
-
} from '@lumerahq/ui/lib';
|
|
13
|
-
|
|
14
8
|
import { routeTree } from './routeTree.gen';
|
|
15
9
|
import '@lumerahq/ui/styles.css';
|
|
16
10
|
import './styles.css';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createFileRoute } from '@tanstack/react-router';
|
|
2
|
+
import { Activity, FileText, TrendingUp, Users } from 'lucide-react';
|
|
2
3
|
import { useContext } from 'react';
|
|
3
|
-
import { Users, FileText, Activity, TrendingUp } from 'lucide-react';
|
|
4
|
-
import { AuthContext } from '../main';
|
|
5
4
|
import { StatCard } from '../components/StatCard';
|
|
5
|
+
import { AuthContext } from '../main';
|
|
6
6
|
|
|
7
7
|
export const Route = createFileRoute('/')({
|
|
8
8
|
component: HomePage,
|
|
@@ -16,9 +16,7 @@ function HomePage() {
|
|
|
16
16
|
{/* Header */}
|
|
17
17
|
<div>
|
|
18
18
|
<h1 className="text-2xl font-semibold">Dashboard</h1>
|
|
19
|
-
<p className="text-muted-foreground mt-1">
|
|
20
|
-
Welcome back, {auth?.user?.name ?? 'User'}
|
|
21
|
-
</p>
|
|
19
|
+
<p className="text-muted-foreground mt-1">Welcome back, {auth?.user?.name ?? 'User'}</p>
|
|
22
20
|
</div>
|
|
23
21
|
|
|
24
22
|
{/* Stats Grid */}
|
|
@@ -9,16 +9,12 @@ function SettingsPage() {
|
|
|
9
9
|
<div className="space-y-6">
|
|
10
10
|
<div>
|
|
11
11
|
<h1 className="text-2xl font-semibold">Settings</h1>
|
|
12
|
-
<p className="text-muted-foreground mt-1">
|
|
13
|
-
Manage your application settings
|
|
14
|
-
</p>
|
|
12
|
+
<p className="text-muted-foreground mt-1">Manage your application settings</p>
|
|
15
13
|
</div>
|
|
16
14
|
|
|
17
15
|
<div className="rounded-xl border bg-card p-6">
|
|
18
16
|
<h2 className="font-semibold mb-4">General</h2>
|
|
19
|
-
<p className="text-sm text-muted-foreground">
|
|
20
|
-
Add your settings UI here
|
|
21
|
-
</p>
|
|
17
|
+
<p className="text-sm text-muted-foreground">Add your settings UI here</p>
|
|
22
18
|
</div>
|
|
23
19
|
</div>
|
|
24
20
|
);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { defineConfig } from 'vite';
|
|
2
|
-
import viteReact from '@vitejs/plugin-react';
|
|
3
1
|
import tailwindcss from '@tailwindcss/vite';
|
|
4
2
|
import { tanstackRouter } from '@tanstack/router-plugin/vite';
|
|
3
|
+
import viteReact from '@vitejs/plugin-react';
|
|
4
|
+
import { defineConfig } from 'vite';
|
|
5
5
|
|
|
6
6
|
export default defineConfig({
|
|
7
7
|
base: './', // Use relative paths for S3 hosting at subpaths
|
|
@@ -22,6 +22,7 @@ export default defineConfig({
|
|
|
22
22
|
server: {
|
|
23
23
|
allowedHosts: [
|
|
24
24
|
'mac.lumerahq.com',
|
|
25
|
+
'untunable-del-nonephemerally.ngrok-free.dev',
|
|
25
26
|
],
|
|
26
27
|
},
|
|
27
28
|
});
|