@lotics/cli 0.62.0 → 0.63.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 +2 -0
- package/dist/app_commands.d.ts +11 -0
- package/dist/app_commands.js +44 -0
- package/dist/app_commands.test.js +66 -1
- package/dist/cli.js +11 -1
- package/dist/client.d.ts +17 -0
- package/dist/client.js +10 -0
- package/dist/src/cli.js +61 -0
- package/dist/starter_template.js +3 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -156,6 +156,8 @@ Run `lotics xlsx` or `lotics docx` with no subcommand for the full list.
|
|
|
156
156
|
lotics app create "Sales Desk" # scaffold + deploy v1
|
|
157
157
|
lotics app pull app_... # bootstrap an existing app locally
|
|
158
158
|
lotics app deploy -m "Add quote drawer" # build + upload a new version
|
|
159
|
+
lotics app versions # deploy history: version, when, who, -m message (* = live)
|
|
160
|
+
lotics app versions app_... # ...for any app, without pulling it first
|
|
159
161
|
|
|
160
162
|
# Regenerate .lotics/* WITHOUT a deploy: the .d.ts type companions (always) +
|
|
161
163
|
# the runtime app_fields.ts (when authenticated) — F/OPT maps that address
|
package/dist/app_commands.d.ts
CHANGED
|
@@ -196,6 +196,17 @@ export declare function appSetSubdomain(client: LoticsClient, args: {
|
|
|
196
196
|
export declare function appRename(client: LoticsClient, args: {
|
|
197
197
|
name: string;
|
|
198
198
|
}): Promise<void>;
|
|
199
|
+
/**
|
|
200
|
+
* `lotics app versions [app_id]` — print the app's deploy history, newest
|
|
201
|
+
* first: version number, when, deployer, build status, and the `-m` message.
|
|
202
|
+
* With no `app_id`, reads it from the local `package.json` manifest (run inside
|
|
203
|
+
* the app dir); pass an explicit `app_id` to inspect any app without pulling it.
|
|
204
|
+
* The currently served version is marked with `*`. Admin-only server-side.
|
|
205
|
+
*/
|
|
206
|
+
export declare function appVersions(client: LoticsClient, args: {
|
|
207
|
+
app_id?: string;
|
|
208
|
+
limit?: number;
|
|
209
|
+
}): Promise<void>;
|
|
199
210
|
/**
|
|
200
211
|
* Where `lotics app pull <app_id>` lands when given NO explicit path. If the cwd
|
|
201
212
|
* IS already this app's own project (its manifest `app_id` matches), refresh in
|
package/dist/app_commands.js
CHANGED
|
@@ -630,6 +630,50 @@ export async function appRename(client, args) {
|
|
|
630
630
|
throw new Error(res.error);
|
|
631
631
|
console.error(`App renamed: "${args.name}" (${meta.app_id})`);
|
|
632
632
|
}
|
|
633
|
+
/**
|
|
634
|
+
* `lotics app versions [app_id]` — print the app's deploy history, newest
|
|
635
|
+
* first: version number, when, deployer, build status, and the `-m` message.
|
|
636
|
+
* With no `app_id`, reads it from the local `package.json` manifest (run inside
|
|
637
|
+
* the app dir); pass an explicit `app_id` to inspect any app without pulling it.
|
|
638
|
+
* The currently served version is marked with `*`. Admin-only server-side.
|
|
639
|
+
*/
|
|
640
|
+
export async function appVersions(client, args) {
|
|
641
|
+
const appId = args.app_id ?? readAppMeta(process.cwd()).app_id;
|
|
642
|
+
const { current_version_id, versions } = await client.listAppVersions(appId, {
|
|
643
|
+
limit: args.limit,
|
|
644
|
+
});
|
|
645
|
+
if (versions.length === 0) {
|
|
646
|
+
console.error(`No versions found for ${appId}.`);
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
const fmtWhen = (iso) => {
|
|
650
|
+
const d = new Date(iso);
|
|
651
|
+
if (Number.isNaN(d.getTime()))
|
|
652
|
+
return iso;
|
|
653
|
+
const p = (n) => String(n).padStart(2, "0");
|
|
654
|
+
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`;
|
|
655
|
+
};
|
|
656
|
+
const rows = versions.map((v) => ({
|
|
657
|
+
mark: v.id === current_version_id ? "*" : " ",
|
|
658
|
+
ver: `v${v.version}`,
|
|
659
|
+
when: fmtWhen(v.created_at),
|
|
660
|
+
by: v.created_by_name ?? v.created_by ?? "—",
|
|
661
|
+
status: v.build_status,
|
|
662
|
+
message: v.message ?? "",
|
|
663
|
+
}));
|
|
664
|
+
const colWidth = (key, header) => Math.max(header.length, ...rows.map((r) => r[key].length));
|
|
665
|
+
const wVer = colWidth("ver", "VER");
|
|
666
|
+
const wWhen = colWidth("when", "WHEN");
|
|
667
|
+
const wBy = colWidth("by", "DEPLOYER");
|
|
668
|
+
const wStatus = colWidth("status", "STATUS");
|
|
669
|
+
const pad = (s, n) => s.padEnd(n);
|
|
670
|
+
// Title → stderr (status); the table → stdout (data), so it stays pipeable.
|
|
671
|
+
console.error(`Deploy history — ${appId} (${versions.length} version${versions.length === 1 ? "" : "s"}, newest first; * = currently served)`);
|
|
672
|
+
console.log(` ${pad("VER", wVer)} ${pad("WHEN", wWhen)} ${pad("DEPLOYER", wBy)} ${pad("STATUS", wStatus)} MESSAGE`);
|
|
673
|
+
for (const r of rows) {
|
|
674
|
+
console.log(`${r.mark} ${pad(r.ver, wVer)} ${pad(r.when, wWhen)} ${pad(r.by, wBy)} ${pad(r.status, wStatus)} ${r.message}`.trimEnd());
|
|
675
|
+
}
|
|
676
|
+
}
|
|
633
677
|
/**
|
|
634
678
|
* Where `lotics app pull <app_id>` lands when given NO explicit path. If the cwd
|
|
635
679
|
* IS already this app's own project (its manifest `app_id` matches), refresh in
|
|
@@ -2,7 +2,7 @@ import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { tmpdir } from "node:os";
|
|
5
|
-
import { stampPulledManifest, undeclaredCapabilities, appDirName, defaultPullTarget, ensureWorkflowTsconfigExcludes, appCodegen, appUiLink, appWorkflowSet, appWorkflowPull, appExecuteWorkflow, writeWorkflowFile, writeWorkflowGlobals, stripWorkflowHeader, FALLBACK_ENVELOPE_PREFIX, FALLBACK_ENVELOPE_SUFFIX, } from "./app_commands.js";
|
|
5
|
+
import { stampPulledManifest, undeclaredCapabilities, appDirName, defaultPullTarget, ensureWorkflowTsconfigExcludes, appCodegen, appUiLink, appVersions, appWorkflowSet, appWorkflowPull, appExecuteWorkflow, writeWorkflowFile, writeWorkflowGlobals, stripWorkflowHeader, FALLBACK_ENVELOPE_PREFIX, FALLBACK_ENVELOPE_SUFFIX, } from "./app_commands.js";
|
|
6
6
|
/**
|
|
7
7
|
* `appPull` reads workflows from the live App row (server response), NOT from
|
|
8
8
|
* the manifest embedded in the extracted source archive. The frozen archive
|
|
@@ -724,3 +724,68 @@ describe("ensureWorkflowTsconfigExcludes", () => {
|
|
|
724
724
|
expect(fs.readFileSync(tsconfigPath(), "utf-8")).toBe("{ not json,, }");
|
|
725
725
|
});
|
|
726
726
|
});
|
|
727
|
+
describe("appVersions", () => {
|
|
728
|
+
let logLines;
|
|
729
|
+
let errLines;
|
|
730
|
+
beforeEach(() => {
|
|
731
|
+
logLines = [];
|
|
732
|
+
errLines = [];
|
|
733
|
+
vi.spyOn(console, "log").mockImplementation((...args) => {
|
|
734
|
+
logLines.push(String(args[0]));
|
|
735
|
+
});
|
|
736
|
+
vi.spyOn(console, "error").mockImplementation((...args) => {
|
|
737
|
+
errLines.push(String(args[0]));
|
|
738
|
+
});
|
|
739
|
+
});
|
|
740
|
+
afterEach(() => {
|
|
741
|
+
vi.restoreAllMocks();
|
|
742
|
+
});
|
|
743
|
+
const clientWith = (payload) => ({ listAppVersions: vi.fn().mockResolvedValue(payload) });
|
|
744
|
+
it("renders history newest-first, marks the current version, and prefers the deployer name", async () => {
|
|
745
|
+
const client = clientWith({
|
|
746
|
+
current_version_id: "apv_2",
|
|
747
|
+
versions: [
|
|
748
|
+
{
|
|
749
|
+
id: "apv_2",
|
|
750
|
+
version: 2,
|
|
751
|
+
message: "add receipt gate",
|
|
752
|
+
build_status: "success",
|
|
753
|
+
bundle_size_bytes: 1234,
|
|
754
|
+
created_at: "2026-06-24T03:04:41Z",
|
|
755
|
+
created_by: "mem_a",
|
|
756
|
+
created_by_name: "Minh Vu",
|
|
757
|
+
},
|
|
758
|
+
{
|
|
759
|
+
id: "apv_1",
|
|
760
|
+
version: 1,
|
|
761
|
+
message: "initial deploy",
|
|
762
|
+
build_status: "success",
|
|
763
|
+
bundle_size_bytes: 1000,
|
|
764
|
+
created_at: "2026-06-23T08:00:00Z",
|
|
765
|
+
created_by: "mem_b",
|
|
766
|
+
created_by_name: null,
|
|
767
|
+
},
|
|
768
|
+
],
|
|
769
|
+
});
|
|
770
|
+
// Explicit app_id → no manifest/package.json in cwd required.
|
|
771
|
+
await appVersions(client, { app_id: "app_x" });
|
|
772
|
+
// One header row + one row per version, all on stdout.
|
|
773
|
+
expect(logLines.length).toBe(3);
|
|
774
|
+
const v2Row = logLines.find((l) => l.includes("v2"));
|
|
775
|
+
const v1Row = logLines.find((l) => l.includes("v1"));
|
|
776
|
+
// Currently-served version is marked with `*`; the other is not.
|
|
777
|
+
expect(v2Row.startsWith("*")).toBe(true);
|
|
778
|
+
expect(v1Row.startsWith("*")).toBe(false);
|
|
779
|
+
// Messages render; the deployer name is preferred, falling back to the id.
|
|
780
|
+
expect(v2Row).toContain("add receipt gate");
|
|
781
|
+
expect(v2Row).toContain("Minh Vu");
|
|
782
|
+
expect(v1Row).toContain("initial deploy");
|
|
783
|
+
expect(v1Row).toContain("mem_b");
|
|
784
|
+
});
|
|
785
|
+
it("reports an empty history to stderr without printing a table", async () => {
|
|
786
|
+
const client = clientWith({ current_version_id: null, versions: [] });
|
|
787
|
+
await appVersions(client, { app_id: "app_empty" });
|
|
788
|
+
expect(logLines).toEqual([]);
|
|
789
|
+
expect(errLines.join("\n")).toContain("No versions found");
|
|
790
|
+
});
|
|
791
|
+
});
|
package/dist/cli.js
CHANGED
|
@@ -13,7 +13,7 @@ net.setDefaultAutoSelectFamilyAttemptTimeout(2000);
|
|
|
13
13
|
import { LoticsClient, API_BASE_URL } from "./client.js";
|
|
14
14
|
import { resolveContext, deleteConfig, getConfigPath, loadGlobalConfig, saveGlobalConfig, loadLocalConfig, upsertProfile, removeProfile, setActiveOrg, setSelectedWorkspace, resolveProfileByNameOrId, checkForUpdate, } from "./config.js";
|
|
15
15
|
import { VERSION } from "./version.js";
|
|
16
|
-
import { appCreate, appPull, appDeploy, appDev, appSetSubdomain, appRename, appCodegen, appExecuteWorkflow, appWorkflowSet, appWorkflowPull, appWorkflowCheck, appUiLink, } from "./app_commands.js";
|
|
16
|
+
import { appCreate, appPull, appDeploy, appDev, appSetSubdomain, appRename, appVersions, appCodegen, appExecuteWorkflow, appWorkflowSet, appWorkflowPull, appWorkflowCheck, appUiLink, } from "./app_commands.js";
|
|
17
17
|
import { parseArgs } from "./args.js";
|
|
18
18
|
import { ingestJsonArgs } from "./inputs.js";
|
|
19
19
|
import { runXlsxCommand } from "./xlsx.js";
|
|
@@ -74,6 +74,9 @@ COMMANDS
|
|
|
74
74
|
lotics app deploy [-m <message>] Build + upload current dir as a new version
|
|
75
75
|
(code + queries only — workflow bindings are
|
|
76
76
|
managed by set_app_workflow / remove_app_workflow)
|
|
77
|
+
lotics app versions [app_id] Show deploy history newest-first (version,
|
|
78
|
+
timestamp, deployer, build status, -m message;
|
|
79
|
+
* marks the currently served version)
|
|
77
80
|
lotics app codegen [path] Regenerate .lotics/* (types + field/option ids)
|
|
78
81
|
from the manifest + workspace schema — no deploy
|
|
79
82
|
lotics app workflow run <alias> '<json>' Execute a bound app workflow end-to-end
|
|
@@ -596,6 +599,7 @@ async function main() {
|
|
|
596
599
|
console.error(" lotics app create <name> [path] Scaffold a new app locally");
|
|
597
600
|
console.error(" lotics app pull <app_id> [path] Pull an existing app for local editing");
|
|
598
601
|
console.error(" lotics app deploy [-m <message>] Build + upload the current directory");
|
|
602
|
+
console.error(" lotics app versions [app_id] Show deploy history (version, when, who, message)");
|
|
599
603
|
console.error(" lotics app codegen [path] Regenerate .lotics/* (types + field ids) — no deploy");
|
|
600
604
|
console.error(" lotics app workflow run <alias> '<json>' Execute a bound app workflow end-to-end");
|
|
601
605
|
console.error(" lotics app workflow set <alias> Push the edited src/workflows/<alias>.ts body");
|
|
@@ -749,6 +753,12 @@ async function main() {
|
|
|
749
753
|
await appRename(client, { name: newName });
|
|
750
754
|
return;
|
|
751
755
|
}
|
|
756
|
+
if (subcommand === "versions") {
|
|
757
|
+
// Optional positional app_id (inspect any app); else read the local manifest.
|
|
758
|
+
const appId = toolArgs || undefined;
|
|
759
|
+
await appVersions(client, { app_id: appId });
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
752
762
|
if (subcommand === "workflow") {
|
|
753
763
|
// `lotics app workflow <run|set|pull> …` — disambiguated subcommands so an
|
|
754
764
|
// alias can never collide with the verb. `toolArgs` is the verb; `restArgs`
|
package/dist/client.d.ts
CHANGED
|
@@ -199,6 +199,23 @@ export declare class LoticsClient {
|
|
|
199
199
|
build_status: string;
|
|
200
200
|
}>;
|
|
201
201
|
getAppVersionSourceUrl(app_id: string, version_id: string): Promise<string>;
|
|
202
|
+
/** Deploy history for an app — newest first. Backs `lotics app versions`. */
|
|
203
|
+
listAppVersions(app_id: string, opts?: {
|
|
204
|
+
limit?: number;
|
|
205
|
+
offset?: number;
|
|
206
|
+
}): Promise<{
|
|
207
|
+
current_version_id: string | null;
|
|
208
|
+
versions: Array<{
|
|
209
|
+
id: string;
|
|
210
|
+
version: number;
|
|
211
|
+
message: string | null;
|
|
212
|
+
build_status: string;
|
|
213
|
+
bundle_size_bytes: number | null;
|
|
214
|
+
created_at: string;
|
|
215
|
+
created_by: string | null;
|
|
216
|
+
created_by_name: string | null;
|
|
217
|
+
}>;
|
|
218
|
+
}>;
|
|
202
219
|
/**
|
|
203
220
|
* Run a named query declared in the app's manifest, scoped to the app's IAM
|
|
204
221
|
* principal. Mirrors POST /v1/apps/{app_id}/query.
|
package/dist/client.js
CHANGED
|
@@ -244,6 +244,16 @@ export class LoticsClient {
|
|
|
244
244
|
const result = await this.request("GET", `/v1/apps/${encodeURIComponent(app_id)}/versions/${encodeURIComponent(version_id)}/source`);
|
|
245
245
|
return result.url;
|
|
246
246
|
}
|
|
247
|
+
/** Deploy history for an app — newest first. Backs `lotics app versions`. */
|
|
248
|
+
async listAppVersions(app_id, opts) {
|
|
249
|
+
const qs = new URLSearchParams();
|
|
250
|
+
if (opts?.limit != null)
|
|
251
|
+
qs.set("limit", String(opts.limit));
|
|
252
|
+
if (opts?.offset != null)
|
|
253
|
+
qs.set("offset", String(opts.offset));
|
|
254
|
+
const suffix = qs.toString() ? `?${qs.toString()}` : "";
|
|
255
|
+
return this.request("GET", `/v1/apps/${encodeURIComponent(app_id)}/versions${suffix}`);
|
|
256
|
+
}
|
|
247
257
|
// ── App iframe RPC endpoints ──────────────────────────────────────────────
|
|
248
258
|
// These mirror the two ops handled by frontend/features/app_ui/app_iframe_host.tsx.
|
|
249
259
|
// The deployed iframe sends postMessage to the parent frontend, which calls
|
package/dist/src/cli.js
CHANGED
|
@@ -29803,6 +29803,14 @@ var LoticsClient = class {
|
|
|
29803
29803
|
);
|
|
29804
29804
|
return result.url;
|
|
29805
29805
|
}
|
|
29806
|
+
/** Deploy history for an app — newest first. Backs `lotics app versions`. */
|
|
29807
|
+
async listAppVersions(app_id, opts) {
|
|
29808
|
+
const qs = new URLSearchParams();
|
|
29809
|
+
if (opts?.limit != null) qs.set("limit", String(opts.limit));
|
|
29810
|
+
if (opts?.offset != null) qs.set("offset", String(opts.offset));
|
|
29811
|
+
const suffix = qs.toString() ? `?${qs.toString()}` : "";
|
|
29812
|
+
return this.request("GET", `/v1/apps/${encodeURIComponent(app_id)}/versions${suffix}`);
|
|
29813
|
+
}
|
|
29806
29814
|
// ── App iframe RPC endpoints ──────────────────────────────────────────────
|
|
29807
29815
|
// These mirror the two ops handled by frontend/features/app_ui/app_iframe_host.tsx.
|
|
29808
29816
|
// The deployed iframe sends postMessage to the parent frontend, which calls
|
|
@@ -30882,6 +30890,9 @@ declare module "lucide-react-native/dist/esm/icons/*" {
|
|
|
30882
30890
|
const classes: { [key: string]: string };
|
|
30883
30891
|
export default classes;
|
|
30884
30892
|
}
|
|
30893
|
+
|
|
30894
|
+
// Plain side-effect CSS imports (@lotics/ui ships .tsx with import "./x.css").
|
|
30895
|
+
declare module "*.css";
|
|
30885
30896
|
`
|
|
30886
30897
|
},
|
|
30887
30898
|
{
|
|
@@ -32526,6 +32537,47 @@ async function appRename(client, args) {
|
|
|
32526
32537
|
if (res.error) throw new Error(res.error);
|
|
32527
32538
|
console.error(`App renamed: "${args.name}" (${meta.app_id})`);
|
|
32528
32539
|
}
|
|
32540
|
+
async function appVersions(client, args) {
|
|
32541
|
+
const appId = args.app_id ?? readAppMeta(process.cwd()).app_id;
|
|
32542
|
+
const { current_version_id, versions } = await client.listAppVersions(appId, {
|
|
32543
|
+
limit: args.limit
|
|
32544
|
+
});
|
|
32545
|
+
if (versions.length === 0) {
|
|
32546
|
+
console.error(`No versions found for ${appId}.`);
|
|
32547
|
+
return;
|
|
32548
|
+
}
|
|
32549
|
+
const fmtWhen = (iso) => {
|
|
32550
|
+
const d = new Date(iso);
|
|
32551
|
+
if (Number.isNaN(d.getTime())) return iso;
|
|
32552
|
+
const p = (n) => String(n).padStart(2, "0");
|
|
32553
|
+
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`;
|
|
32554
|
+
};
|
|
32555
|
+
const rows = versions.map((v) => ({
|
|
32556
|
+
mark: v.id === current_version_id ? "*" : " ",
|
|
32557
|
+
ver: `v${v.version}`,
|
|
32558
|
+
when: fmtWhen(v.created_at),
|
|
32559
|
+
by: v.created_by_name ?? v.created_by ?? "\u2014",
|
|
32560
|
+
status: v.build_status,
|
|
32561
|
+
message: v.message ?? ""
|
|
32562
|
+
}));
|
|
32563
|
+
const colWidth = (key, header) => Math.max(header.length, ...rows.map((r) => r[key].length));
|
|
32564
|
+
const wVer = colWidth("ver", "VER");
|
|
32565
|
+
const wWhen = colWidth("when", "WHEN");
|
|
32566
|
+
const wBy = colWidth("by", "DEPLOYER");
|
|
32567
|
+
const wStatus = colWidth("status", "STATUS");
|
|
32568
|
+
const pad = (s, n) => s.padEnd(n);
|
|
32569
|
+
console.error(
|
|
32570
|
+
`Deploy history \u2014 ${appId} (${versions.length} version${versions.length === 1 ? "" : "s"}, newest first; * = currently served)`
|
|
32571
|
+
);
|
|
32572
|
+
console.log(
|
|
32573
|
+
` ${pad("VER", wVer)} ${pad("WHEN", wWhen)} ${pad("DEPLOYER", wBy)} ${pad("STATUS", wStatus)} MESSAGE`
|
|
32574
|
+
);
|
|
32575
|
+
for (const r of rows) {
|
|
32576
|
+
console.log(
|
|
32577
|
+
`${r.mark} ${pad(r.ver, wVer)} ${pad(r.when, wWhen)} ${pad(r.by, wBy)} ${pad(r.status, wStatus)} ${r.message}`.trimEnd()
|
|
32578
|
+
);
|
|
32579
|
+
}
|
|
32580
|
+
}
|
|
32529
32581
|
function defaultPullTarget(appId, appName) {
|
|
32530
32582
|
const cwdPkgPath = path5.join(process.cwd(), "package.json");
|
|
32531
32583
|
if (fs4.existsSync(cwdPkgPath)) {
|
|
@@ -49154,6 +49206,9 @@ COMMANDS
|
|
|
49154
49206
|
lotics app deploy [-m <message>] Build + upload current dir as a new version
|
|
49155
49207
|
(code + queries only \u2014 workflow bindings are
|
|
49156
49208
|
managed by set_app_workflow / remove_app_workflow)
|
|
49209
|
+
lotics app versions [app_id] Show deploy history newest-first (version,
|
|
49210
|
+
timestamp, deployer, build status, -m message;
|
|
49211
|
+
* marks the currently served version)
|
|
49157
49212
|
lotics app codegen [path] Regenerate .lotics/* (types + field/option ids)
|
|
49158
49213
|
from the manifest + workspace schema \u2014 no deploy
|
|
49159
49214
|
lotics app workflow run <alias> '<json>' Execute a bound app workflow end-to-end
|
|
@@ -49629,6 +49684,7 @@ async function main() {
|
|
|
49629
49684
|
console.error(" lotics app create <name> [path] Scaffold a new app locally");
|
|
49630
49685
|
console.error(" lotics app pull <app_id> [path] Pull an existing app for local editing");
|
|
49631
49686
|
console.error(" lotics app deploy [-m <message>] Build + upload the current directory");
|
|
49687
|
+
console.error(" lotics app versions [app_id] Show deploy history (version, when, who, message)");
|
|
49632
49688
|
console.error(" lotics app codegen [path] Regenerate .lotics/* (types + field ids) \u2014 no deploy");
|
|
49633
49689
|
console.error(" lotics app workflow run <alias> '<json>' Execute a bound app workflow end-to-end");
|
|
49634
49690
|
console.error(" lotics app workflow set <alias> Push the edited src/workflows/<alias>.ts body");
|
|
@@ -49775,6 +49831,11 @@ Available workspaces:`);
|
|
|
49775
49831
|
await appRename(client, { name: newName });
|
|
49776
49832
|
return;
|
|
49777
49833
|
}
|
|
49834
|
+
if (subcommand === "versions") {
|
|
49835
|
+
const appId = toolArgs || void 0;
|
|
49836
|
+
await appVersions(client, { app_id: appId });
|
|
49837
|
+
return;
|
|
49838
|
+
}
|
|
49778
49839
|
if (subcommand === "workflow") {
|
|
49779
49840
|
const action = toolArgs;
|
|
49780
49841
|
const workflowUsage = () => {
|
package/dist/starter_template.js
CHANGED
|
@@ -580,6 +580,9 @@ declare module "lucide-react-native/dist/esm/icons/*" {
|
|
|
580
580
|
const classes: { [key: string]: string };
|
|
581
581
|
export default classes;
|
|
582
582
|
}
|
|
583
|
+
|
|
584
|
+
// Plain side-effect CSS imports (@lotics/ui ships .tsx with import "./x.css").
|
|
585
|
+
declare module "*.css";
|
|
583
586
|
`,
|
|
584
587
|
},
|
|
585
588
|
{
|