@lotics/cli 0.57.0 → 0.62.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 +37 -0
- package/dist/app_commands.d.ts +165 -2
- package/dist/app_commands.js +803 -7
- package/dist/app_commands.test.js +569 -2
- package/dist/app_workflow_check.d.ts +77 -0
- package/dist/app_workflow_check.js +169 -0
- package/dist/app_workflow_check.test.d.ts +1 -0
- package/dist/app_workflow_check.test.js +166 -0
- package/dist/args.d.ts +4 -0
- package/dist/args.js +9 -0
- package/dist/args.test.js +12 -0
- package/dist/child_env.d.ts +13 -0
- package/dist/child_env.js +24 -0
- package/dist/cli.js +144 -30
- package/dist/client.d.ts +58 -0
- package/dist/client.js +85 -0
- package/dist/dev/server.js +2 -1
- package/dist/generate_app_fields.d.ts +54 -0
- package/dist/generate_app_fields.js +148 -0
- package/dist/generate_app_fields.test.d.ts +1 -0
- package/dist/generate_app_fields.test.js +108 -0
- package/dist/inputs.d.ts +38 -0
- package/dist/inputs.js +50 -0
- package/dist/inputs.test.d.ts +1 -0
- package/dist/inputs.test.js +89 -0
- package/dist/src/cli.js +1208 -187
- package/dist/starter_template.js +72 -2
- package/dist/starter_template.test.js +15 -0
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -149,6 +149,43 @@ Edits mutate the file in place via an atomic temp-file + rename. Unknown OOXML c
|
|
|
149
149
|
|
|
150
150
|
Run `lotics xlsx` or `lotics docx` with no subcommand for the full list.
|
|
151
151
|
|
|
152
|
+
## Custom-code apps
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
# Scaffold / pull / deploy a Vite+React+TS app project
|
|
156
|
+
lotics app create "Sales Desk" # scaffold + deploy v1
|
|
157
|
+
lotics app pull app_... # bootstrap an existing app locally
|
|
158
|
+
lotics app deploy -m "Add quote drawer" # build + upload a new version
|
|
159
|
+
|
|
160
|
+
# Regenerate .lotics/* WITHOUT a deploy: the .d.ts type companions (always) +
|
|
161
|
+
# the runtime app_fields.ts (when authenticated) — F/OPT maps that address
|
|
162
|
+
# fields + select options by stable display-name aliases instead of opaque ids.
|
|
163
|
+
lotics app codegen # import { F, OPT } from "../.lotics/app_fields"
|
|
164
|
+
|
|
165
|
+
# Execute a bound app workflow end-to-end (inputs: inline / @file / stdin)
|
|
166
|
+
lotics app workflow run issueInvoice '{"record_id":"rec_..."}'
|
|
167
|
+
cat inputs.json | lotics app workflow run importRates # bulk inputs bypass ARG_MAX
|
|
168
|
+
# Honest post-run harvest: created records + a paste-ready cleanup plan + the
|
|
169
|
+
# caveat (external/notification calls can't be auto-undone; sub-workflows may run).
|
|
170
|
+
lotics app workflow run issueInvoice '{...}' --print-created
|
|
171
|
+
lotics app workflow run issueInvoice '{...}' --cleanup # also deletes created records (NOT a rollback)
|
|
172
|
+
|
|
173
|
+
# Edit workflow bodies as files. `app pull` writes src/workflows/<alias>.ts (the
|
|
174
|
+
# faithful server source, wrapped + referencing its .lotics/workflows/<alias>.globals.d.ts);
|
|
175
|
+
# edit the body, then push it back through set_app_workflow — the server verifies it
|
|
176
|
+
# (deploy still never authors workflows). Bodies are locally typecheckable with
|
|
177
|
+
# `app workflow check` (one isolated program per alias = the same verdict as `set`):
|
|
178
|
+
lotics app workflow pull # rewrite src/workflows/*.ts + globals from the server
|
|
179
|
+
lotics app workflow check # typecheck every body locally ([alias] for one)
|
|
180
|
+
lotics app workflow set issueInvoice # push the edited src/workflows/issueInvoice.ts
|
|
181
|
+
|
|
182
|
+
# Dev-link @lotics/ui to the monorepo's packages/ui/src for live HMR (monorepo only)
|
|
183
|
+
lotics ui link card # edits to packages/ui/src go live
|
|
184
|
+
lotics ui link card --remove # finalize: PR + publish, then drop the alias
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
`app codegen` reads `package.json#lotics.queries` to decide which tables to put in `app_fields.ts`; widen the set with `package.json#lotics.codegen.tables` (an array of `tbl_…` ids) for tables the app only writes via workflows.
|
|
188
|
+
|
|
152
189
|
## SDK
|
|
153
190
|
|
|
154
191
|
```typescript
|
package/dist/app_commands.d.ts
CHANGED
|
@@ -42,6 +42,74 @@ export type AppAgentDeclaration = {
|
|
|
42
42
|
inputs?: Record<string, unknown>;
|
|
43
43
|
outputs?: Record<string, unknown>;
|
|
44
44
|
};
|
|
45
|
+
/**
|
|
46
|
+
* The `async function __workflow(...)` wrapper a workflow body sits inside —
|
|
47
|
+
* the SAME envelope the server compiles the body within at `set_app_workflow`
|
|
48
|
+
* verify time (GAP-59). Carried so a body that uses top-level `await` and ends
|
|
49
|
+
* with `return({...})` typechecks locally exactly as the server checks it. The
|
|
50
|
+
* server returns the canonical strings (`getAppWorkflowDts`); these are the
|
|
51
|
+
* offline fallback when the dts fetch fails so the file is still wrapped — a
|
|
52
|
+
* test pins them equal to the server's, so they can't drift.
|
|
53
|
+
*/
|
|
54
|
+
export declare const FALLBACK_ENVELOPE_PREFIX = "async function __workflow(): Promise<__WorkflowReturn | void> {\n";
|
|
55
|
+
export declare const FALLBACK_ENVELOPE_SUFFIX = "\n}";
|
|
56
|
+
export interface WorkflowEnvelope {
|
|
57
|
+
prefix: string;
|
|
58
|
+
suffix: string;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Write `.lotics/workflows/<alias>.globals.d.ts` = the server-generated ambient
|
|
62
|
+
* declarations the body typechecks against. Idempotent. Returns the path.
|
|
63
|
+
*/
|
|
64
|
+
export declare function writeWorkflowGlobals(projectDir: string, alias: string, dts: string): string;
|
|
65
|
+
/**
|
|
66
|
+
* Write `src/workflows/<alias>.ts` = header (triple-slash reference + comments)
|
|
67
|
+
* + the body wrapped in the `__workflow` envelope. Idempotent (a re-pull
|
|
68
|
+
* overwrites with the current server body). The raw `source` round-trips on
|
|
69
|
+
* `set` (the header + wrapper are stripped). Exported for direct unit testing —
|
|
70
|
+
* the surrounding pull shells out to `tar`/`npm`.
|
|
71
|
+
*/
|
|
72
|
+
export declare function writeWorkflowFile(projectDir: string, alias: string, source: string, envelope?: WorkflowEnvelope): string;
|
|
73
|
+
/**
|
|
74
|
+
* Strip the CLI bookkeeping back off a workflow body before pushing it: the
|
|
75
|
+
* triple-slash reference + the `//` header comments + the `export {};` marker +
|
|
76
|
+
* blank lines, then the `__workflow` envelope (the opening
|
|
77
|
+
* `async function __workflow(...) {` line and the matching trailing `}`). `set`
|
|
78
|
+
* sends ONLY the JS-subset body the author edited — the server stays the single
|
|
79
|
+
* verifier.
|
|
80
|
+
*
|
|
81
|
+
* The strip is anchored on the GENERATED bookkeeping, never on "the file happens
|
|
82
|
+
* to start with comments": the leading comment/marker/blank block is only peeled
|
|
83
|
+
* when it is immediately followed by the `__workflow` wrapper opener (the exact
|
|
84
|
+
* shape `writeWorkflowFile` produces). A hand-written, wrapper-LESS body whose
|
|
85
|
+
* first lines are comments therefore round-trips unchanged — its comments are
|
|
86
|
+
* real source, not bookkeeping, and must not be silently eaten.
|
|
87
|
+
*/
|
|
88
|
+
export declare function stripWorkflowHeader(content: string): string;
|
|
89
|
+
/**
|
|
90
|
+
* Add the workflow-body globs to the main `tsconfig.json`'s `exclude` if missing,
|
|
91
|
+
* preserving every other exclude. The starter ships these excludes already, but
|
|
92
|
+
* an app SCAFFOLDED before this CLI release (or one with a hand-written tsconfig)
|
|
93
|
+
* doesn't — and pulling bodies into it would otherwise break its
|
|
94
|
+
* `npm run typecheck`: the bodies pull the app's DOM lib (the server doesn't) and
|
|
95
|
+
* the per-alias ambient globals collide on `trigger`. Idempotent — a second pull
|
|
96
|
+
* is a no-op. Warns exactly what it added. A missing/unparseable tsconfig is a
|
|
97
|
+
* non-fatal warn (the pull itself still succeeds); the author fixes the config.
|
|
98
|
+
*/
|
|
99
|
+
export declare function ensureWorkflowTsconfigExcludes(projectDir: string): void;
|
|
100
|
+
/**
|
|
101
|
+
* `lotics app codegen [path]` — regenerate every `.lotics/` artifact from the
|
|
102
|
+
* manifest + workspace schema, WITHOUT a deploy. The `.d.ts` companions are
|
|
103
|
+
* always written (synchronous, no network). When a `client` is available, the
|
|
104
|
+
* runtime `app_fields.ts` is also regenerated from the live schema of the tables
|
|
105
|
+
* the app's queries reference (+ the allowlist); a network failure is non-fatal
|
|
106
|
+
* (warn, keep the last-generated file) — so codegen still does useful work
|
|
107
|
+
* offline, mirroring `app create`'s tolerance of an offline npm registry.
|
|
108
|
+
*/
|
|
109
|
+
export declare function appCodegen(args: {
|
|
110
|
+
projectDir?: string;
|
|
111
|
+
client?: LoticsClient;
|
|
112
|
+
}): Promise<void>;
|
|
45
113
|
/**
|
|
46
114
|
* Stamp the post-extraction manifest with server-authoritative meta. Called
|
|
47
115
|
* by `appPull` after the source archive lands on disk.
|
|
@@ -106,8 +174,10 @@ export declare function appCreate(client: LoticsClient, args: {
|
|
|
106
174
|
* 4. Regenerate `.lotics/app_workflows.d.ts` from the live workflows so
|
|
107
175
|
* `useWorkflow<"alias">` is typed at pull time.
|
|
108
176
|
* 5. Run `npm install`.
|
|
109
|
-
*
|
|
110
|
-
*
|
|
177
|
+
*
|
|
178
|
+
* Runtime field/option id aliases (`.lotics/app_fields.ts`) are generated on
|
|
179
|
+
* demand by `lotics app codegen`, which fetches the workspace schema — pull
|
|
180
|
+
* leaves it to that command so a schema fetch never blocks the bootstrap.
|
|
111
181
|
*/
|
|
112
182
|
/**
|
|
113
183
|
* `lotics app subdomain <new>` — rename the current app's public address.
|
|
@@ -126,6 +196,14 @@ export declare function appSetSubdomain(client: LoticsClient, args: {
|
|
|
126
196
|
export declare function appRename(client: LoticsClient, args: {
|
|
127
197
|
name: string;
|
|
128
198
|
}): Promise<void>;
|
|
199
|
+
/**
|
|
200
|
+
* Where `lotics app pull <app_id>` lands when given NO explicit path. If the cwd
|
|
201
|
+
* IS already this app's own project (its manifest `app_id` matches), refresh in
|
|
202
|
+
* place — the documented `cd <app> && lotics app pull` flow. Otherwise a fresh
|
|
203
|
+
* clone goes to an `appDirName(name)` subdir. Without this, pulling from inside
|
|
204
|
+
* the app dropped a stray `./<name>/` subdir instead of refreshing the project.
|
|
205
|
+
*/
|
|
206
|
+
export declare function defaultPullTarget(appId: string, appName: string): string;
|
|
129
207
|
export declare function appPull(client: LoticsClient, args: {
|
|
130
208
|
app_id: string;
|
|
131
209
|
targetPath?: string;
|
|
@@ -166,3 +244,88 @@ export declare function appDev(client: LoticsClient, args: {
|
|
|
166
244
|
port?: number;
|
|
167
245
|
vitePort?: number;
|
|
168
246
|
}): Promise<void>;
|
|
247
|
+
/**
|
|
248
|
+
* `lotics app workflow run <alias> '<json>'` — execute a bound app workflow
|
|
249
|
+
* end-to-end against the live workspace. `app_id` comes from the local manifest
|
|
250
|
+
* (like deploy/dev), the alias must be bound server-side via `set_app_workflow`.
|
|
251
|
+
*
|
|
252
|
+
* The full `{ status, message, data, files, side_effects }` JSON prints to
|
|
253
|
+
* stdout (pipeable / assertable); a one-line human summary goes to stderr. A
|
|
254
|
+
* `status: "error"` envelope exits non-zero so a script can branch on it — the
|
|
255
|
+
* transport already normalizes a gateway/timeout failure into the same
|
|
256
|
+
* `{ status: "error" }` shape, so a failed run is never a thrown HTML body.
|
|
257
|
+
*
|
|
258
|
+
* `--print-created` (alias `--report-effects`) renders the honest post-run
|
|
259
|
+
* harvest (GAP-58): created records grouped by table, a paste-ready
|
|
260
|
+
* `delete_records` per table, and the mandatory caveat about what cannot be
|
|
261
|
+
* auto-undone. `--cleanup` (DEFAULT OFF) additionally runs the deletes for the
|
|
262
|
+
* harvested records ONLY — never files, external integrations, or notifications.
|
|
263
|
+
* Neither is a rollback; a rollback is structurally impossible here.
|
|
264
|
+
*/
|
|
265
|
+
export declare function appExecuteWorkflow(client: LoticsClient, args: {
|
|
266
|
+
alias: string;
|
|
267
|
+
inputs: Record<string, unknown>;
|
|
268
|
+
printCreated?: boolean;
|
|
269
|
+
cleanup?: boolean;
|
|
270
|
+
}): Promise<void>;
|
|
271
|
+
/**
|
|
272
|
+
* `lotics app workflow set <alias>` — push the edited `src/workflows/<alias>.ts`
|
|
273
|
+
* body to the server through `set_app_workflow` (the single author of
|
|
274
|
+
* `apps.workflows`). The body is read from disk (header stripped); the typed
|
|
275
|
+
* `inputs`/`outputs` schemas come from `package.json#lotics.workflows.<alias>`,
|
|
276
|
+
* so a pulled-then-edited app keeps its declared contract. The server re-verifies
|
|
277
|
+
* the body and echoes the bound `outputs` (declared, else DERIVED from
|
|
278
|
+
* `return({ data })`) — the same guarantee as calling `set_app_workflow` by hand,
|
|
279
|
+
* with no fetch/reconstruct/escape. Errors (missing file, unbound alias, verify
|
|
280
|
+
* failure) print to stderr and exit non-zero.
|
|
281
|
+
*
|
|
282
|
+
* This is a CLI convenience over the existing tool — `lotics app deploy` is still
|
|
283
|
+
* NOT an author of workflows; the single-author invariant holds.
|
|
284
|
+
*/
|
|
285
|
+
export declare function appWorkflowSet(client: LoticsClient, args: {
|
|
286
|
+
alias: string;
|
|
287
|
+
}): Promise<void>;
|
|
288
|
+
/**
|
|
289
|
+
* `lotics app workflow pull` — rewrite every `src/workflows/<alias>.ts` from the
|
|
290
|
+
* server without a full `lotics app pull` (no source archive, no npm install).
|
|
291
|
+
* The alias set + bodies come from the live App row (the same source `app pull`
|
|
292
|
+
* uses); a legacy alias with no rendered source warns and is skipped.
|
|
293
|
+
*/
|
|
294
|
+
export declare function appWorkflowPull(client: LoticsClient): Promise<void>;
|
|
295
|
+
/**
|
|
296
|
+
* `lotics app workflow check [alias]` — local TypeScript type check of the
|
|
297
|
+
* editable workflow bodies, ONE isolated program per bound alias (GAP-59 fix).
|
|
298
|
+
*
|
|
299
|
+
* The dedicated `tsconfig.workflows.json` that GAP-59 first shipped compiled ALL
|
|
300
|
+
* aliases' bodies + per-alias ambient globals into a SINGLE program, so the N
|
|
301
|
+
* `declare const trigger: AppWorkflowTrigger` declarations (each with THAT
|
|
302
|
+
* alias's `app_workflow.inputs`) collided — tsc resolved one and every body
|
|
303
|
+
* checked `trigger.app_workflow.inputs` against the wrong alias. This command
|
|
304
|
+
* replaces that config: it builds a separate `ts.Program` per alias from exactly
|
|
305
|
+
* that alias's `{body, globals}` pair (mirroring the SERVER, which verifies one
|
|
306
|
+
* body at a time), so the ambient `trigger` is unambiguous and the verdict
|
|
307
|
+
* matches set-time. All aliases run in ONE process.
|
|
308
|
+
*
|
|
309
|
+
* `[alias]` checks one alias; omitted, checks every bound alias that has a body
|
|
310
|
+
* file. Exits non-zero if ANY alias has a type error. A bound alias with no body
|
|
311
|
+
* file yet (never pulled) is warned and skipped; an alias missing its globals
|
|
312
|
+
* file is an error (the body can't be checked without its types).
|
|
313
|
+
*/
|
|
314
|
+
export declare function appWorkflowCheck(args: {
|
|
315
|
+
alias?: string;
|
|
316
|
+
}): Promise<void>;
|
|
317
|
+
/**
|
|
318
|
+
* `lotics ui link <component> [--remove]` — add or remove the `@lotics/ui`
|
|
319
|
+
* dev-link alias in the app's `vite.config.ts`, so edits to the monorepo's
|
|
320
|
+
* `packages/ui/src` go live (HMR) without a publish round-trip. `component` is
|
|
321
|
+
* advisory only — the alias is package-wide (one subpath regex covers every
|
|
322
|
+
* import); it's validated to exist under `packages/ui/src` so a typo fails here.
|
|
323
|
+
*
|
|
324
|
+
* Idempotent: linking twice is a no-op; `--remove` strips the one inserted
|
|
325
|
+
* entry and leaves the rest of `resolve.alias` intact.
|
|
326
|
+
*/
|
|
327
|
+
export declare function appUiLink(args: {
|
|
328
|
+
projectDir?: string;
|
|
329
|
+
component: string;
|
|
330
|
+
remove?: boolean;
|
|
331
|
+
}): void;
|