@lotics/cli 0.40.0 → 0.41.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/app_commands.js +29 -13
- package/dist/client.d.ts +6 -8
- package/dist/client.js +0 -10
- package/dist/src/cli.js +22 -19
- package/package.json +1 -1
package/dist/app_commands.js
CHANGED
|
@@ -92,10 +92,6 @@ function readAppMeta(projectDir) {
|
|
|
92
92
|
version_number: pkg.lotics.version_number ?? null,
|
|
93
93
|
workflows: pkg.lotics.workflows ?? {},
|
|
94
94
|
queries: pkg.lotics.queries ?? {},
|
|
95
|
-
// Left as `undefined` when absent so the deploy omits them and the
|
|
96
|
-
// App row's icon/theme is preserved.
|
|
97
|
-
icon: pkg.lotics.icon,
|
|
98
|
-
theme: pkg.lotics.theme,
|
|
99
95
|
capabilities: pkg.lotics.capabilities,
|
|
100
96
|
};
|
|
101
97
|
}
|
|
@@ -346,15 +342,10 @@ export async function appDeploy(client, args) {
|
|
|
346
342
|
// Sync apps.queries from the manifest. Server validates each query
|
|
347
343
|
// template (parseQueryNode, table access, param coverage).
|
|
348
344
|
queries: meta.queries ?? {},
|
|
349
|
-
//
|
|
350
|
-
//
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
// Capabilities are manifest-authoritative (like workflows/queries, not
|
|
354
|
-
// like icon/theme): always send, defaulting to `{}` when the manifest
|
|
355
|
-
// declares none — so deleting the `capabilities` block turns every
|
|
356
|
-
// capability OFF on the next deploy (fail-safe; the declaration is the
|
|
357
|
-
// grant). The manifest is the only writer of capabilities.
|
|
345
|
+
// Capabilities are manifest-authoritative (like workflows/queries):
|
|
346
|
+
// always send, defaulting to `{}` when the manifest declares none — so
|
|
347
|
+
// deleting the `capabilities` block turns every capability OFF on the
|
|
348
|
+
// next deploy (fail-safe; the declaration is the grant).
|
|
358
349
|
capabilities: meta.capabilities ?? {},
|
|
359
350
|
// Opt into destructive workflow removal. Default false — the server
|
|
360
351
|
// rejects deploys whose manifest is missing aliases the App row has.
|
|
@@ -367,6 +358,7 @@ export async function appDeploy(client, args) {
|
|
|
367
358
|
});
|
|
368
359
|
console.error(`Deployed v${result.version_number} (${result.version_id})`);
|
|
369
360
|
console.error(`Bundle size: ${(result.bundle_size_bytes / 1024).toFixed(1)} KB`);
|
|
361
|
+
await warnIfUnbranded(client, meta.app_id);
|
|
370
362
|
}
|
|
371
363
|
catch (err) {
|
|
372
364
|
const e = err;
|
|
@@ -385,6 +377,30 @@ export async function appDeploy(client, args) {
|
|
|
385
377
|
fs.unlinkSync(tmpDist);
|
|
386
378
|
}
|
|
387
379
|
}
|
|
380
|
+
/**
|
|
381
|
+
* Non-blocking nudge after a successful deploy: an app with no icon/color shows a
|
|
382
|
+
* generic tile in the launcher. Branding is set via `update_app` (the single
|
|
383
|
+
* setter) — this only reminds; it never fails the deploy.
|
|
384
|
+
*/
|
|
385
|
+
async function warnIfUnbranded(client, appId) {
|
|
386
|
+
try {
|
|
387
|
+
const app = await client.getApp(appId);
|
|
388
|
+
const missing = [];
|
|
389
|
+
if (!app.icon)
|
|
390
|
+
missing.push("icon");
|
|
391
|
+
if (!app.theme?.color)
|
|
392
|
+
missing.push("color");
|
|
393
|
+
if (missing.length === 0)
|
|
394
|
+
return;
|
|
395
|
+
console.error(`\n⚠ This app has no ${missing.join(" or ")} set — it shows a generic tile in the launcher.\n` +
|
|
396
|
+
` Set it: lotics run update_app '{"app_id":"${appId}","icon":"<lucide-name>","theme":{"color":"blue"}}'\n` +
|
|
397
|
+
` Find an icon: lotics run search_app_icons '{"query":"<word>"}'`);
|
|
398
|
+
}
|
|
399
|
+
catch (err) {
|
|
400
|
+
// Deploy already succeeded; a failed branding check must not mask that.
|
|
401
|
+
console.error(`(skipped branding check: ${err.message})`);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
388
404
|
/**
|
|
389
405
|
* `lotics app dev [path] [--port=5174] [--vite-port=5173]`
|
|
390
406
|
*
|
package/dist/client.d.ts
CHANGED
|
@@ -96,6 +96,12 @@ export declare class LoticsClient {
|
|
|
96
96
|
name: string;
|
|
97
97
|
workspace_id: string;
|
|
98
98
|
current_version_id: string | null;
|
|
99
|
+
/** Launcher icon — a Lucide name, or an image ref. Null when unset. */
|
|
100
|
+
icon?: string | null;
|
|
101
|
+
/** Launcher theme — `{ color }` is a palette token. Null when unset. */
|
|
102
|
+
theme?: {
|
|
103
|
+
color?: string | null;
|
|
104
|
+
} | null;
|
|
99
105
|
/**
|
|
100
106
|
* Live alias → workflow declaration map from `apps.workflows`. Source of
|
|
101
107
|
* truth for `lotics app pull` — supersedes the manifest embedded in the
|
|
@@ -232,14 +238,6 @@ export declare class LoticsClient {
|
|
|
232
238
|
ast: unknown;
|
|
233
239
|
params?: Record<string, unknown>;
|
|
234
240
|
}>;
|
|
235
|
-
/**
|
|
236
|
-
* App icon (Lucide name) + theme `{ color }` from `package.json#lotics`.
|
|
237
|
-
* `undefined` ⇒ not sent ⇒ the deploy leaves the App row's icon/theme
|
|
238
|
-
* as-is. A present value is applied authoritatively. `icon` rides as a
|
|
239
|
-
* raw form field; `theme` is an object, so it's JSON-encoded.
|
|
240
|
-
*/
|
|
241
|
-
icon?: string;
|
|
242
|
-
theme?: Record<string, unknown>;
|
|
243
241
|
/**
|
|
244
242
|
* Opt-in app capabilities from `package.json#lotics.capabilities`. The CLI
|
|
245
243
|
* sends this on every deploy (defaulting to `{}`): the manifest is
|
package/dist/client.js
CHANGED
|
@@ -220,16 +220,6 @@ export class LoticsClient {
|
|
|
220
220
|
// Always send queries — empty object clears any previously-declared
|
|
221
221
|
// named queries. Server validates each template.
|
|
222
222
|
formData.append("queries", JSON.stringify(args.queries ?? {}));
|
|
223
|
-
// icon/theme are optional overrides — only sent when the manifest
|
|
224
|
-
// declares them, so a deploy never clobbers a value set in the UI.
|
|
225
|
-
// `icon` is a plain string → raw field, like `message`. `theme` is an
|
|
226
|
-
// object → JSON-encoded, like `workflows`/`queries`.
|
|
227
|
-
if (args.icon !== undefined) {
|
|
228
|
-
formData.append("icon", args.icon);
|
|
229
|
-
}
|
|
230
|
-
if (args.theme !== undefined) {
|
|
231
|
-
formData.append("theme", JSON.stringify(args.theme));
|
|
232
|
-
}
|
|
233
223
|
// capabilities is manifest-authoritative — the caller always passes it
|
|
234
224
|
// (`{}` when none declared), so a deploy turns off any capability the
|
|
235
225
|
// manifest no longer declares. JSON-encoded.
|
package/dist/src/cli.js
CHANGED
|
@@ -29814,12 +29814,6 @@ var LoticsClient = class {
|
|
|
29814
29814
|
}
|
|
29815
29815
|
formData.append("workflows", JSON.stringify(args.workflows ?? {}));
|
|
29816
29816
|
formData.append("queries", JSON.stringify(args.queries ?? {}));
|
|
29817
|
-
if (args.icon !== void 0) {
|
|
29818
|
-
formData.append("icon", args.icon);
|
|
29819
|
-
}
|
|
29820
|
-
if (args.theme !== void 0) {
|
|
29821
|
-
formData.append("theme", JSON.stringify(args.theme));
|
|
29822
|
-
}
|
|
29823
29817
|
if (args.capabilities !== void 0) {
|
|
29824
29818
|
formData.append("capabilities", JSON.stringify(args.capabilities));
|
|
29825
29819
|
}
|
|
@@ -31239,10 +31233,6 @@ function readAppMeta(projectDir) {
|
|
|
31239
31233
|
version_number: pkg2.lotics.version_number ?? null,
|
|
31240
31234
|
workflows: pkg2.lotics.workflows ?? {},
|
|
31241
31235
|
queries: pkg2.lotics.queries ?? {},
|
|
31242
|
-
// Left as `undefined` when absent so the deploy omits them and the
|
|
31243
|
-
// App row's icon/theme is preserved.
|
|
31244
|
-
icon: pkg2.lotics.icon,
|
|
31245
|
-
theme: pkg2.lotics.theme,
|
|
31246
31236
|
capabilities: pkg2.lotics.capabilities
|
|
31247
31237
|
};
|
|
31248
31238
|
}
|
|
@@ -31417,15 +31407,10 @@ async function appDeploy(client, args) {
|
|
|
31417
31407
|
// Sync apps.queries from the manifest. Server validates each query
|
|
31418
31408
|
// template (parseQueryNode, table access, param coverage).
|
|
31419
31409
|
queries: meta.queries ?? {},
|
|
31420
|
-
//
|
|
31421
|
-
//
|
|
31422
|
-
|
|
31423
|
-
|
|
31424
|
-
// Capabilities are manifest-authoritative (like workflows/queries, not
|
|
31425
|
-
// like icon/theme): always send, defaulting to `{}` when the manifest
|
|
31426
|
-
// declares none — so deleting the `capabilities` block turns every
|
|
31427
|
-
// capability OFF on the next deploy (fail-safe; the declaration is the
|
|
31428
|
-
// grant). The manifest is the only writer of capabilities.
|
|
31410
|
+
// Capabilities are manifest-authoritative (like workflows/queries):
|
|
31411
|
+
// always send, defaulting to `{}` when the manifest declares none — so
|
|
31412
|
+
// deleting the `capabilities` block turns every capability OFF on the
|
|
31413
|
+
// next deploy (fail-safe; the declaration is the grant).
|
|
31429
31414
|
capabilities: meta.capabilities ?? {},
|
|
31430
31415
|
// Opt into destructive workflow removal. Default false — the server
|
|
31431
31416
|
// rejects deploys whose manifest is missing aliases the App row has.
|
|
@@ -31438,6 +31423,7 @@ async function appDeploy(client, args) {
|
|
|
31438
31423
|
});
|
|
31439
31424
|
console.error(`Deployed v${result.version_number} (${result.version_id})`);
|
|
31440
31425
|
console.error(`Bundle size: ${(result.bundle_size_bytes / 1024).toFixed(1)} KB`);
|
|
31426
|
+
await warnIfUnbranded(client, meta.app_id);
|
|
31441
31427
|
} catch (err2) {
|
|
31442
31428
|
const e = err2;
|
|
31443
31429
|
if (e.code === "VERSION_CONFLICT") {
|
|
@@ -31453,6 +31439,23 @@ async function appDeploy(client, args) {
|
|
|
31453
31439
|
if (fs3.existsSync(tmpDist)) fs3.unlinkSync(tmpDist);
|
|
31454
31440
|
}
|
|
31455
31441
|
}
|
|
31442
|
+
async function warnIfUnbranded(client, appId) {
|
|
31443
|
+
try {
|
|
31444
|
+
const app = await client.getApp(appId);
|
|
31445
|
+
const missing = [];
|
|
31446
|
+
if (!app.icon) missing.push("icon");
|
|
31447
|
+
if (!app.theme?.color) missing.push("color");
|
|
31448
|
+
if (missing.length === 0) return;
|
|
31449
|
+
console.error(
|
|
31450
|
+
`
|
|
31451
|
+
\u26A0 This app has no ${missing.join(" or ")} set \u2014 it shows a generic tile in the launcher.
|
|
31452
|
+
Set it: lotics run update_app '{"app_id":"${appId}","icon":"<lucide-name>","theme":{"color":"blue"}}'
|
|
31453
|
+
Find an icon: lotics run search_app_icons '{"query":"<word>"}'`
|
|
31454
|
+
);
|
|
31455
|
+
} catch (err2) {
|
|
31456
|
+
console.error(`(skipped branding check: ${err2.message})`);
|
|
31457
|
+
}
|
|
31458
|
+
}
|
|
31456
31459
|
async function appDev(client, args) {
|
|
31457
31460
|
const projectDir = path4.resolve(args.projectDir ?? process.cwd());
|
|
31458
31461
|
const meta = readAppMeta(projectDir);
|