@lumerahq/cli 0.7.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/README.md +118 -0
- package/dist/auth-7RGL7GXU.js +311 -0
- package/dist/chunk-2CR762KB.js +18 -0
- package/dist/chunk-AVKPM7C4.js +199 -0
- package/dist/chunk-D2BLSEGR.js +59 -0
- package/dist/chunk-NDLYGKS6.js +77 -0
- package/dist/chunk-V2XXMMEI.js +147 -0
- package/dist/dev-UTZC4ZJ7.js +87 -0
- package/dist/index.js +157 -0
- package/dist/init-OQCIET53.js +363 -0
- package/dist/migrate-2DZ6RQ5K.js +190 -0
- package/dist/resources-PNK3NESI.js +1350 -0
- package/dist/run-4NDI2CN4.js +257 -0
- package/dist/skills-56EUKHGY.js +414 -0
- package/dist/status-BEVUV6RY.js +131 -0
- package/package.json +37 -0
- package/templates/default/CLAUDE.md +245 -0
- package/templates/default/README.md +59 -0
- package/templates/default/biome.json +33 -0
- package/templates/default/index.html +13 -0
- package/templates/default/package.json.hbs +46 -0
- package/templates/default/platform/automations/.gitkeep +0 -0
- package/templates/default/platform/collections/example_items.json +28 -0
- package/templates/default/platform/hooks/.gitkeep +0 -0
- package/templates/default/pyproject.toml.hbs +14 -0
- package/templates/default/scripts/seed-demo.py +35 -0
- package/templates/default/src/components/Sidebar.tsx +84 -0
- package/templates/default/src/components/StatCard.tsx +31 -0
- package/templates/default/src/components/layout.tsx +13 -0
- package/templates/default/src/lib/queries.ts +27 -0
- package/templates/default/src/main.tsx +137 -0
- package/templates/default/src/routes/__root.tsx +10 -0
- package/templates/default/src/routes/index.tsx +90 -0
- package/templates/default/src/routes/settings.tsx +25 -0
- package/templates/default/src/styles.css +40 -0
- package/templates/default/tsconfig.json +23 -0
- package/templates/default/vite.config.ts +27 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// src/lib/auth.ts
|
|
2
|
+
import { existsSync, readFileSync } from "fs";
|
|
3
|
+
import { homedir } from "os";
|
|
4
|
+
import { join } from "path";
|
|
5
|
+
var GLOBAL_CONFIG_DIR = join(homedir(), ".config", "lumera");
|
|
6
|
+
var GLOBAL_CREDS_PATH = join(GLOBAL_CONFIG_DIR, "credentials.json");
|
|
7
|
+
function getLocalCredsPath(cwd = process.cwd()) {
|
|
8
|
+
return join(cwd, ".lumera", "credentials.json");
|
|
9
|
+
}
|
|
10
|
+
function getToken(cwd = process.cwd()) {
|
|
11
|
+
if (process.env.LUMERA_TOKEN) {
|
|
12
|
+
return process.env.LUMERA_TOKEN;
|
|
13
|
+
}
|
|
14
|
+
const localCredsPath = getLocalCredsPath(cwd);
|
|
15
|
+
if (existsSync(localCredsPath)) {
|
|
16
|
+
try {
|
|
17
|
+
const creds = JSON.parse(readFileSync(localCredsPath, "utf-8"));
|
|
18
|
+
if (creds.token) return creds.token;
|
|
19
|
+
} catch {
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (existsSync(GLOBAL_CREDS_PATH)) {
|
|
23
|
+
try {
|
|
24
|
+
const creds = JSON.parse(readFileSync(GLOBAL_CREDS_PATH, "utf-8"));
|
|
25
|
+
if (creds.token) return creds.token;
|
|
26
|
+
} catch {
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
throw new Error(
|
|
30
|
+
"No Lumera token found.\n Run `lumera login` to authenticate, or\n Set LUMERA_TOKEN environment variable"
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
function getTokenSource(cwd = process.cwd()) {
|
|
34
|
+
if (process.env.LUMERA_TOKEN) {
|
|
35
|
+
return "environment (LUMERA_TOKEN)";
|
|
36
|
+
}
|
|
37
|
+
const localCredsPath = getLocalCredsPath(cwd);
|
|
38
|
+
if (existsSync(localCredsPath)) {
|
|
39
|
+
try {
|
|
40
|
+
const creds = JSON.parse(readFileSync(localCredsPath, "utf-8"));
|
|
41
|
+
if (creds.token) return `project (${localCredsPath})`;
|
|
42
|
+
} catch {
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (existsSync(GLOBAL_CREDS_PATH)) {
|
|
46
|
+
try {
|
|
47
|
+
const creds = JSON.parse(readFileSync(GLOBAL_CREDS_PATH, "utf-8"));
|
|
48
|
+
if (creds.token) return `global (${GLOBAL_CREDS_PATH})`;
|
|
49
|
+
} catch {
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
function getCredentials(cwd = process.cwd()) {
|
|
55
|
+
const localCredsPath = getLocalCredsPath(cwd);
|
|
56
|
+
if (existsSync(localCredsPath)) {
|
|
57
|
+
try {
|
|
58
|
+
const creds = JSON.parse(readFileSync(localCredsPath, "utf-8"));
|
|
59
|
+
if (creds.token) return creds;
|
|
60
|
+
} catch {
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (existsSync(GLOBAL_CREDS_PATH)) {
|
|
64
|
+
try {
|
|
65
|
+
const creds = JSON.parse(readFileSync(GLOBAL_CREDS_PATH, "utf-8"));
|
|
66
|
+
if (creds.token) return creds;
|
|
67
|
+
} catch {
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export {
|
|
74
|
+
getToken,
|
|
75
|
+
getTokenSource,
|
|
76
|
+
getCredentials
|
|
77
|
+
};
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getToken
|
|
3
|
+
} from "./chunk-NDLYGKS6.js";
|
|
4
|
+
|
|
5
|
+
// src/lib/api.ts
|
|
6
|
+
var ApiClient = class {
|
|
7
|
+
baseUrl;
|
|
8
|
+
token;
|
|
9
|
+
constructor(token, baseUrl) {
|
|
10
|
+
this.token = token || getToken();
|
|
11
|
+
let base = baseUrl || process.env.LUMERA_BASE_URL || "https://app.lumerahq.com";
|
|
12
|
+
base = base.replace(/\/$/, "");
|
|
13
|
+
if (base.endsWith("/api")) {
|
|
14
|
+
base = base.slice(0, -4);
|
|
15
|
+
}
|
|
16
|
+
this.baseUrl = base.replace(/\/$/, "");
|
|
17
|
+
}
|
|
18
|
+
async request(path, options = {}) {
|
|
19
|
+
const url = `${this.baseUrl}${path}`;
|
|
20
|
+
const headers = {
|
|
21
|
+
"Content-Type": "application/json",
|
|
22
|
+
Authorization: `Bearer ${this.token}`,
|
|
23
|
+
...options.headers
|
|
24
|
+
};
|
|
25
|
+
const response = await fetch(url, {
|
|
26
|
+
...options,
|
|
27
|
+
headers
|
|
28
|
+
});
|
|
29
|
+
if (!response.ok) {
|
|
30
|
+
const text = await response.text();
|
|
31
|
+
throw new Error(`API request failed: ${response.status} ${text}`);
|
|
32
|
+
}
|
|
33
|
+
if (response.status === 204) {
|
|
34
|
+
return {};
|
|
35
|
+
}
|
|
36
|
+
return response.json();
|
|
37
|
+
}
|
|
38
|
+
// Collections
|
|
39
|
+
async listCollections() {
|
|
40
|
+
const result = await this.request("/api/pb/collections");
|
|
41
|
+
return result.items;
|
|
42
|
+
}
|
|
43
|
+
async getCollection(id) {
|
|
44
|
+
return this.request(`/api/pb/collections/${id}`);
|
|
45
|
+
}
|
|
46
|
+
async ensureCollection(name, def) {
|
|
47
|
+
return this.request(`/api/pb/collections/${name}`, {
|
|
48
|
+
method: "PUT",
|
|
49
|
+
body: JSON.stringify(def)
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
async deleteCollection(id) {
|
|
53
|
+
await this.request(`/api/pb/collections/${id}`, {
|
|
54
|
+
method: "DELETE"
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
// Automations
|
|
58
|
+
async listAutomations(params) {
|
|
59
|
+
let path = "/api/automations";
|
|
60
|
+
if (params?.external_id) {
|
|
61
|
+
path += `?external_id=${encodeURIComponent(params.external_id)}`;
|
|
62
|
+
}
|
|
63
|
+
const result = await this.request(path);
|
|
64
|
+
return result.automations || [];
|
|
65
|
+
}
|
|
66
|
+
async getAutomation(id) {
|
|
67
|
+
return this.request(`/api/automations/${id}`);
|
|
68
|
+
}
|
|
69
|
+
async createAutomation(def) {
|
|
70
|
+
return this.request("/api/automations", {
|
|
71
|
+
method: "POST",
|
|
72
|
+
body: JSON.stringify(def)
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
async updateAutomation(id, def) {
|
|
76
|
+
return this.request(`/api/automations/${id}`, {
|
|
77
|
+
method: "PATCH",
|
|
78
|
+
body: JSON.stringify(def)
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
async deleteAutomation(id) {
|
|
82
|
+
await this.request(`/api/automations/${id}`, {
|
|
83
|
+
method: "DELETE"
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
// Automation Presets
|
|
87
|
+
async listPresets(automationId) {
|
|
88
|
+
const result = await this.request(
|
|
89
|
+
`/api/automations/${automationId}/presets`
|
|
90
|
+
);
|
|
91
|
+
return result.presets || [];
|
|
92
|
+
}
|
|
93
|
+
async createPreset(automationId, def) {
|
|
94
|
+
return this.request(`/api/automations/${automationId}/presets`, {
|
|
95
|
+
method: "POST",
|
|
96
|
+
body: JSON.stringify(def)
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
async updatePreset(presetId, def) {
|
|
100
|
+
return this.request(`/api/automation-presets/${presetId}`, {
|
|
101
|
+
method: "PATCH",
|
|
102
|
+
body: JSON.stringify(def)
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
async deletePreset(presetId) {
|
|
106
|
+
await this.request(`/api/automation-presets/${presetId}`, {
|
|
107
|
+
method: "DELETE"
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
// Hooks
|
|
111
|
+
async listHooks(params) {
|
|
112
|
+
const query = new URLSearchParams();
|
|
113
|
+
if (params?.collection_id) query.set("collection_id", params.collection_id);
|
|
114
|
+
if (params?.external_id) query.set("external_id", params.external_id);
|
|
115
|
+
const queryString = query.toString();
|
|
116
|
+
const path = queryString ? `/api/pb/hooks?${queryString}` : "/api/pb/hooks";
|
|
117
|
+
const result = await this.request(path);
|
|
118
|
+
return result.items || [];
|
|
119
|
+
}
|
|
120
|
+
async getHook(id) {
|
|
121
|
+
return this.request(`/api/pb/hooks/${id}`);
|
|
122
|
+
}
|
|
123
|
+
async createHook(def) {
|
|
124
|
+
return this.request("/api/pb/hooks", {
|
|
125
|
+
method: "POST",
|
|
126
|
+
body: JSON.stringify(def)
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
async updateHook(id, def) {
|
|
130
|
+
return this.request(`/api/pb/hooks/${id}`, {
|
|
131
|
+
method: "PATCH",
|
|
132
|
+
body: JSON.stringify(def)
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
async deleteHook(id) {
|
|
136
|
+
await this.request(`/api/pb/hooks/${id}`, {
|
|
137
|
+
method: "DELETE"
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
function createApiClient(token, baseUrl) {
|
|
142
|
+
return new ApiClient(token, baseUrl);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export {
|
|
146
|
+
createApiClient
|
|
147
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import {
|
|
2
|
+
dev
|
|
3
|
+
} from "./chunk-AVKPM7C4.js";
|
|
4
|
+
import {
|
|
5
|
+
loadEnv
|
|
6
|
+
} from "./chunk-2CR762KB.js";
|
|
7
|
+
import {
|
|
8
|
+
getToken
|
|
9
|
+
} from "./chunk-NDLYGKS6.js";
|
|
10
|
+
import {
|
|
11
|
+
findProjectRoot,
|
|
12
|
+
getApiUrl,
|
|
13
|
+
getAppName,
|
|
14
|
+
getAppTitle
|
|
15
|
+
} from "./chunk-D2BLSEGR.js";
|
|
16
|
+
|
|
17
|
+
// src/commands/dev.ts
|
|
18
|
+
import pc from "picocolors";
|
|
19
|
+
function parseFlags(args) {
|
|
20
|
+
const result = {};
|
|
21
|
+
for (let i = 0; i < args.length; i++) {
|
|
22
|
+
const arg = args[i];
|
|
23
|
+
if (arg.startsWith("--")) {
|
|
24
|
+
const key = arg.slice(2);
|
|
25
|
+
const next = args[i + 1];
|
|
26
|
+
if (next && !next.startsWith("--")) {
|
|
27
|
+
result[key] = next;
|
|
28
|
+
i++;
|
|
29
|
+
} else {
|
|
30
|
+
result[key] = true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
function showHelp() {
|
|
37
|
+
console.log(`
|
|
38
|
+
${pc.dim("Usage:")}
|
|
39
|
+
lumera dev [options]
|
|
40
|
+
|
|
41
|
+
${pc.dim("Description:")}
|
|
42
|
+
Start the development server with Lumera registration.
|
|
43
|
+
Registers your app with Lumera and starts a local dev server.
|
|
44
|
+
|
|
45
|
+
${pc.dim("Options:")}
|
|
46
|
+
--port <number> Dev server port (default: 8080)
|
|
47
|
+
--url <url> App URL for dev mode (default: http://localhost:{port})
|
|
48
|
+
--help, -h Show this help
|
|
49
|
+
|
|
50
|
+
${pc.dim("Environment variables:")}
|
|
51
|
+
LUMERA_TOKEN API token (overrides \`lumera login\`)
|
|
52
|
+
LUMERA_API_URL API base URL (default: https://app.lumerahq.com/api)
|
|
53
|
+
PORT Dev server port (default: 8080)
|
|
54
|
+
APP_URL App URL for dev mode
|
|
55
|
+
|
|
56
|
+
${pc.dim("Examples:")}
|
|
57
|
+
lumera dev # Start dev server on port 8080
|
|
58
|
+
lumera dev --port 3000 # Start dev server on port 3000
|
|
59
|
+
lumera dev --url http://192.168.1.100:8080 # Custom URL for mobile testing
|
|
60
|
+
`);
|
|
61
|
+
}
|
|
62
|
+
async function dev2(args) {
|
|
63
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
64
|
+
showHelp();
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const flags = parseFlags(args);
|
|
68
|
+
const projectRoot = findProjectRoot();
|
|
69
|
+
loadEnv(projectRoot);
|
|
70
|
+
const token = getToken(projectRoot);
|
|
71
|
+
const appName = getAppName(projectRoot);
|
|
72
|
+
const appTitle = getAppTitle(projectRoot);
|
|
73
|
+
const apiUrl = getApiUrl();
|
|
74
|
+
const port = Number(flags.port || process.env.PORT || "8080");
|
|
75
|
+
const appUrl = typeof flags.url === "string" ? flags.url : process.env.APP_URL;
|
|
76
|
+
await dev({
|
|
77
|
+
token,
|
|
78
|
+
appName,
|
|
79
|
+
appTitle,
|
|
80
|
+
port,
|
|
81
|
+
appUrl,
|
|
82
|
+
apiUrl
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
export {
|
|
86
|
+
dev2 as dev
|
|
87
|
+
};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import { readFileSync } from "fs";
|
|
5
|
+
import { dirname, join } from "path";
|
|
6
|
+
import { fileURLToPath } from "url";
|
|
7
|
+
import pc from "picocolors";
|
|
8
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
var pkg = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8"));
|
|
10
|
+
var VERSION = pkg.version;
|
|
11
|
+
var args = process.argv.slice(2);
|
|
12
|
+
var command = args[0];
|
|
13
|
+
var subcommand = args[1];
|
|
14
|
+
function showHelp() {
|
|
15
|
+
console.log(`
|
|
16
|
+
${pc.bold("Lumera CLI")} - Build and deploy Lumera apps
|
|
17
|
+
|
|
18
|
+
${pc.dim("Usage:")}
|
|
19
|
+
lumera <command> [options]
|
|
20
|
+
|
|
21
|
+
${pc.dim("Resource Commands:")}
|
|
22
|
+
${pc.cyan("plan")} [resource] Preview changes
|
|
23
|
+
${pc.cyan("apply")} [resource] Create/update resources
|
|
24
|
+
${pc.cyan("pull")} [resource] Download remote state
|
|
25
|
+
${pc.cyan("destroy")} [resource] Delete resources
|
|
26
|
+
${pc.cyan("list")} [type] List resources with status
|
|
27
|
+
${pc.cyan("show")} <resource> Show resource details
|
|
28
|
+
|
|
29
|
+
${pc.dim("Development:")}
|
|
30
|
+
${pc.cyan("dev")} Start dev server
|
|
31
|
+
${pc.cyan("run")} <target> Run script or trigger automation
|
|
32
|
+
|
|
33
|
+
${pc.dim("Project:")}
|
|
34
|
+
${pc.cyan("init")} [name] Scaffold a new project
|
|
35
|
+
${pc.cyan("status")} Show project info
|
|
36
|
+
${pc.cyan("migrate")} Upgrade legacy project
|
|
37
|
+
|
|
38
|
+
${pc.dim("Skills:")}
|
|
39
|
+
${pc.cyan("skills list")} List available skills
|
|
40
|
+
${pc.cyan("skills install")} Install skills
|
|
41
|
+
${pc.cyan("skills update")} Update skills
|
|
42
|
+
|
|
43
|
+
${pc.dim("Auth:")}
|
|
44
|
+
${pc.cyan("login")} Login to Lumera
|
|
45
|
+
${pc.cyan("logout")} Clear credentials
|
|
46
|
+
${pc.cyan("whoami")} Show current user
|
|
47
|
+
|
|
48
|
+
${pc.dim("Options:")}
|
|
49
|
+
--help, -h Show help
|
|
50
|
+
--version, -v Show version
|
|
51
|
+
|
|
52
|
+
${pc.dim("Resource Types:")}
|
|
53
|
+
collections Data collections (schemas)
|
|
54
|
+
automations Background Python scripts
|
|
55
|
+
hooks Collection lifecycle handlers
|
|
56
|
+
app Frontend application
|
|
57
|
+
|
|
58
|
+
${pc.dim("Examples:")}
|
|
59
|
+
lumera apply # Apply all resources
|
|
60
|
+
lumera apply collections/users # Apply single collection
|
|
61
|
+
lumera apply app # Deploy frontend
|
|
62
|
+
lumera list # List all resources
|
|
63
|
+
lumera show collections/users # Show collection details
|
|
64
|
+
lumera run scripts/seed.py # Run a script
|
|
65
|
+
lumera run automations/sync # Trigger automation
|
|
66
|
+
lumera dev # Start dev server
|
|
67
|
+
|
|
68
|
+
${pc.dim("Documentation:")}
|
|
69
|
+
https://docs.lumerahq.com/cli
|
|
70
|
+
`);
|
|
71
|
+
}
|
|
72
|
+
function showVersion() {
|
|
73
|
+
console.log(`lumera ${VERSION}`);
|
|
74
|
+
}
|
|
75
|
+
async function main() {
|
|
76
|
+
if (!command || command.startsWith("-")) {
|
|
77
|
+
if (args.includes("--help") || args.includes("-h") || args.length === 0) {
|
|
78
|
+
showHelp();
|
|
79
|
+
process.exit(0);
|
|
80
|
+
}
|
|
81
|
+
if (args.includes("--version") || args.includes("-v")) {
|
|
82
|
+
showVersion();
|
|
83
|
+
process.exit(0);
|
|
84
|
+
}
|
|
85
|
+
if (command?.startsWith("-")) {
|
|
86
|
+
console.error(pc.red(`Unknown option: ${command}`));
|
|
87
|
+
showHelp();
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
try {
|
|
92
|
+
switch (command) {
|
|
93
|
+
// Resource commands
|
|
94
|
+
case "plan":
|
|
95
|
+
await import("./resources-PNK3NESI.js").then((m) => m.plan(args.slice(1)));
|
|
96
|
+
break;
|
|
97
|
+
case "apply":
|
|
98
|
+
await import("./resources-PNK3NESI.js").then((m) => m.apply(args.slice(1)));
|
|
99
|
+
break;
|
|
100
|
+
case "pull":
|
|
101
|
+
await import("./resources-PNK3NESI.js").then((m) => m.pull(args.slice(1)));
|
|
102
|
+
break;
|
|
103
|
+
case "destroy":
|
|
104
|
+
await import("./resources-PNK3NESI.js").then((m) => m.destroy(args.slice(1)));
|
|
105
|
+
break;
|
|
106
|
+
case "list":
|
|
107
|
+
await import("./resources-PNK3NESI.js").then((m) => m.list(args.slice(1)));
|
|
108
|
+
break;
|
|
109
|
+
case "show":
|
|
110
|
+
await import("./resources-PNK3NESI.js").then((m) => m.show(args.slice(1)));
|
|
111
|
+
break;
|
|
112
|
+
// Development
|
|
113
|
+
case "dev":
|
|
114
|
+
await import("./dev-UTZC4ZJ7.js").then((m) => m.dev(args.slice(1)));
|
|
115
|
+
break;
|
|
116
|
+
case "run":
|
|
117
|
+
await import("./run-4NDI2CN4.js").then((m) => m.run(args.slice(1)));
|
|
118
|
+
break;
|
|
119
|
+
// Project
|
|
120
|
+
case "init":
|
|
121
|
+
await import("./init-OQCIET53.js").then((m) => m.init(args.slice(1)));
|
|
122
|
+
break;
|
|
123
|
+
case "status":
|
|
124
|
+
await import("./status-BEVUV6RY.js").then((m) => m.status(args.slice(1)));
|
|
125
|
+
break;
|
|
126
|
+
case "migrate":
|
|
127
|
+
await import("./migrate-2DZ6RQ5K.js").then((m) => m.migrate(args.slice(1)));
|
|
128
|
+
break;
|
|
129
|
+
// Skills
|
|
130
|
+
case "skills":
|
|
131
|
+
await import("./skills-56EUKHGY.js").then((m) => m.skills(subcommand, args.slice(2)));
|
|
132
|
+
break;
|
|
133
|
+
// Auth
|
|
134
|
+
case "login":
|
|
135
|
+
await import("./auth-7RGL7GXU.js").then((m) => m.login(args.slice(1)));
|
|
136
|
+
break;
|
|
137
|
+
case "logout":
|
|
138
|
+
await import("./auth-7RGL7GXU.js").then((m) => m.logout(args.slice(1)));
|
|
139
|
+
break;
|
|
140
|
+
case "whoami":
|
|
141
|
+
await import("./auth-7RGL7GXU.js").then((m) => m.whoami());
|
|
142
|
+
break;
|
|
143
|
+
default:
|
|
144
|
+
console.error(pc.red(`Unknown command: ${command}`));
|
|
145
|
+
console.error(`Run ${pc.cyan("lumera --help")} for usage.`);
|
|
146
|
+
process.exit(1);
|
|
147
|
+
}
|
|
148
|
+
} catch (error) {
|
|
149
|
+
if (error instanceof Error) {
|
|
150
|
+
console.error(pc.red(`Error: ${error.message}`));
|
|
151
|
+
} else {
|
|
152
|
+
console.error(pc.red("An unexpected error occurred"));
|
|
153
|
+
}
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
main();
|