@lotics/cli 0.46.0 → 0.48.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.d.ts +0 -1
- package/dist/app_commands.js +7 -10
- package/dist/args.d.ts +2 -3
- package/dist/args.js +2 -6
- package/dist/args.test.js +3 -14
- package/dist/cli.js +6 -10
- package/dist/client.d.ts +15 -21
- package/dist/client.js +10 -10
- package/dist/dev/rpc_handler.d.ts +1 -1
- package/dist/dev/rpc_handler.js +8 -0
- package/dist/dev/rpc_handler.test.js +21 -0
- package/dist/src/cli.js +29 -26
- package/package.json +1 -1
package/dist/app_commands.d.ts
CHANGED
|
@@ -119,7 +119,6 @@ export declare function undeclaredCapabilities(sourceText: string, declared: Rec
|
|
|
119
119
|
export declare function appDeploy(client: LoticsClient, args: {
|
|
120
120
|
projectDir?: string;
|
|
121
121
|
message?: string;
|
|
122
|
-
forceWorkflowSync?: boolean;
|
|
123
122
|
}): Promise<void>;
|
|
124
123
|
/**
|
|
125
124
|
* `lotics app dev [path] [--port=5174] [--vite-port=5173]`
|
package/dist/app_commands.js
CHANGED
|
@@ -388,20 +388,17 @@ export async function appDeploy(client, args) {
|
|
|
388
388
|
dist_archive: fs.readFileSync(tmpDist),
|
|
389
389
|
prev_version_id: meta.current_version_id,
|
|
390
390
|
message: args.message,
|
|
391
|
-
// Sync apps.workflows from the manifest. Server validates each
|
|
392
|
-
// workflow_id exists in the workspace before committing.
|
|
393
|
-
workflows: meta.workflows ?? {},
|
|
394
391
|
// Sync apps.queries from the manifest. Server validates each query
|
|
395
392
|
// template (parseQueryNode, table access, param coverage).
|
|
396
393
|
queries: meta.queries ?? {},
|
|
397
|
-
// Capabilities are manifest-authoritative (like
|
|
398
|
-
//
|
|
399
|
-
//
|
|
400
|
-
//
|
|
394
|
+
// Capabilities are manifest-authoritative (like queries): always send,
|
|
395
|
+
// defaulting to `{}` when the manifest declares none — so deleting the
|
|
396
|
+
// `capabilities` block turns every capability OFF on the next deploy
|
|
397
|
+
// (fail-safe; the declaration is the grant).
|
|
401
398
|
capabilities: meta.capabilities ?? {},
|
|
402
|
-
//
|
|
403
|
-
//
|
|
404
|
-
|
|
399
|
+
// Workflow bindings are NOT a deploy concern — set_app_workflow /
|
|
400
|
+
// remove_app_workflow own apps.workflows. The manifest's `workflows`
|
|
401
|
+
// map is a pulled reflection used only for the .d.ts codegen above.
|
|
405
402
|
});
|
|
406
403
|
writeAppMeta(projectDir, {
|
|
407
404
|
...meta,
|
package/dist/args.d.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Splits `process.argv.slice(2)` into a command / subcommand / positional
|
|
5
5
|
* (`toolArgs`) / remaining-positionals (`restArgs`) shape plus typed `flags`.
|
|
6
6
|
* Value-taking flags (`-m`, `--api-key`, …) consume the next token; boolean
|
|
7
|
-
* flags (`--
|
|
8
|
-
*
|
|
7
|
+
* flags (`--json`, `--local`, …) toggle. Anything not matching a known flag is
|
|
8
|
+
* positional.
|
|
9
9
|
*
|
|
10
10
|
* Lives apart from `cli.ts` so it can be unit-tested — `cli.ts` runs `main()`
|
|
11
11
|
* on import, so importing the parser from there would execute the CLI.
|
|
@@ -26,7 +26,6 @@ export declare function parseArgs(argv: string[]): {
|
|
|
26
26
|
name?: string;
|
|
27
27
|
timezone?: string;
|
|
28
28
|
message?: string;
|
|
29
|
-
forceWorkflowSync: boolean;
|
|
30
29
|
local: boolean;
|
|
31
30
|
all: boolean;
|
|
32
31
|
version: boolean;
|
package/dist/args.js
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Splits `process.argv.slice(2)` into a command / subcommand / positional
|
|
5
5
|
* (`toolArgs`) / remaining-positionals (`restArgs`) shape plus typed `flags`.
|
|
6
6
|
* Value-taking flags (`-m`, `--api-key`, …) consume the next token; boolean
|
|
7
|
-
* flags (`--
|
|
8
|
-
*
|
|
7
|
+
* flags (`--json`, `--local`, …) toggle. Anything not matching a known flag is
|
|
8
|
+
* positional.
|
|
9
9
|
*
|
|
10
10
|
* Lives apart from `cli.ts` so it can be unit-tested — `cli.ts` runs `main()`
|
|
11
11
|
* on import, so importing the parser from there would execute the CLI.
|
|
@@ -22,7 +22,6 @@ export function parseArgs(argv) {
|
|
|
22
22
|
name: undefined,
|
|
23
23
|
timezone: undefined,
|
|
24
24
|
message: undefined,
|
|
25
|
-
forceWorkflowSync: false,
|
|
26
25
|
local: false,
|
|
27
26
|
all: false,
|
|
28
27
|
version: false,
|
|
@@ -69,9 +68,6 @@ export function parseArgs(argv) {
|
|
|
69
68
|
case "--message":
|
|
70
69
|
flags.message = argv[++i];
|
|
71
70
|
break;
|
|
72
|
-
case "--force-workflow-sync":
|
|
73
|
-
flags.forceWorkflowSync = true;
|
|
74
|
-
break;
|
|
75
71
|
case "--local":
|
|
76
72
|
flags.local = true;
|
|
77
73
|
break;
|
package/dist/args.test.js
CHANGED
|
@@ -8,8 +8,8 @@ describe("parseArgs", () => {
|
|
|
8
8
|
expect(r.toolArgs).toBe("my message");
|
|
9
9
|
expect(r.restArgs).toEqual([]);
|
|
10
10
|
});
|
|
11
|
-
// `app deploy` regression: `-m`
|
|
12
|
-
//
|
|
11
|
+
// `app deploy` regression: `-m` must be parsed as a flag, not silently
|
|
12
|
+
// consumed as the positional message.
|
|
13
13
|
it("parses -m as the message flag", () => {
|
|
14
14
|
const r = parseArgs(["app", "deploy", "-m", "a message"]);
|
|
15
15
|
expect(r.flags.message).toBe("a message");
|
|
@@ -19,19 +19,8 @@ describe("parseArgs", () => {
|
|
|
19
19
|
const r = parseArgs(["app", "deploy", "--message", "a message"]);
|
|
20
20
|
expect(r.flags.message).toBe("a message");
|
|
21
21
|
});
|
|
22
|
-
it("
|
|
23
|
-
const r = parseArgs(["app", "deploy", "msg", "--force-workflow-sync"]);
|
|
24
|
-
expect(r.flags.forceWorkflowSync).toBe(true);
|
|
25
|
-
expect(r.toolArgs).toBe("msg");
|
|
26
|
-
});
|
|
27
|
-
it("parses --force-workflow-sync before -m without eating the message", () => {
|
|
28
|
-
const r = parseArgs(["app", "deploy", "--force-workflow-sync", "-m", "msg"]);
|
|
29
|
-
expect(r.flags.forceWorkflowSync).toBe(true);
|
|
30
|
-
expect(r.flags.message).toBe("msg");
|
|
31
|
-
});
|
|
32
|
-
it("defaults forceWorkflowSync to false and message to undefined", () => {
|
|
22
|
+
it("defaults message to undefined for a bare deploy", () => {
|
|
33
23
|
const r = parseArgs(["app", "deploy"]);
|
|
34
|
-
expect(r.flags.forceWorkflowSync).toBe(false);
|
|
35
24
|
expect(r.flags.message).toBeUndefined();
|
|
36
25
|
});
|
|
37
26
|
it("parses --workspace as a value flag", () => {
|
package/dist/cli.js
CHANGED
|
@@ -60,10 +60,9 @@ COMMANDS
|
|
|
60
60
|
Download all files on a record file field
|
|
61
61
|
lotics app create <name> [path] Create a new custom-code app + scaffold locally
|
|
62
62
|
lotics app pull <app_id> [path] Bootstrap full local env (source + npm install + types)
|
|
63
|
-
lotics app deploy [-m <message>]
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
workflow aliases; default refuses)
|
|
63
|
+
lotics app deploy [-m <message>] Build + upload current dir as a new version
|
|
64
|
+
(code + queries only — workflow bindings are
|
|
65
|
+
managed by set_app_workflow / remove_app_workflow)
|
|
67
66
|
lotics app subdomain <new-subdomain> Rename the app's public <slug>.lotics.app address
|
|
68
67
|
lotics app rename "<new name>" Rename the app's display name (launcher title)
|
|
69
68
|
lotics app dev [path] Run the app locally with HMR (RPC forwarded to prod)
|
|
@@ -527,8 +526,7 @@ async function main() {
|
|
|
527
526
|
console.error("Usage:");
|
|
528
527
|
console.error(" lotics app create <name> [path] Scaffold a new app locally");
|
|
529
528
|
console.error(" lotics app pull <app_id> [path] Pull an existing app for local editing");
|
|
530
|
-
console.error(" lotics app deploy [-m <message>]
|
|
531
|
-
console.error(" Build + upload the current directory");
|
|
529
|
+
console.error(" lotics app deploy [-m <message>] Build + upload the current directory");
|
|
532
530
|
console.error(" lotics app subdomain <new-subdomain> Rename the app's public <slug>.lotics.app address");
|
|
533
531
|
console.error(" lotics app rename \"<new name>\" Rename the app's display name (launcher title)");
|
|
534
532
|
console.error(" lotics app dev [path] Run the app locally with HMR + RPC forwarding");
|
|
@@ -650,11 +648,9 @@ async function main() {
|
|
|
650
648
|
return;
|
|
651
649
|
}
|
|
652
650
|
if (subcommand === "deploy") {
|
|
653
|
-
// The message is either `-m <message>` or a bare positional arg after
|
|
654
|
-
// `deploy`. `--force-workflow-sync` is a parsed boolean flag, valid in
|
|
655
|
-
// any position.
|
|
651
|
+
// The message is either `-m <message>` or a bare positional arg after `deploy`.
|
|
656
652
|
const message = flags.message ?? toolArgs;
|
|
657
|
-
await appDeploy(client, { message
|
|
653
|
+
await appDeploy(client, { message });
|
|
658
654
|
return;
|
|
659
655
|
}
|
|
660
656
|
if (subcommand === "subdomain") {
|
package/dist/client.d.ts
CHANGED
|
@@ -183,6 +183,21 @@ export declare class LoticsClient {
|
|
|
183
183
|
image: string | null;
|
|
184
184
|
}>;
|
|
185
185
|
}>;
|
|
186
|
+
/**
|
|
187
|
+
* Resolve the full option set (key, label, color) of a named query's select
|
|
188
|
+
* columns — the picker companion to `appQuery`. Mirrors
|
|
189
|
+
* POST /v1/apps/{app_id}/field-options.
|
|
190
|
+
*/
|
|
191
|
+
appFieldOptions(app_id: string, alias: string): Promise<{
|
|
192
|
+
fields: Record<string, {
|
|
193
|
+
label: string;
|
|
194
|
+
options: Array<{
|
|
195
|
+
key: string;
|
|
196
|
+
label: string;
|
|
197
|
+
color: string;
|
|
198
|
+
}>;
|
|
199
|
+
}>;
|
|
200
|
+
}>;
|
|
186
201
|
/**
|
|
187
202
|
* Execute a workflow by alias declared in package.json#lotics.workflows.
|
|
188
203
|
* Mirrors POST /v1/apps/{app_id}/workflows/{alias}/execute.
|
|
@@ -235,19 +250,6 @@ export declare class LoticsClient {
|
|
|
235
250
|
dist_archive: Buffer;
|
|
236
251
|
prev_version_id?: string | null;
|
|
237
252
|
message?: string | null;
|
|
238
|
-
/**
|
|
239
|
-
* Alias → workflow declaration map from the app's `package.json#lotics.workflows`.
|
|
240
|
-
* Each value is a `{ workflow_id, inputs? }` object — inputs declares a typed
|
|
241
|
-
* schema or is omitted when the workflow accepts no typed inputs. Always sent
|
|
242
|
-
* (empty object when none declared) so the server can overwrite apps.workflows
|
|
243
|
-
* authoritatively. Deleting an alias from the manifest removes it from the DB
|
|
244
|
-
* on next deploy — gated by the destructive-removal guard unless
|
|
245
|
-
* `force_workflow_sync` is true.
|
|
246
|
-
*/
|
|
247
|
-
workflows?: Record<string, {
|
|
248
|
-
workflow_id: string;
|
|
249
|
-
inputs?: Record<string, unknown>;
|
|
250
|
-
}>;
|
|
251
253
|
/**
|
|
252
254
|
* Alias → query declaration map from `package.json#lotics.queries`. Each
|
|
253
255
|
* value is `{ ast, params? }` — a fixed query AST template and an optional
|
|
@@ -267,14 +269,6 @@ export declare class LoticsClient {
|
|
|
267
269
|
capabilities?: {
|
|
268
270
|
comments?: boolean;
|
|
269
271
|
};
|
|
270
|
-
/**
|
|
271
|
-
* Opt into destructive workflow removal. When false/absent, the server
|
|
272
|
-
* rejects a deploy whose `workflows` map is missing aliases that exist
|
|
273
|
-
* on the App row. Set true to deploy anyway and wipe the missing aliases —
|
|
274
|
-
* the user is asserting they know what they're doing. Wired to CLI flag
|
|
275
|
-
* `--force-workflow-sync`.
|
|
276
|
-
*/
|
|
277
|
-
force_workflow_sync?: boolean;
|
|
278
272
|
}): Promise<{
|
|
279
273
|
version_id: string;
|
|
280
274
|
version_number: number;
|
package/dist/client.js
CHANGED
|
@@ -187,6 +187,14 @@ export class LoticsClient {
|
|
|
187
187
|
const qs = group_id ? `?group_id=${encodeURIComponent(group_id)}` : "";
|
|
188
188
|
return this.request("GET", `/v1/apps/${encodeURIComponent(app_id)}/members${qs}`);
|
|
189
189
|
}
|
|
190
|
+
/**
|
|
191
|
+
* Resolve the full option set (key, label, color) of a named query's select
|
|
192
|
+
* columns — the picker companion to `appQuery`. Mirrors
|
|
193
|
+
* POST /v1/apps/{app_id}/field-options.
|
|
194
|
+
*/
|
|
195
|
+
async appFieldOptions(app_id, alias) {
|
|
196
|
+
return this.request("POST", `/v1/apps/${encodeURIComponent(app_id)}/field-options`, { alias });
|
|
197
|
+
}
|
|
190
198
|
/**
|
|
191
199
|
* Execute a workflow by alias declared in package.json#lotics.workflows.
|
|
192
200
|
* Mirrors POST /v1/apps/{app_id}/workflows/{alias}/execute.
|
|
@@ -239,11 +247,9 @@ export class LoticsClient {
|
|
|
239
247
|
if (args.message) {
|
|
240
248
|
formData.append("message", args.message);
|
|
241
249
|
}
|
|
242
|
-
// Always send workflows — empty object is meaningful (clears any
|
|
243
|
-
// previously-declared aliases). Server validates each entry.
|
|
244
|
-
formData.append("workflows", JSON.stringify(args.workflows ?? {}));
|
|
245
250
|
// Always send queries — empty object clears any previously-declared
|
|
246
|
-
// named queries. Server validates each template.
|
|
251
|
+
// named queries. Server validates each template. (Workflow bindings are
|
|
252
|
+
// not sent: set_app_workflow / remove_app_workflow own apps.workflows.)
|
|
247
253
|
formData.append("queries", JSON.stringify(args.queries ?? {}));
|
|
248
254
|
// capabilities is manifest-authoritative — the caller always passes it
|
|
249
255
|
// (`{}` when none declared), so a deploy turns off any capability the
|
|
@@ -251,12 +257,6 @@ export class LoticsClient {
|
|
|
251
257
|
if (args.capabilities !== undefined) {
|
|
252
258
|
formData.append("capabilities", JSON.stringify(args.capabilities));
|
|
253
259
|
}
|
|
254
|
-
// Only post the override flag when the user explicitly opts in. The
|
|
255
|
-
// server defaults to "honor the guard" — opt-in is loud, opt-out
|
|
256
|
-
// requires intent.
|
|
257
|
-
if (args.force_workflow_sync) {
|
|
258
|
-
formData.append("force_workflow_sync", "true");
|
|
259
|
-
}
|
|
260
260
|
const url = `${this.baseUrl}/v1/apps/${encodeURIComponent(args.app_id)}/versions`;
|
|
261
261
|
const response = await fetch(url, {
|
|
262
262
|
method: "POST",
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* { message }. Same shape as the production iframe-host's error path.
|
|
7
7
|
*/
|
|
8
8
|
import { LoticsClient } from "../client.js";
|
|
9
|
-
export type RpcOp = "query" | "workflow" | "members" | "context" | "upload_url" | "upload_complete" | "comments.list" | "comments.create" | "comments.update" | "comments.delete" | "comments.counts";
|
|
9
|
+
export type RpcOp = "query" | "field_options" | "workflow" | "members" | "context" | "upload_url" | "upload_complete" | "comments.list" | "comments.create" | "comments.update" | "comments.delete" | "comments.counts";
|
|
10
10
|
export interface RpcRequest {
|
|
11
11
|
app_id: string;
|
|
12
12
|
op: RpcOp;
|
package/dist/dev/rpc_handler.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
const SUPPORTED_OPS = new Set([
|
|
9
9
|
"query",
|
|
10
|
+
"field_options",
|
|
10
11
|
"workflow",
|
|
11
12
|
"members",
|
|
12
13
|
"context",
|
|
@@ -52,6 +53,13 @@ export async function dispatchRpc(client, body, opts) {
|
|
|
52
53
|
count: p.count,
|
|
53
54
|
});
|
|
54
55
|
}
|
|
56
|
+
case "field_options": {
|
|
57
|
+
const p = body.payload;
|
|
58
|
+
if (!p || typeof p.alias !== "string") {
|
|
59
|
+
throw new Error("field_options payload must include `alias`");
|
|
60
|
+
}
|
|
61
|
+
return client.appFieldOptions(body.app_id, p.alias);
|
|
62
|
+
}
|
|
55
63
|
case "workflow": {
|
|
56
64
|
const p = body.payload;
|
|
57
65
|
if (!p || typeof p.alias !== "string") {
|
|
@@ -27,6 +27,27 @@ describe("dispatchRpc — context op", () => {
|
|
|
27
27
|
await expect(dispatchRpc(client, { app_id: "app_x", op: "bogus", payload: {} })).rejects.toThrow(/Unknown RPC op/);
|
|
28
28
|
});
|
|
29
29
|
});
|
|
30
|
+
describe("dispatchRpc — field_options op", () => {
|
|
31
|
+
it("forwards the alias to appFieldOptions and returns its { fields } shape", async () => {
|
|
32
|
+
const fields = {
|
|
33
|
+
status: {
|
|
34
|
+
label: "Status",
|
|
35
|
+
options: [{ key: "opt_open", label: "Open", color: "blue" }],
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
const client = mockClient({ appFieldOptions: async () => ({ fields }) });
|
|
39
|
+
const result = await dispatchRpc(client, {
|
|
40
|
+
app_id: "app_x",
|
|
41
|
+
op: "field_options",
|
|
42
|
+
payload: { alias: "records" },
|
|
43
|
+
});
|
|
44
|
+
expect(result).toEqual({ fields });
|
|
45
|
+
});
|
|
46
|
+
it("requires an alias in the payload", async () => {
|
|
47
|
+
const client = mockClient({ appFieldOptions: async () => ({ fields: {} }) });
|
|
48
|
+
await expect(dispatchRpc(client, { app_id: "app_x", op: "field_options", payload: {} })).rejects.toThrow(/alias/);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
30
51
|
describe("dispatchRpc — comment ops", () => {
|
|
31
52
|
it("comments.list forwards to appGetRecordComments, wrapped as { comments }", async () => {
|
|
32
53
|
const comments = [{ id: "cmt_1", content: "hi" }];
|
package/dist/src/cli.js
CHANGED
|
@@ -29772,6 +29772,14 @@ var LoticsClient = class {
|
|
|
29772
29772
|
const qs = group_id ? `?group_id=${encodeURIComponent(group_id)}` : "";
|
|
29773
29773
|
return this.request("GET", `/v1/apps/${encodeURIComponent(app_id)}/members${qs}`);
|
|
29774
29774
|
}
|
|
29775
|
+
/**
|
|
29776
|
+
* Resolve the full option set (key, label, color) of a named query's select
|
|
29777
|
+
* columns — the picker companion to `appQuery`. Mirrors
|
|
29778
|
+
* POST /v1/apps/{app_id}/field-options.
|
|
29779
|
+
*/
|
|
29780
|
+
async appFieldOptions(app_id, alias) {
|
|
29781
|
+
return this.request("POST", `/v1/apps/${encodeURIComponent(app_id)}/field-options`, { alias });
|
|
29782
|
+
}
|
|
29775
29783
|
/**
|
|
29776
29784
|
* Execute a workflow by alias declared in package.json#lotics.workflows.
|
|
29777
29785
|
* Mirrors POST /v1/apps/{app_id}/workflows/{alias}/execute.
|
|
@@ -29858,14 +29866,10 @@ var LoticsClient = class {
|
|
|
29858
29866
|
if (args.message) {
|
|
29859
29867
|
formData.append("message", args.message);
|
|
29860
29868
|
}
|
|
29861
|
-
formData.append("workflows", JSON.stringify(args.workflows ?? {}));
|
|
29862
29869
|
formData.append("queries", JSON.stringify(args.queries ?? {}));
|
|
29863
29870
|
if (args.capabilities !== void 0) {
|
|
29864
29871
|
formData.append("capabilities", JSON.stringify(args.capabilities));
|
|
29865
29872
|
}
|
|
29866
|
-
if (args.force_workflow_sync) {
|
|
29867
|
-
formData.append("force_workflow_sync", "true");
|
|
29868
|
-
}
|
|
29869
29873
|
const url = `${this.baseUrl}/v1/apps/${encodeURIComponent(args.app_id)}/versions`;
|
|
29870
29874
|
const response = await fetch(url, {
|
|
29871
29875
|
method: "POST",
|
|
@@ -30724,6 +30728,7 @@ import { spawn } from "node:child_process";
|
|
|
30724
30728
|
// src/dev/rpc_handler.ts
|
|
30725
30729
|
var SUPPORTED_OPS = /* @__PURE__ */ new Set([
|
|
30726
30730
|
"query",
|
|
30731
|
+
"field_options",
|
|
30727
30732
|
"workflow",
|
|
30728
30733
|
"members",
|
|
30729
30734
|
"context",
|
|
@@ -30765,6 +30770,13 @@ async function dispatchRpc(client, body, opts) {
|
|
|
30765
30770
|
count: p.count
|
|
30766
30771
|
});
|
|
30767
30772
|
}
|
|
30773
|
+
case "field_options": {
|
|
30774
|
+
const p = body.payload;
|
|
30775
|
+
if (!p || typeof p.alias !== "string") {
|
|
30776
|
+
throw new Error("field_options payload must include `alias`");
|
|
30777
|
+
}
|
|
30778
|
+
return client.appFieldOptions(body.app_id, p.alias);
|
|
30779
|
+
}
|
|
30768
30780
|
case "workflow": {
|
|
30769
30781
|
const p = body.payload;
|
|
30770
30782
|
if (!p || typeof p.alias !== "string") {
|
|
@@ -31643,20 +31655,17 @@ async function appDeploy(client, args) {
|
|
|
31643
31655
|
dist_archive: fs3.readFileSync(tmpDist),
|
|
31644
31656
|
prev_version_id: meta.current_version_id,
|
|
31645
31657
|
message: args.message,
|
|
31646
|
-
// Sync apps.workflows from the manifest. Server validates each
|
|
31647
|
-
// workflow_id exists in the workspace before committing.
|
|
31648
|
-
workflows: meta.workflows ?? {},
|
|
31649
31658
|
// Sync apps.queries from the manifest. Server validates each query
|
|
31650
31659
|
// template (parseQueryNode, table access, param coverage).
|
|
31651
31660
|
queries: meta.queries ?? {},
|
|
31652
|
-
// Capabilities are manifest-authoritative (like
|
|
31653
|
-
//
|
|
31654
|
-
//
|
|
31655
|
-
//
|
|
31656
|
-
capabilities: meta.capabilities ?? {}
|
|
31657
|
-
//
|
|
31658
|
-
//
|
|
31659
|
-
|
|
31661
|
+
// Capabilities are manifest-authoritative (like queries): always send,
|
|
31662
|
+
// defaulting to `{}` when the manifest declares none — so deleting the
|
|
31663
|
+
// `capabilities` block turns every capability OFF on the next deploy
|
|
31664
|
+
// (fail-safe; the declaration is the grant).
|
|
31665
|
+
capabilities: meta.capabilities ?? {}
|
|
31666
|
+
// Workflow bindings are NOT a deploy concern — set_app_workflow /
|
|
31667
|
+
// remove_app_workflow own apps.workflows. The manifest's `workflows`
|
|
31668
|
+
// map is a pulled reflection used only for the .d.ts codegen above.
|
|
31660
31669
|
});
|
|
31661
31670
|
writeAppMeta(projectDir, {
|
|
31662
31671
|
...meta,
|
|
@@ -31756,7 +31765,6 @@ function parseArgs(argv) {
|
|
|
31756
31765
|
name: void 0,
|
|
31757
31766
|
timezone: void 0,
|
|
31758
31767
|
message: void 0,
|
|
31759
|
-
forceWorkflowSync: false,
|
|
31760
31768
|
local: false,
|
|
31761
31769
|
all: false,
|
|
31762
31770
|
version: false,
|
|
@@ -31803,9 +31811,6 @@ function parseArgs(argv) {
|
|
|
31803
31811
|
case "--message":
|
|
31804
31812
|
flags.message = argv[++i2];
|
|
31805
31813
|
break;
|
|
31806
|
-
case "--force-workflow-sync":
|
|
31807
|
-
flags.forceWorkflowSync = true;
|
|
31808
|
-
break;
|
|
31809
31814
|
case "--local":
|
|
31810
31815
|
flags.local = true;
|
|
31811
31816
|
break;
|
|
@@ -47595,10 +47600,9 @@ COMMANDS
|
|
|
47595
47600
|
Download all files on a record file field
|
|
47596
47601
|
lotics app create <name> [path] Create a new custom-code app + scaffold locally
|
|
47597
47602
|
lotics app pull <app_id> [path] Bootstrap full local env (source + npm install + types)
|
|
47598
|
-
lotics app deploy [-m <message>]
|
|
47599
|
-
|
|
47600
|
-
|
|
47601
|
-
workflow aliases; default refuses)
|
|
47603
|
+
lotics app deploy [-m <message>] Build + upload current dir as a new version
|
|
47604
|
+
(code + queries only \u2014 workflow bindings are
|
|
47605
|
+
managed by set_app_workflow / remove_app_workflow)
|
|
47602
47606
|
lotics app subdomain <new-subdomain> Rename the app's public <slug>.lotics.app address
|
|
47603
47607
|
lotics app rename "<new name>" Rename the app's display name (launcher title)
|
|
47604
47608
|
lotics app dev [path] Run the app locally with HMR (RPC forwarded to prod)
|
|
@@ -48027,8 +48031,7 @@ async function main() {
|
|
|
48027
48031
|
console.error("Usage:");
|
|
48028
48032
|
console.error(" lotics app create <name> [path] Scaffold a new app locally");
|
|
48029
48033
|
console.error(" lotics app pull <app_id> [path] Pull an existing app for local editing");
|
|
48030
|
-
console.error(" lotics app deploy [-m <message>]
|
|
48031
|
-
console.error(" Build + upload the current directory");
|
|
48034
|
+
console.error(" lotics app deploy [-m <message>] Build + upload the current directory");
|
|
48032
48035
|
console.error(" lotics app subdomain <new-subdomain> Rename the app's public <slug>.lotics.app address");
|
|
48033
48036
|
console.error(` lotics app rename "<new name>" Rename the app's display name (launcher title)`);
|
|
48034
48037
|
console.error(" lotics app dev [path] Run the app locally with HMR + RPC forwarding");
|
|
@@ -48145,7 +48148,7 @@ Available workspaces:`);
|
|
|
48145
48148
|
}
|
|
48146
48149
|
if (subcommand === "deploy") {
|
|
48147
48150
|
const message = flags.message ?? toolArgs;
|
|
48148
|
-
await appDeploy(client, { message
|
|
48151
|
+
await appDeploy(client, { message });
|
|
48149
48152
|
return;
|
|
48150
48153
|
}
|
|
48151
48154
|
if (subcommand === "subdomain") {
|