@lotics/cli 0.30.1 → 0.31.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/dist/src/app_commands.d.ts +8 -0
- package/dist/src/app_commands.js +18 -0
- package/dist/src/cli.js +13 -1
- package/dist/src/client.d.ts +17 -0
- package/dist/src/client.js +18 -0
- package/dist/src/dev/server.js +11 -2
- package/package.json +1 -1
|
@@ -78,6 +78,14 @@ export declare function appCreate(client: LoticsClient, args: {
|
|
|
78
78
|
* 6. (TODO) Generate `.lotics/types.ts` with workspace tables augmentation —
|
|
79
79
|
* pending a `client.getWorkspaceSchema()` endpoint.
|
|
80
80
|
*/
|
|
81
|
+
/**
|
|
82
|
+
* `lotics app subdomain <new>` — rename the current app's public address.
|
|
83
|
+
* The app_id comes from the local `package.json` manifest. The old
|
|
84
|
+
* `<slug>.lotics.app` stops resolving once the change lands.
|
|
85
|
+
*/
|
|
86
|
+
export declare function appSetSubdomain(client: LoticsClient, args: {
|
|
87
|
+
subdomain: string;
|
|
88
|
+
}): Promise<void>;
|
|
81
89
|
export declare function appPull(client: LoticsClient, args: {
|
|
82
90
|
app_id: string;
|
|
83
91
|
targetPath?: string;
|
package/dist/src/app_commands.js
CHANGED
|
@@ -66,6 +66,10 @@ function readAppMeta(projectDir) {
|
|
|
66
66
|
version_number: pkg.lotics.version_number ?? null,
|
|
67
67
|
workflows: pkg.lotics.workflows ?? {},
|
|
68
68
|
queries: pkg.lotics.queries ?? {},
|
|
69
|
+
// Left as `undefined` when absent so the deploy omits them and the
|
|
70
|
+
// App row's icon/theme is preserved.
|
|
71
|
+
icon: pkg.lotics.icon,
|
|
72
|
+
theme: pkg.lotics.theme,
|
|
69
73
|
};
|
|
70
74
|
}
|
|
71
75
|
function writeAppMeta(projectDir, meta) {
|
|
@@ -189,6 +193,16 @@ export async function appCreate(client, args) {
|
|
|
189
193
|
* 6. (TODO) Generate `.lotics/types.ts` with workspace tables augmentation —
|
|
190
194
|
* pending a `client.getWorkspaceSchema()` endpoint.
|
|
191
195
|
*/
|
|
196
|
+
/**
|
|
197
|
+
* `lotics app subdomain <new>` — rename the current app's public address.
|
|
198
|
+
* The app_id comes from the local `package.json` manifest. The old
|
|
199
|
+
* `<slug>.lotics.app` stops resolving once the change lands.
|
|
200
|
+
*/
|
|
201
|
+
export async function appSetSubdomain(client, args) {
|
|
202
|
+
const meta = readAppMeta(process.cwd());
|
|
203
|
+
const result = await client.setAppSubdomain(meta.app_id, args.subdomain);
|
|
204
|
+
console.error(`Public address set: https://${result.public_subdomain}.lotics.app`);
|
|
205
|
+
}
|
|
192
206
|
export async function appPull(client, args) {
|
|
193
207
|
const app = await client.getApp(args.app_id);
|
|
194
208
|
if (!app.current_version_id) {
|
|
@@ -283,6 +297,10 @@ export async function appDeploy(client, args) {
|
|
|
283
297
|
// Sync apps.queries from the manifest. Server validates each query
|
|
284
298
|
// template (parseQueryNode, table access, param coverage).
|
|
285
299
|
queries: meta.queries ?? {},
|
|
300
|
+
// Optional icon/theme overrides — only sent when the manifest
|
|
301
|
+
// declares them (undefined ⇒ omitted ⇒ App row left untouched).
|
|
302
|
+
icon: meta.icon,
|
|
303
|
+
theme: meta.theme,
|
|
286
304
|
// Opt into destructive workflow removal. Default false — the server
|
|
287
305
|
// rejects deploys whose manifest is missing aliases the App row has.
|
|
288
306
|
force_workflow_sync: args.forceWorkflowSync,
|
package/dist/src/cli.js
CHANGED
|
@@ -5,7 +5,7 @@ import readline from "node:readline";
|
|
|
5
5
|
import { LoticsClient, API_BASE_URL } from "./client.js";
|
|
6
6
|
import { resolveAuth, loadConfig, saveConfig, deleteConfig, getConfigPath, checkForUpdate } from "./config.js";
|
|
7
7
|
import { VERSION } from "./version.js";
|
|
8
|
-
import { appCreate, appPull, appDeploy, appDev } from "./app_commands.js";
|
|
8
|
+
import { appCreate, appPull, appDeploy, appDev, appSetSubdomain } from "./app_commands.js";
|
|
9
9
|
import { parseArgs } from "./args.js";
|
|
10
10
|
function printHelp() {
|
|
11
11
|
console.log(`Lotics CLI v${VERSION} — AI agent interface for Lotics
|
|
@@ -51,6 +51,7 @@ COMMANDS
|
|
|
51
51
|
Build + upload current dir as a new version
|
|
52
52
|
(--force-workflow-sync wipes server-only
|
|
53
53
|
workflow aliases; default refuses)
|
|
54
|
+
lotics app subdomain <new-subdomain> Rename the app's public <slug>.lotics.app address
|
|
54
55
|
lotics app dev [path] Run the app locally with HMR (RPC forwarded to prod)
|
|
55
56
|
|
|
56
57
|
FLAGS
|
|
@@ -359,6 +360,7 @@ async function main() {
|
|
|
359
360
|
console.error(" lotics app pull <app_id> [path] Pull an existing app for local editing");
|
|
360
361
|
console.error(" lotics app deploy [-m <message>] [--force-workflow-sync]");
|
|
361
362
|
console.error(" Build + upload the current directory");
|
|
363
|
+
console.error(" lotics app subdomain <new-subdomain> Rename the app's public <slug>.lotics.app address");
|
|
362
364
|
console.error(" lotics app dev [path] Run the app locally with HMR + RPC forwarding");
|
|
363
365
|
process.exit(1);
|
|
364
366
|
}
|
|
@@ -481,6 +483,16 @@ async function main() {
|
|
|
481
483
|
await appDeploy(client, { message, forceWorkflowSync: flags.forceWorkflowSync });
|
|
482
484
|
return;
|
|
483
485
|
}
|
|
486
|
+
if (subcommand === "subdomain") {
|
|
487
|
+
const newSubdomain = toolArgs;
|
|
488
|
+
if (!newSubdomain) {
|
|
489
|
+
console.error("Usage: lotics app subdomain <new-subdomain>");
|
|
490
|
+
console.error("Renames the app's public address — https://<slug>.lotics.app");
|
|
491
|
+
process.exit(1);
|
|
492
|
+
}
|
|
493
|
+
await appSetSubdomain(client, { subdomain: newSubdomain });
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
484
496
|
if (subcommand === "dev") {
|
|
485
497
|
// First positional is an optional project path (defaults to cwd).
|
|
486
498
|
// --port and --vite-port can override the wrapper / Vite ports.
|
package/dist/src/client.d.ts
CHANGED
|
@@ -105,6 +105,15 @@ export declare class LoticsClient {
|
|
|
105
105
|
workspace_id: string;
|
|
106
106
|
current_version_id: string | null;
|
|
107
107
|
}>;
|
|
108
|
+
/**
|
|
109
|
+
* Rename an app's public subdomain — its `<slug>.lotics.app` address.
|
|
110
|
+
* Mirrors PUT /v1/apps/{app_id}/subdomain. The old subdomain stops
|
|
111
|
+
* resolving once the change lands.
|
|
112
|
+
*/
|
|
113
|
+
setAppSubdomain(app_id: string, public_subdomain: string): Promise<{
|
|
114
|
+
app_id: string;
|
|
115
|
+
public_subdomain: string;
|
|
116
|
+
}>;
|
|
108
117
|
getAppVersion(app_id: string, version_id: string): Promise<{
|
|
109
118
|
id: string;
|
|
110
119
|
app_id: string;
|
|
@@ -188,6 +197,14 @@ export declare class LoticsClient {
|
|
|
188
197
|
ast: unknown;
|
|
189
198
|
params?: Record<string, unknown>;
|
|
190
199
|
}>;
|
|
200
|
+
/**
|
|
201
|
+
* App icon (Lucide name) + theme `{ color }` from `package.json#lotics`.
|
|
202
|
+
* `undefined` ⇒ not sent ⇒ the deploy leaves the App row's icon/theme
|
|
203
|
+
* as-is. A present value is applied authoritatively. `icon` rides as a
|
|
204
|
+
* raw form field; `theme` is an object, so it's JSON-encoded.
|
|
205
|
+
*/
|
|
206
|
+
icon?: string;
|
|
207
|
+
theme?: Record<string, unknown>;
|
|
191
208
|
/**
|
|
192
209
|
* Opt into destructive workflow removal. When false/absent, the server
|
|
193
210
|
* rejects a deploy whose `workflows` map is missing aliases that exist
|
package/dist/src/client.js
CHANGED
|
@@ -149,6 +149,14 @@ export class LoticsClient {
|
|
|
149
149
|
async createApp(body) {
|
|
150
150
|
return this.request("POST", "/v1/apps", { ...body, ui: { type: "custom_code" } });
|
|
151
151
|
}
|
|
152
|
+
/**
|
|
153
|
+
* Rename an app's public subdomain — its `<slug>.lotics.app` address.
|
|
154
|
+
* Mirrors PUT /v1/apps/{app_id}/subdomain. The old subdomain stops
|
|
155
|
+
* resolving once the change lands.
|
|
156
|
+
*/
|
|
157
|
+
async setAppSubdomain(app_id, public_subdomain) {
|
|
158
|
+
return this.request("PUT", `/v1/apps/${encodeURIComponent(app_id)}/subdomain`, { public_subdomain });
|
|
159
|
+
}
|
|
152
160
|
async getAppVersion(app_id, version_id) {
|
|
153
161
|
return this.request("GET", `/v1/apps/${encodeURIComponent(app_id)}/versions/${encodeURIComponent(version_id)}`);
|
|
154
162
|
}
|
|
@@ -208,6 +216,16 @@ export class LoticsClient {
|
|
|
208
216
|
// Always send queries — empty object clears any previously-declared
|
|
209
217
|
// named queries. Server validates each template.
|
|
210
218
|
formData.append("queries", JSON.stringify(args.queries ?? {}));
|
|
219
|
+
// icon/theme are optional overrides — only sent when the manifest
|
|
220
|
+
// declares them, so a deploy never clobbers a value set in the UI.
|
|
221
|
+
// `icon` is a plain string → raw field, like `message`. `theme` is an
|
|
222
|
+
// object → JSON-encoded, like `workflows`/`queries`.
|
|
223
|
+
if (args.icon !== undefined) {
|
|
224
|
+
formData.append("icon", args.icon);
|
|
225
|
+
}
|
|
226
|
+
if (args.theme !== undefined) {
|
|
227
|
+
formData.append("theme", JSON.stringify(args.theme));
|
|
228
|
+
}
|
|
211
229
|
// Only post the override flag when the user explicitly opts in. The
|
|
212
230
|
// server defaults to "honor the guard" — opt-in is loud, opt-out
|
|
213
231
|
// requires intent.
|
package/dist/src/dev/server.js
CHANGED
|
@@ -31,10 +31,19 @@ export async function startDevServer(args) {
|
|
|
31
31
|
});
|
|
32
32
|
// ── Vite child ──────────────────────────────────────────────────────────
|
|
33
33
|
// `npx vite` resolves to the project's installed Vite (devDependency in
|
|
34
|
-
// the starter).
|
|
34
|
+
// the starter). stdout/stderr are inherited so the dev sees Vite's banner
|
|
35
|
+
// + HMR logs.
|
|
36
|
+
//
|
|
37
|
+
// stdin is inherited ONLY under a TTY. Vite's dev server quits when a
|
|
38
|
+
// non-interactive stdin (a backgrounded launch, `</dev/null`, a closing
|
|
39
|
+
// pipe) reaches EOF — so inheriting it would kill the dev server the moment
|
|
40
|
+
// `lotics app dev` runs under an agent, CI, or `nohup`. A non-TTY launch
|
|
41
|
+
// gets `/dev/null` (`"ignore"`) instead, decoupling Vite's lifetime from
|
|
42
|
+
// however the wrapper was started. Vite's CLI shortcuts (`r`/`q`/`u`) are
|
|
43
|
+
// only meaningful under a TTY anyway.
|
|
35
44
|
const viteChild = spawn("npx", ["vite", "--port", String(vitePort), "--strictPort"], {
|
|
36
45
|
cwd: args.projectDir,
|
|
37
|
-
stdio: "inherit",
|
|
46
|
+
stdio: [process.stdin.isTTY ? "inherit" : "ignore", "inherit", "inherit"],
|
|
38
47
|
env: { ...process.env, FORCE_COLOR: "1" },
|
|
39
48
|
});
|
|
40
49
|
let stopped = false;
|