@lotics/cli 0.227.0 → 0.228.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.
Files changed (2) hide show
  1. package/dist/src/cli.js +70 -31
  2. package/package.json +1 -1
package/dist/src/cli.js CHANGED
@@ -52,7 +52,7 @@ var __toESM = (mod2, isNodeMode, target) => (target = mod2 != null ? __create(__
52
52
  var define_LOTICS_KIT_VERSIONS_default;
53
53
  var init_define_LOTICS_KIT_VERSIONS = __esm({
54
54
  "<define:__LOTICS_KIT_VERSIONS__>"() {
55
- define_LOTICS_KIT_VERSIONS_default = { ui: "56.0.0", sdk: "0.98.3", runtime: "0.18.0" };
55
+ define_LOTICS_KIT_VERSIONS_default = { ui: "57.0.0", sdk: "0.98.3", runtime: "0.19.0" };
56
56
  }
57
57
  });
58
58
 
@@ -53916,7 +53916,7 @@ function resultSideEffects(result) {
53916
53916
 
53917
53917
  // src/version.ts
53918
53918
  init_define_LOTICS_KIT_VERSIONS();
53919
- var VERSION = "0.227.0";
53919
+ var VERSION = "0.228.0";
53920
53920
 
53921
53921
  // src/timezone.ts
53922
53922
  init_define_LOTICS_KIT_VERSIONS();
@@ -65930,7 +65930,7 @@ function planCreate(entry, roles, on = entry, desk) {
65930
65930
  const firstOption = lifecycleBound?.options === void 0 ? void 0 : [...lifecycleBound.options.values()][0];
65931
65931
  const opening = lifecycleBound === void 0 || firstOption === void 0 ? void 0 : { bound: lifecycleBound, option: firstOption };
65932
65932
  const inputs = [];
65933
- const reads = /* @__PURE__ */ new Map();
65933
+ const copied = /* @__PURE__ */ new Map();
65934
65934
  const unique3 = [];
65935
65935
  let party;
65936
65936
  let queued;
@@ -65945,9 +65945,7 @@ function planCreate(entry, roles, on = entry, desk) {
65945
65945
  const link2 = entry.createLinks.get(linkAlias);
65946
65946
  const source = link2 === void 0 ? void 0 : sourceOnTarget(link2, sourceAlias);
65947
65947
  if (link2 === void 0 || source === void 0) continue;
65948
- const read2 = reads.get(linkAlias) ?? { input: linkAlias, local: `${camel(linkAlias)}Row`, link: link2, copies: [], where: link2.where ?? [] };
65949
- read2.copies.push({ into: fieldBound, from: source });
65950
- reads.set(linkAlias, read2);
65948
+ copied.set(linkAlias, { link: link2, copies: [...copied.get(linkAlias)?.copies ?? [], { into: fieldBound, from: source }] });
65951
65949
  continue;
65952
65950
  }
65953
65951
  if (parent !== void 0 && field.alias === parentField?.alias) continue;
@@ -65966,9 +65964,6 @@ function planCreate(entry, roles, on = entry, desk) {
65966
65964
  }
65967
65965
  const link = entry.createLinks.get(field.alias);
65968
65966
  if (link === void 0) continue;
65969
- if ((link.where !== void 0 || link.scope !== void 0) && !reads.has(field.alias)) {
65970
- reads.set(field.alias, { input: fieldBound.alias, local: `${camel(field.alias)}Row`, link, copies: [], where: link.where ?? [] });
65971
- }
65972
65967
  if (desk === void 0 && party === void 0 && roleOfField(field) === "party" && link.keys.length > 0) {
65973
65968
  party = { alias: field.alias, link, bound: fieldBound, local: `${camel(field.alias)}Id` };
65974
65969
  for (const key of link.keys) {
@@ -66025,6 +66020,20 @@ function planCreate(entry, roles, on = entry, desk) {
66025
66020
  if (mount === void 0) return void 0;
66026
66021
  const run = section?.itinerary;
66027
66022
  const day = run === void 0 ? void 0 : drafted.find((input) => input.link === void 0 && input.field.alias === run.when.alias)?.name;
66023
+ const reads = drafted.flatMap((input) => {
66024
+ const link = input.into === "row" ? input.link : void 0;
66025
+ if (link === void 0) return [];
66026
+ const copies = copied.get(input.field.alias)?.copies ?? [];
66027
+ if (copies.length === 0 && link.where === void 0 && link.scope === void 0) return [];
66028
+ return [{ by: { kind: "input", input }, local: `${camel(input.field.alias)}Row`, link, copies }];
66029
+ });
66030
+ const lent = (alias, by) => {
66031
+ const lending = alias === void 0 ? void 0 : copied.get(alias);
66032
+ return alias === void 0 || lending === void 0 ? [] : [{ by, local: `${camel(alias)}Row`, link: lending.link, copies: lending.copies }];
66033
+ };
66034
+ if (parent !== void 0) reads.push(...lent(parentField?.alias, { kind: "parent" }));
66035
+ const named3 = party;
66036
+ if (named3 !== void 0 && drafted.some((input) => input.through?.alias === named3.alias)) reads.push(...lent(named3.alias, { kind: "party" }));
66028
66037
  return {
66029
66038
  entry,
66030
66039
  entity,
@@ -66035,11 +66044,7 @@ function planCreate(entry, roles, on = entry, desk) {
66035
66044
  ...opening === void 0 ? {} : { opening },
66036
66045
  ...party === void 0 ? {} : { party },
66037
66046
  ...queued === void 0 ? {} : { queued },
66038
- // THE ROWS THE BODY READS ARE THE ONES THE DRAFT NAMES. A desk's create
66039
- // takes the destination and nothing else, so a picker's narrowing or a
66040
- // copied default over a link nobody states would read a row by an input the
66041
- // workflow never declared.
66042
- reads: [...reads.values()].filter((read2) => queued === void 0 || read2.input === queued.name),
66047
+ reads,
66043
66048
  unique: unique3,
66044
66049
  inputs: drafted,
66045
66050
  mount
@@ -68415,6 +68420,16 @@ ${historyRow(append, `i.${param}`, "reached", " ")}
68415
68420
  }
68416
68421
  return [write(`set: { ${str(bound.id)}: i.${bound.alias} }`, bound.alias)];
68417
68422
  });
68423
+ const bounds = entity.fields.flatMap((field) => {
68424
+ const bound = entry.fields.get(field.alias);
68425
+ const rule = writeRuleOf(entry.rules, entity.alias, field.alias);
68426
+ if (bound === void 0 || rule === void 0 || !saved.has(field.alias)) return [];
68427
+ const sent = `includes(keys(i), ${str(bound.alias)}) && !isNull(i.${bound.alias})`;
68428
+ return [
68429
+ ...rule.min === void 0 ? [] : [checkLine(`${sent} && i.${bound.alias} < ${rule.min}`, bound.alias, entry.words.refusals.below(bound.label, rule.min))],
68430
+ ...rule.max === void 0 ? [] : [checkLine(`${sent} && i.${bound.alias} > ${rule.max}`, bound.alias, entry.words.refusals.above(bound.label, rule.max))]
68431
+ ];
68432
+ });
68418
68433
  return `// ${writeAlias(entity.alias)} \u2014 one row of ${entity.label}, changed by the record surface
68419
68434
  // that opens it. Every input but the record is OPTIONAL, and it is the KEY's
68420
68435
  // presence that says a value was sent: \`null\` clears the field, an absent key
@@ -68423,7 +68438,7 @@ const i = trigger.app_workflow.inputs;
68423
68438
  validate({
68424
68439
  checks: [{ fail_when: size(keys(i)) < 2, message: ${str(entry.words.refusals.noField)} }],
68425
68440
  });
68426
- ${scopeGuard(entry, param)}${blocks.join("\n")}
68441
+ ${validateBlock(bounds)}${scopeGuard(entry, param)}${blocks.join("\n")}
68427
68442
  `;
68428
68443
  }
68429
68444
  function removeSource(entry, desk) {
@@ -68539,6 +68554,13 @@ function whereCheck(local, condition) {
68539
68554
  return "false";
68540
68555
  }
68541
68556
  }
68557
+ function admits(link, local) {
68558
+ const where = link.where ?? [];
68559
+ return {
68560
+ ...where.length > 0 ? { where: where.map((condition) => whereCheck(local, condition)).join(" && ") } : {},
68561
+ ...link.scope === void 0 ? {} : { scope: `(${scopePasses(link.scope, local)})` }
68562
+ };
68563
+ }
68542
68564
  function createSource(plan) {
68543
68565
  const { entry, entity, party } = plan;
68544
68566
  const words = entry.words;
@@ -68591,23 +68613,36 @@ function createSource(plan) {
68591
68613
  );
68592
68614
  }
68593
68615
  for (const read2 of plan.reads) {
68594
- lines.push(`const ${read2.local} = await get_record({ table_id: ${str(read2.link.table.id)}, record_id: i.${read2.input} });`);
68595
- const narrowed = [
68596
- ...read2.where.length > 0 ? [read2.where.map((condition) => whereCheck(read2.local, condition)).join(" && ")] : [],
68597
- ...read2.link.scope === void 0 ? [] : [`(${scopePasses(read2.link.scope, read2.local)})`]
68598
- ];
68599
- if (narrowed.length > 0) {
68600
- lines.push(
68601
- validateBlock([
68602
- checkLine(`!(${narrowed.join(" && ")})`, read2.input, words.refusals.offered(read2.link.target.label))
68603
- ]).trimEnd()
68604
- );
68616
+ const fetch2 = (id) => `const ${read2.local} = await get_record({ table_id: ${str(read2.link.table.id)}, record_id: ${id} });`;
68617
+ if (read2.by.kind === "parent" && plan.parent !== void 0) lines.push(fetch2(`i.${plan.parent.param}`));
68618
+ if (read2.by.kind !== "input") continue;
68619
+ const input = read2.by.input;
68620
+ const { where, scope } = admits(read2.link, read2.local);
68621
+ const passes = [where, scope].filter((part) => part !== void 0).join(" && ");
68622
+ const refusal = passes === "" ? "" : validateBlock([checkLine(`!(${passes})`, input.name, words.refusals.offered(read2.link.target.label))]);
68623
+ const indent = (text) => text.split("\n").filter((line) => line !== "").map((line) => ` ${line}`).join("\n");
68624
+ if (input.several === true) {
68625
+ lines.push(`for (const picked of i.${input.name} ?? []) {`, indent(fetch2("picked")), ...refusal === "" ? [] : [indent(refusal)], `}`);
68626
+ continue;
68605
68627
  }
68628
+ if (!input.required) {
68629
+ lines.push(`if (!isNull(i.${input.name})) {`, indent(fetch2(`i.${input.name}`)), ...refusal === "" ? [] : [indent(refusal)], `}`);
68630
+ continue;
68631
+ }
68632
+ lines.push(fetch2(`i.${input.name}`));
68633
+ if (refusal !== "") lines.push(refusal.trimEnd());
68606
68634
  }
68607
68635
  if (party !== void 0) {
68608
68636
  const matched = plan.inputs.filter((input) => input.through?.alias === party.alias && input.through.matched);
68609
68637
  const minted = plan.inputs.filter((input) => input.through?.alias === party.alias && !input.through.matched);
68610
68638
  const filter2 = matched.length === 1 ? `{ node_type: "condition", field_key: ${str(matched[0].bound.id)}, operator: "equals", value: trim(i.${matched[0].name}) }` : `{ node_type: "group", logic: "and", children: [${matched.map((input) => `{ node_type: "condition", field_key: ${str(input.bound.id)}, operator: "equals", value: trim(i.${input.name}) }`).join(", ")}] }`;
68639
+ const known = `${camel(party.alias)}Known`;
68640
+ const { where, scope } = admits(party.link, known);
68641
+ const typed = matched[0];
68642
+ const partyChecks = typed === void 0 ? [] : [
68643
+ ...scope === void 0 ? [] : [checkLine(`!isNull(${known}) && !${scope}`, typed.name, words.refusals.taken(typed.label))],
68644
+ ...where === void 0 ? [] : [checkLine(`!isNull(${known}) && !(${where})`, typed.name, words.refusals.offered(party.link.target.label))]
68645
+ ];
68611
68646
  lines.push(
68612
68647
  `// THE PARTY IS FOUND BEFORE IT IS MADE: the key the book recognises a row`,
68613
68648
  `// by decides whether this is somebody we already have.`,
@@ -68615,8 +68650,9 @@ function createSource(plan) {
68615
68650
  table_id: ${str(party.link.table.id)},
68616
68651
  filters: ${filter2},
68617
68652
  });`,
68618
- `const ${camel(party.alias)}Known = first(${camel(party.alias)}Book.records);`,
68619
- `let ${party.local} = isNull(${camel(party.alias)}Known) ? null : ${camel(party.alias)}Known.id;`,
68653
+ `const ${known} = first(${camel(party.alias)}Book.records);`,
68654
+ ...partyChecks.length === 0 ? [] : [validateBlock(partyChecks).trimEnd()],
68655
+ `let ${party.local} = isNull(${known}) ? null : ${known}.id;`,
68620
68656
  `if (isNull(${party.local})) {`,
68621
68657
  ...minted.length === 0 ? [] : [
68622
68658
  validateBlock(
@@ -68632,6 +68668,10 @@ function createSource(plan) {
68632
68668
  ` ${party.local} = ${camel(party.alias)}Opened.record_ids[0];`,
68633
68669
  `}`
68634
68670
  );
68671
+ for (const read2 of plan.reads) {
68672
+ if (read2.by.kind !== "party") continue;
68673
+ lines.push(`const ${read2.local} = await get_record({ table_id: ${str(read2.link.table.id)}, record_id: ${party.local} });`);
68674
+ }
68635
68675
  }
68636
68676
  const cells = [];
68637
68677
  if (plan.parent !== void 0) cells.push(` ${str(plan.parent.bound.id)}: [i.${plan.parent.param}],`);
@@ -74551,11 +74591,10 @@ async function readLiveQueries(client, appId) {
74551
74591
  const app = await client.getApp(appId);
74552
74592
  return app.queries ?? {};
74553
74593
  } catch (err) {
74554
- console.error(
74594
+ fail(
74555
74595
  `Could not read ${appId}'s current queries, which this deploy has to send back unchanged: ${err instanceof Error ? err.message : String(err)}
74556
74596
  Nothing was deployed. Retry.`
74557
74597
  );
74558
- process.exit(1);
74559
74598
  }
74560
74599
  }
74561
74600
  async function appCheck(client, args = {}) {
@@ -74653,7 +74692,7 @@ async function appCheck(client, args = {}) {
74653
74692
  // fails the run whatever the probes found: everything measured after the
74654
74693
  // refusal describes a surface no reader could have put the app in.
74655
74694
  refusedWrites > 0) {
74656
- process.exit(1);
74695
+ fail("The findings above block a deploy.");
74657
74696
  }
74658
74697
  console.error(
74659
74698
  "Checked the app's types, bindings, capabilities, agent schemas, workflow bodies and id portability" + (args.screens === true ? ", and the screens above" : "") + " \u2014 nothing blocking."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lotics/cli",
3
- "version": "0.227.0",
3
+ "version": "0.228.0",
4
4
  "description": "Lotics SDK and CLI for AI agents",
5
5
  "type": "module",
6
6
  "bin": {