@lotics/cli 0.39.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 +31 -8
- package/dist/client.d.ts +15 -6
- package/dist/client.js +5 -9
- package/dist/dev/rpc_handler.js +1 -0
- package/dist/src/cli.js +7966 -7612
- package/dist/starter_template.js +10 -6
- package/dist/starter_template.test.js +10 -0
- package/package.json +1 -1
package/dist/app_commands.js
CHANGED
|
@@ -92,10 +92,7 @@ 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
|
-
|
|
96
|
-
// App row's icon/theme is preserved.
|
|
97
|
-
icon: pkg.lotics.icon,
|
|
98
|
-
theme: pkg.lotics.theme,
|
|
95
|
+
capabilities: pkg.lotics.capabilities,
|
|
99
96
|
};
|
|
100
97
|
}
|
|
101
98
|
function writeAppMeta(projectDir, meta) {
|
|
@@ -345,10 +342,11 @@ export async function appDeploy(client, args) {
|
|
|
345
342
|
// Sync apps.queries from the manifest. Server validates each query
|
|
346
343
|
// template (parseQueryNode, table access, param coverage).
|
|
347
344
|
queries: meta.queries ?? {},
|
|
348
|
-
//
|
|
349
|
-
//
|
|
350
|
-
|
|
351
|
-
|
|
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).
|
|
349
|
+
capabilities: meta.capabilities ?? {},
|
|
352
350
|
// Opt into destructive workflow removal. Default false — the server
|
|
353
351
|
// rejects deploys whose manifest is missing aliases the App row has.
|
|
354
352
|
force_workflow_sync: args.forceWorkflowSync,
|
|
@@ -360,6 +358,7 @@ export async function appDeploy(client, args) {
|
|
|
360
358
|
});
|
|
361
359
|
console.error(`Deployed v${result.version_number} (${result.version_id})`);
|
|
362
360
|
console.error(`Bundle size: ${(result.bundle_size_bytes / 1024).toFixed(1)} KB`);
|
|
361
|
+
await warnIfUnbranded(client, meta.app_id);
|
|
363
362
|
}
|
|
364
363
|
catch (err) {
|
|
365
364
|
const e = err;
|
|
@@ -378,6 +377,30 @@ export async function appDeploy(client, args) {
|
|
|
378
377
|
fs.unlinkSync(tmpDist);
|
|
379
378
|
}
|
|
380
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
|
+
}
|
|
381
404
|
/**
|
|
382
405
|
* `lotics app dev [path] [--port=5174] [--vite-port=5173]`
|
|
383
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
|
|
@@ -155,8 +161,10 @@ export declare class LoticsClient {
|
|
|
155
161
|
offset?: number;
|
|
156
162
|
sort?: AppQuerySortKey[];
|
|
157
163
|
filter?: AppQueryFilter;
|
|
164
|
+
count?: boolean;
|
|
158
165
|
}): Promise<{
|
|
159
166
|
rows: unknown[];
|
|
167
|
+
total?: number;
|
|
160
168
|
}>;
|
|
161
169
|
appMembers(app_id: string, group_id?: string): Promise<{
|
|
162
170
|
members: Array<{
|
|
@@ -231,13 +239,14 @@ export declare class LoticsClient {
|
|
|
231
239
|
params?: Record<string, unknown>;
|
|
232
240
|
}>;
|
|
233
241
|
/**
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
*
|
|
242
|
+
* Opt-in app capabilities from `package.json#lotics.capabilities`. The CLI
|
|
243
|
+
* sends this on every deploy (defaulting to `{}`): the manifest is
|
|
244
|
+
* authoritative, so an empty/absent block turns every capability off.
|
|
245
|
+
* `comments: true` enables the members-only `useComments` primitive.
|
|
238
246
|
*/
|
|
239
|
-
|
|
240
|
-
|
|
247
|
+
capabilities?: {
|
|
248
|
+
comments?: boolean;
|
|
249
|
+
};
|
|
241
250
|
/**
|
|
242
251
|
* Opt into destructive workflow removal. When false/absent, the server
|
|
243
252
|
* rejects a deploy whose `workflows` map is missing aliases that exist
|
package/dist/client.js
CHANGED
|
@@ -220,15 +220,11 @@ 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
|
-
//
|
|
224
|
-
//
|
|
225
|
-
//
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
formData.append("icon", args.icon);
|
|
229
|
-
}
|
|
230
|
-
if (args.theme !== undefined) {
|
|
231
|
-
formData.append("theme", JSON.stringify(args.theme));
|
|
223
|
+
// capabilities is manifest-authoritative — the caller always passes it
|
|
224
|
+
// (`{}` when none declared), so a deploy turns off any capability the
|
|
225
|
+
// manifest no longer declares. JSON-encoded.
|
|
226
|
+
if (args.capabilities !== undefined) {
|
|
227
|
+
formData.append("capabilities", JSON.stringify(args.capabilities));
|
|
232
228
|
}
|
|
233
229
|
// Only post the override flag when the user explicitly opts in. The
|
|
234
230
|
// server defaults to "honor the guard" — opt-in is loud, opt-out
|