@lotics/cli 0.165.0 → 0.171.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 +25 -4
- package/dist/src/cli.js +706 -421
- package/dist/src/client.d.ts +38 -1
- package/dist/src/client.js +42 -0
- package/docs/building_an_app.md +8 -0
- package/docs/cli_reference.md +3 -2
- package/package.json +4 -1
package/dist/src/cli.js
CHANGED
|
@@ -26822,12 +26822,12 @@ var require_tokens = __commonJS({
|
|
|
26822
26822
|
});
|
|
26823
26823
|
}
|
|
26824
26824
|
exports2.assignCategoriesMapProp = assignCategoriesMapProp;
|
|
26825
|
-
function singleAssignCategoriesToksMap(
|
|
26826
|
-
utils_1.forEach(
|
|
26825
|
+
function singleAssignCategoriesToksMap(path13, nextNode) {
|
|
26826
|
+
utils_1.forEach(path13, function(pathNode) {
|
|
26827
26827
|
nextNode.categoryMatchesMap[pathNode.tokenTypeIdx] = true;
|
|
26828
26828
|
});
|
|
26829
26829
|
utils_1.forEach(nextNode.CATEGORIES, function(nextCategory) {
|
|
26830
|
-
var newPath =
|
|
26830
|
+
var newPath = path13.concat(nextNode);
|
|
26831
26831
|
if (!utils_1.contains(newPath, nextCategory)) {
|
|
26832
26832
|
singleAssignCategoriesToksMap(newPath, nextCategory);
|
|
26833
26833
|
}
|
|
@@ -28590,10 +28590,10 @@ var require_interpreter = __commonJS({
|
|
|
28590
28590
|
/** @class */
|
|
28591
28591
|
(function(_super) {
|
|
28592
28592
|
__extends(AbstractNextPossibleTokensWalker2, _super);
|
|
28593
|
-
function AbstractNextPossibleTokensWalker2(topProd,
|
|
28593
|
+
function AbstractNextPossibleTokensWalker2(topProd, path13) {
|
|
28594
28594
|
var _this = _super.call(this) || this;
|
|
28595
28595
|
_this.topProd = topProd;
|
|
28596
|
-
_this.path =
|
|
28596
|
+
_this.path = path13;
|
|
28597
28597
|
_this.possibleTokTypes = [];
|
|
28598
28598
|
_this.nextProductionName = "";
|
|
28599
28599
|
_this.nextProductionOccurrence = 0;
|
|
@@ -28647,9 +28647,9 @@ var require_interpreter = __commonJS({
|
|
|
28647
28647
|
/** @class */
|
|
28648
28648
|
(function(_super) {
|
|
28649
28649
|
__extends(NextAfterTokenWalker2, _super);
|
|
28650
|
-
function NextAfterTokenWalker2(topProd,
|
|
28651
|
-
var _this = _super.call(this, topProd,
|
|
28652
|
-
_this.path =
|
|
28650
|
+
function NextAfterTokenWalker2(topProd, path13) {
|
|
28651
|
+
var _this = _super.call(this, topProd, path13) || this;
|
|
28652
|
+
_this.path = path13;
|
|
28653
28653
|
_this.nextTerminalName = "";
|
|
28654
28654
|
_this.nextTerminalOccurrence = 0;
|
|
28655
28655
|
_this.nextTerminalName = _this.path.lastTok.name;
|
|
@@ -29346,10 +29346,10 @@ var require_lookahead = __commonJS({
|
|
|
29346
29346
|
}
|
|
29347
29347
|
return result;
|
|
29348
29348
|
}
|
|
29349
|
-
function pathToHashKeys(
|
|
29349
|
+
function pathToHashKeys(path13) {
|
|
29350
29350
|
var keys3 = [""];
|
|
29351
|
-
for (var i2 = 0; i2 <
|
|
29352
|
-
var tokType =
|
|
29351
|
+
for (var i2 = 0; i2 < path13.length; i2++) {
|
|
29352
|
+
var tokType = path13[i2];
|
|
29353
29353
|
var longerKeys = [];
|
|
29354
29354
|
for (var j = 0; j < keys3.length; j++) {
|
|
29355
29355
|
var currShorterKey = keys3[j];
|
|
@@ -29661,9 +29661,9 @@ var require_checks = __commonJS({
|
|
|
29661
29661
|
return errors2;
|
|
29662
29662
|
}
|
|
29663
29663
|
exports2.validateRuleIsOverridden = validateRuleIsOverridden;
|
|
29664
|
-
function validateNoLeftRecursion(topRule, currRule, errMsgProvider,
|
|
29665
|
-
if (
|
|
29666
|
-
|
|
29664
|
+
function validateNoLeftRecursion(topRule, currRule, errMsgProvider, path13) {
|
|
29665
|
+
if (path13 === void 0) {
|
|
29666
|
+
path13 = [];
|
|
29667
29667
|
}
|
|
29668
29668
|
var errors2 = [];
|
|
29669
29669
|
var nextNonTerminals = getFirstNoneTerminal(currRule.definition);
|
|
@@ -29676,15 +29676,15 @@ var require_checks = __commonJS({
|
|
|
29676
29676
|
errors2.push({
|
|
29677
29677
|
message: errMsgProvider.buildLeftRecursionError({
|
|
29678
29678
|
topLevelRule: topRule,
|
|
29679
|
-
leftRecursionPath:
|
|
29679
|
+
leftRecursionPath: path13
|
|
29680
29680
|
}),
|
|
29681
29681
|
type: parser_1.ParserDefinitionErrorType.LEFT_RECURSION,
|
|
29682
29682
|
ruleName
|
|
29683
29683
|
});
|
|
29684
29684
|
}
|
|
29685
|
-
var validNextSteps = utils2.difference(nextNonTerminals,
|
|
29685
|
+
var validNextSteps = utils2.difference(nextNonTerminals, path13.concat([topRule]));
|
|
29686
29686
|
var errorsFromNextSteps = utils2.map(validNextSteps, function(currRefRule) {
|
|
29687
|
-
var newPath = utils2.cloneArr(
|
|
29687
|
+
var newPath = utils2.cloneArr(path13);
|
|
29688
29688
|
newPath.push(currRefRule);
|
|
29689
29689
|
return validateNoLeftRecursion(topRule, currRefRule, errMsgProvider, newPath);
|
|
29690
29690
|
});
|
|
@@ -37293,8 +37293,8 @@ var require_utils4 = __commonJS({
|
|
|
37293
37293
|
var result = transform2[inputType][outputType](input);
|
|
37294
37294
|
return result;
|
|
37295
37295
|
};
|
|
37296
|
-
exports2.resolve = function(
|
|
37297
|
-
var parts =
|
|
37296
|
+
exports2.resolve = function(path13) {
|
|
37297
|
+
var parts = path13.split("/");
|
|
37298
37298
|
var result = [];
|
|
37299
37299
|
for (var index = 0; index < parts.length; index++) {
|
|
37300
37300
|
var part = parts[index];
|
|
@@ -43147,18 +43147,18 @@ var require_object = __commonJS({
|
|
|
43147
43147
|
var object2 = new ZipObject(name2, zipObjectContent, o);
|
|
43148
43148
|
this.files[name2] = object2;
|
|
43149
43149
|
};
|
|
43150
|
-
var parentFolder = function(
|
|
43151
|
-
if (
|
|
43152
|
-
|
|
43150
|
+
var parentFolder = function(path13) {
|
|
43151
|
+
if (path13.slice(-1) === "/") {
|
|
43152
|
+
path13 = path13.substring(0, path13.length - 1);
|
|
43153
43153
|
}
|
|
43154
|
-
var lastSlash =
|
|
43155
|
-
return lastSlash > 0 ?
|
|
43154
|
+
var lastSlash = path13.lastIndexOf("/");
|
|
43155
|
+
return lastSlash > 0 ? path13.substring(0, lastSlash) : "";
|
|
43156
43156
|
};
|
|
43157
|
-
var forceTrailingSlash = function(
|
|
43158
|
-
if (
|
|
43159
|
-
|
|
43157
|
+
var forceTrailingSlash = function(path13) {
|
|
43158
|
+
if (path13.slice(-1) !== "/") {
|
|
43159
|
+
path13 += "/";
|
|
43160
43160
|
}
|
|
43161
|
-
return
|
|
43161
|
+
return path13;
|
|
43162
43162
|
};
|
|
43163
43163
|
var folderAdd = function(name2, createFolders) {
|
|
43164
43164
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults2.createFolders;
|
|
@@ -44162,7 +44162,7 @@ import dns from "node:dns";
|
|
|
44162
44162
|
import net2 from "node:net";
|
|
44163
44163
|
import fs14 from "node:fs";
|
|
44164
44164
|
import os4 from "node:os";
|
|
44165
|
-
import
|
|
44165
|
+
import path12 from "node:path";
|
|
44166
44166
|
import readline from "node:readline";
|
|
44167
44167
|
|
|
44168
44168
|
// ../shared/src/transport_error.ts
|
|
@@ -44301,6 +44301,26 @@ function getMimeType(filename) {
|
|
|
44301
44301
|
return MIME_MAP[ext] ?? "application/octet-stream";
|
|
44302
44302
|
}
|
|
44303
44303
|
var API_BASE_URL = process.env.LOTICS_API_URL ?? "https://api.lotics.ai";
|
|
44304
|
+
var WEB_APP_URL = "https://lotics.ai";
|
|
44305
|
+
async function fetchOfficialStarters() {
|
|
44306
|
+
let response;
|
|
44307
|
+
try {
|
|
44308
|
+
response = await fetch(`${API_BASE_URL}/v1/starters/official`, {
|
|
44309
|
+
signal: AbortSignal.timeout(SHELF_FETCH_TIMEOUT_MS)
|
|
44310
|
+
});
|
|
44311
|
+
} catch (error52) {
|
|
44312
|
+
throw new Error(
|
|
44313
|
+
`Could not reach Lotics to list the starters (${error52 instanceof Error ? error52.message : String(error52)}). Check your connection, or browse ${WEB_APP_URL}/docs/cli.`
|
|
44314
|
+
);
|
|
44315
|
+
}
|
|
44316
|
+
if (!response.ok) {
|
|
44317
|
+
throw new Error(
|
|
44318
|
+
`Lotics answered ${response.status} listing the starters. If this keeps happening, browse ${WEB_APP_URL}/docs/cli.`
|
|
44319
|
+
);
|
|
44320
|
+
}
|
|
44321
|
+
return await response.json();
|
|
44322
|
+
}
|
|
44323
|
+
var SHELF_FETCH_TIMEOUT_MS = 1e4;
|
|
44304
44324
|
var LoticsClient = class {
|
|
44305
44325
|
apiKey;
|
|
44306
44326
|
workspaceId;
|
|
@@ -44358,8 +44378,8 @@ var LoticsClient = class {
|
|
|
44358
44378
|
}
|
|
44359
44379
|
return headers;
|
|
44360
44380
|
}
|
|
44361
|
-
async request(method,
|
|
44362
|
-
const url2 = `${this.baseUrl}${
|
|
44381
|
+
async request(method, path13, body) {
|
|
44382
|
+
const url2 = `${this.baseUrl}${path13}`;
|
|
44363
44383
|
const headers = this.buildHeaders();
|
|
44364
44384
|
const init = { method, headers };
|
|
44365
44385
|
if (body !== void 0) {
|
|
@@ -45605,11 +45625,15 @@ function isNewerVersion(latest, current) {
|
|
|
45605
45625
|
if (lMin !== cMin) return lMin > cMin;
|
|
45606
45626
|
return lPat > cPat;
|
|
45607
45627
|
}
|
|
45628
|
+
function updateCommand() {
|
|
45629
|
+
if (process.versions.bun === void 0) return "npm i -g @lotics/cli";
|
|
45630
|
+
return process.platform === "win32" ? "irm https://lotics.ai/install.ps1 | iex" : "curl -fsSL https://lotics.ai/install.sh | bash";
|
|
45631
|
+
}
|
|
45608
45632
|
function printUpdateWarning(current, latest) {
|
|
45609
45633
|
if (!isNewerVersion(latest, current)) return;
|
|
45610
45634
|
console.error(`
|
|
45611
45635
|
Update available: ${current} \u2192 ${latest}`);
|
|
45612
|
-
console.error(`Run:
|
|
45636
|
+
console.error(`Run: ${updateCommand()}
|
|
45613
45637
|
`);
|
|
45614
45638
|
}
|
|
45615
45639
|
|
|
@@ -45672,17 +45696,12 @@ function resultSideEffects(result) {
|
|
|
45672
45696
|
}
|
|
45673
45697
|
|
|
45674
45698
|
// src/version.ts
|
|
45675
|
-
|
|
45676
|
-
import { fileURLToPath } from "node:url";
|
|
45677
|
-
import path5 from "node:path";
|
|
45678
|
-
var pkgPath = path5.resolve(path5.dirname(fileURLToPath(import.meta.url)), "../../package.json");
|
|
45679
|
-
var pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
45680
|
-
var VERSION = pkg.version;
|
|
45699
|
+
var VERSION = "0.171.0";
|
|
45681
45700
|
|
|
45682
45701
|
// src/docs_command.ts
|
|
45683
45702
|
import fs5 from "node:fs";
|
|
45684
|
-
import
|
|
45685
|
-
import { fileURLToPath
|
|
45703
|
+
import path5 from "node:path";
|
|
45704
|
+
import { fileURLToPath } from "node:url";
|
|
45686
45705
|
var READING_ORDER = ["@lotics/app-sdk", "@lotics/ui", "@lotics/cli"];
|
|
45687
45706
|
function firstHeading(file2) {
|
|
45688
45707
|
let text;
|
|
@@ -45699,35 +45718,35 @@ function firstHeading(file2) {
|
|
|
45699
45718
|
}
|
|
45700
45719
|
function readVersion(pkgDir) {
|
|
45701
45720
|
try {
|
|
45702
|
-
const raw = fs5.readFileSync(
|
|
45721
|
+
const raw = fs5.readFileSync(path5.join(pkgDir, "package.json"), "utf-8");
|
|
45703
45722
|
return JSON.parse(raw).version ?? "?";
|
|
45704
45723
|
} catch {
|
|
45705
45724
|
return "?";
|
|
45706
45725
|
}
|
|
45707
45726
|
}
|
|
45708
45727
|
function ownPackageDir() {
|
|
45709
|
-
return
|
|
45728
|
+
return path5.resolve(path5.dirname(fileURLToPath(import.meta.url)), "../..");
|
|
45710
45729
|
}
|
|
45711
45730
|
function referencePackageDirs(projectDir) {
|
|
45712
45731
|
const found = /* @__PURE__ */ new Map();
|
|
45713
45732
|
for (let dir = projectDir; ; ) {
|
|
45714
|
-
const scope =
|
|
45733
|
+
const scope = path5.join(dir, "node_modules", "@lotics");
|
|
45715
45734
|
if (fs5.existsSync(scope)) {
|
|
45716
45735
|
for (const name2 of fs5.readdirSync(scope)) {
|
|
45717
|
-
const pkgDir =
|
|
45718
|
-
const carries = fs5.existsSync(
|
|
45736
|
+
const pkgDir = path5.join(scope, name2);
|
|
45737
|
+
const carries = fs5.existsSync(path5.join(pkgDir, "AGENTS.md")) || fs5.existsSync(path5.join(pkgDir, "docs"));
|
|
45719
45738
|
if (carries && !found.has(`@lotics/${name2}`)) found.set(`@lotics/${name2}`, pkgDir);
|
|
45720
45739
|
}
|
|
45721
45740
|
}
|
|
45722
|
-
const parent =
|
|
45741
|
+
const parent = path5.dirname(dir);
|
|
45723
45742
|
if (parent === dir) break;
|
|
45724
45743
|
dir = parent;
|
|
45725
45744
|
}
|
|
45726
45745
|
const own = ownPackageDir();
|
|
45727
|
-
if (!found.has("@lotics/cli") && fs5.existsSync(
|
|
45746
|
+
if (!found.has("@lotics/cli") && fs5.existsSync(path5.join(own, "AGENTS.md"))) {
|
|
45728
45747
|
found.set("@lotics/cli", own);
|
|
45729
45748
|
}
|
|
45730
|
-
return [...found.entries()].map(([
|
|
45749
|
+
return [...found.entries()].map(([pkg, dir]) => ({ pkg, dir })).sort((a, b) => {
|
|
45731
45750
|
const ia = READING_ORDER.indexOf(a.pkg);
|
|
45732
45751
|
const ib = READING_ORDER.indexOf(b.pkg);
|
|
45733
45752
|
if (ia !== ib) return (ia < 0 ? READING_ORDER.length : ia) - (ib < 0 ? READING_ORDER.length : ib);
|
|
@@ -45736,26 +45755,26 @@ function referencePackageDirs(projectDir) {
|
|
|
45736
45755
|
}
|
|
45737
45756
|
function collectDocAreas(projectDir) {
|
|
45738
45757
|
const found = [];
|
|
45739
|
-
for (const { pkg
|
|
45758
|
+
for (const { pkg, dir } of referencePackageDirs(projectDir)) {
|
|
45740
45759
|
const version2 = readVersion(dir);
|
|
45741
|
-
const index =
|
|
45760
|
+
const index = path5.join(dir, "AGENTS.md");
|
|
45742
45761
|
if (fs5.existsSync(index)) {
|
|
45743
45762
|
found.push({
|
|
45744
|
-
area:
|
|
45745
|
-
pkg
|
|
45763
|
+
area: pkg.replace("@lotics/", ""),
|
|
45764
|
+
pkg,
|
|
45746
45765
|
version: version2,
|
|
45747
45766
|
absPath: index,
|
|
45748
45767
|
title: firstHeading(index)
|
|
45749
45768
|
});
|
|
45750
45769
|
}
|
|
45751
|
-
const docsDir =
|
|
45770
|
+
const docsDir = path5.join(dir, "docs");
|
|
45752
45771
|
if (!fs5.existsSync(docsDir)) continue;
|
|
45753
45772
|
for (const file2 of fs5.readdirSync(docsDir).sort()) {
|
|
45754
45773
|
if (!file2.endsWith(".md")) continue;
|
|
45755
|
-
const abs2 =
|
|
45774
|
+
const abs2 = path5.join(docsDir, file2);
|
|
45756
45775
|
found.push({
|
|
45757
45776
|
area: file2.replace(/\.md$/, ""),
|
|
45758
|
-
pkg
|
|
45777
|
+
pkg,
|
|
45759
45778
|
version: version2,
|
|
45760
45779
|
absPath: abs2,
|
|
45761
45780
|
title: firstHeading(abs2)
|
|
@@ -45802,7 +45821,7 @@ ${a.pkg} ${a.version}`);
|
|
|
45802
45821
|
return lines.join("\n");
|
|
45803
45822
|
}
|
|
45804
45823
|
function docsCommand(args) {
|
|
45805
|
-
const projectDir =
|
|
45824
|
+
const projectDir = path5.resolve(args.projectDir ?? process.cwd());
|
|
45806
45825
|
const areas = collectDocAreas(projectDir);
|
|
45807
45826
|
if (args.area === void 0 || args.area === "") {
|
|
45808
45827
|
console.log(renderDocIndex(areas));
|
|
@@ -45824,13 +45843,26 @@ function docsCommand(args) {
|
|
|
45824
45843
|
process.exit(1);
|
|
45825
45844
|
}
|
|
45826
45845
|
const hit = hits[0];
|
|
45827
|
-
console.error(`${hit.pkg} ${hit.version} \xB7 ${
|
|
45846
|
+
console.error(`${hit.pkg} ${hit.version} \xB7 ${path5.relative(projectDir, hit.absPath)}
|
|
45828
45847
|
`);
|
|
45829
45848
|
process.stdout.write(fs5.readFileSync(hit.absPath, "utf-8"));
|
|
45830
45849
|
}
|
|
45831
45850
|
|
|
45832
45851
|
// src/commands.ts
|
|
45833
45852
|
var COMMANDS = [
|
|
45853
|
+
{
|
|
45854
|
+
verbs: ["start"],
|
|
45855
|
+
help: [
|
|
45856
|
+
" lotics start <starter_id> [path] --email <you@co.com>",
|
|
45857
|
+
" First run, one command: create an account if this",
|
|
45858
|
+
" machine has none, then copy the starter into its",
|
|
45859
|
+
" workspace \u2014 schema, templates, knowledge docs,",
|
|
45860
|
+
" sample records, a deployed app \u2014 and print a",
|
|
45861
|
+
" one-time sign-in link. Drop --email to copy into",
|
|
45862
|
+
" the account you already have. --json prints one",
|
|
45863
|
+
" object and nothing else"
|
|
45864
|
+
]
|
|
45865
|
+
},
|
|
45834
45866
|
{
|
|
45835
45867
|
verbs: ["org"],
|
|
45836
45868
|
help: [
|
|
@@ -45859,7 +45891,9 @@ var COMMANDS = [
|
|
|
45859
45891
|
{
|
|
45860
45892
|
verbs: ["starter"],
|
|
45861
45893
|
help: [
|
|
45862
|
-
" lotics starter list Starters you can copy into this workspace",
|
|
45894
|
+
" lotics starter list Starters you can copy into this workspace. Works with",
|
|
45895
|
+
" NO account \u2014 it then lists the published shelf, so you",
|
|
45896
|
+
" can decide whether to copy one or build before signing up",
|
|
45863
45897
|
" lotics starter show <starter_id> What one carries: tables, docs, templates, sample data",
|
|
45864
45898
|
" lotics starter init <starter_id> [path]",
|
|
45865
45899
|
" Copy it in \u2014 schema, templates, knowledge docs,",
|
|
@@ -46046,7 +46080,7 @@ function matchesKnownFlag(known, arg) {
|
|
|
46046
46080
|
|
|
46047
46081
|
// src/report_command.ts
|
|
46048
46082
|
import fs6 from "node:fs";
|
|
46049
|
-
import
|
|
46083
|
+
import path6 from "node:path";
|
|
46050
46084
|
var LIMITS = { goal: 2e3, expected: 2e3, actual: 4e3, tried: 4e3, wanted: 2e3 };
|
|
46051
46085
|
var REPORT_USAGE = `Usage: lotics report '<json>' lotics report @report.json \u2026 | lotics report -
|
|
46052
46086
|
|
|
@@ -46107,9 +46141,9 @@ function parseReport(raw) {
|
|
|
46107
46141
|
}
|
|
46108
46142
|
function appIdOf(projectDir) {
|
|
46109
46143
|
try {
|
|
46110
|
-
const raw = fs6.readFileSync(
|
|
46111
|
-
const
|
|
46112
|
-
const appId =
|
|
46144
|
+
const raw = fs6.readFileSync(path6.join(projectDir, "package.json"), "utf-8");
|
|
46145
|
+
const pkg = JSON.parse(raw);
|
|
46146
|
+
const appId = pkg.lotics?.app_id;
|
|
46113
46147
|
return typeof appId === "string" && appId !== "" ? appId : void 0;
|
|
46114
46148
|
} catch {
|
|
46115
46149
|
return void 0;
|
|
@@ -46147,7 +46181,7 @@ async function reportCommand(client, options) {
|
|
|
46147
46181
|
|
|
46148
46182
|
// src/app_commands.ts
|
|
46149
46183
|
import fs8 from "node:fs";
|
|
46150
|
-
import
|
|
46184
|
+
import path9 from "node:path";
|
|
46151
46185
|
import { spawn as spawn2 } from "node:child_process";
|
|
46152
46186
|
import { createHash as createHash3 } from "node:crypto";
|
|
46153
46187
|
import { tmpdir } from "node:os";
|
|
@@ -46914,7 +46948,7 @@ function escapeHtml(s) {
|
|
|
46914
46948
|
import http from "node:http";
|
|
46915
46949
|
import net from "node:net";
|
|
46916
46950
|
import { existsSync } from "node:fs";
|
|
46917
|
-
import
|
|
46951
|
+
import path7 from "node:path";
|
|
46918
46952
|
import { spawn } from "node:child_process";
|
|
46919
46953
|
|
|
46920
46954
|
// src/child_env.ts
|
|
@@ -47498,6 +47532,9 @@ var STOP_DEADLINE_MS = 2e3;
|
|
|
47498
47532
|
function serializeRpcResult(result) {
|
|
47499
47533
|
return JSON.stringify(result ?? null);
|
|
47500
47534
|
}
|
|
47535
|
+
function nodeForChildProcess() {
|
|
47536
|
+
return process.versions.bun === void 0 ? process.execPath : "node";
|
|
47537
|
+
}
|
|
47501
47538
|
async function startDevServer(args) {
|
|
47502
47539
|
const wrapperPort = await pickPort(args.port ?? DEFAULT_PORT);
|
|
47503
47540
|
const vitePort = await pickPort(args.vitePort ?? DEFAULT_VITE_PORT, wrapperPort);
|
|
@@ -47509,14 +47546,14 @@ async function startDevServer(args) {
|
|
|
47509
47546
|
vite_url: viteUrl,
|
|
47510
47547
|
api_url: args.api_url
|
|
47511
47548
|
});
|
|
47512
|
-
const viteEntry =
|
|
47549
|
+
const viteEntry = path7.join(args.projectDir, "node_modules", "vite", "bin", "vite.js");
|
|
47513
47550
|
if (!existsSync(viteEntry)) {
|
|
47514
47551
|
throw new Error(
|
|
47515
47552
|
`Vite is not installed in ${args.projectDir} \u2014 run \`npm install\` there first.`
|
|
47516
47553
|
);
|
|
47517
47554
|
}
|
|
47518
47555
|
const viteChild = spawn(
|
|
47519
|
-
|
|
47556
|
+
nodeForChildProcess(),
|
|
47520
47557
|
[viteEntry, "--port", String(vitePort), "--strictPort"],
|
|
47521
47558
|
{
|
|
47522
47559
|
cwd: args.projectDir,
|
|
@@ -47871,6 +47908,36 @@ function openBrowser(url2) {
|
|
|
47871
47908
|
child.unref();
|
|
47872
47909
|
}
|
|
47873
47910
|
|
|
47911
|
+
// src/output.ts
|
|
47912
|
+
var machineMode = false;
|
|
47913
|
+
var collectedWarnings = [];
|
|
47914
|
+
function setMachineOutput(on) {
|
|
47915
|
+
machineMode = on;
|
|
47916
|
+
}
|
|
47917
|
+
function isMachineOutput() {
|
|
47918
|
+
return machineMode;
|
|
47919
|
+
}
|
|
47920
|
+
function note(text) {
|
|
47921
|
+
if (machineMode) return;
|
|
47922
|
+
console.error(text);
|
|
47923
|
+
}
|
|
47924
|
+
function warn(text) {
|
|
47925
|
+
if (machineMode) {
|
|
47926
|
+
collectedWarnings.push(text);
|
|
47927
|
+
return;
|
|
47928
|
+
}
|
|
47929
|
+
console.error(text);
|
|
47930
|
+
}
|
|
47931
|
+
function emitJson(value2) {
|
|
47932
|
+
const payload = collectedWarnings.length > 0 ? { ...value2, warnings: [...collectedWarnings] } : value2;
|
|
47933
|
+
collectedWarnings.length = 0;
|
|
47934
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
47935
|
+
}
|
|
47936
|
+
function flushPendingWarnings() {
|
|
47937
|
+
for (const text of collectedWarnings) console.error(text);
|
|
47938
|
+
collectedWarnings.length = 0;
|
|
47939
|
+
}
|
|
47940
|
+
|
|
47874
47941
|
// ../shared/src/app_dts.ts
|
|
47875
47942
|
var IDENTIFIER_REGEX = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
47876
47943
|
function isValidIdentifier(name2) {
|
|
@@ -48437,7 +48504,7 @@ export type AppOptions = typeof OPT;
|
|
|
48437
48504
|
|
|
48438
48505
|
// src/app_workflow_check.ts
|
|
48439
48506
|
import fs7 from "node:fs";
|
|
48440
|
-
import
|
|
48507
|
+
import path8 from "node:path";
|
|
48441
48508
|
import { createRequire } from "node:module";
|
|
48442
48509
|
|
|
48443
48510
|
// ../shared/src/parse_workflow_js.ts
|
|
@@ -49209,10 +49276,10 @@ function mergeDefs(...defs) {
|
|
|
49209
49276
|
function cloneDef(schema) {
|
|
49210
49277
|
return mergeDefs(schema._zod.def);
|
|
49211
49278
|
}
|
|
49212
|
-
function getElementAtPath(obj,
|
|
49213
|
-
if (!
|
|
49279
|
+
function getElementAtPath(obj, path13) {
|
|
49280
|
+
if (!path13)
|
|
49214
49281
|
return obj;
|
|
49215
|
-
return
|
|
49282
|
+
return path13.reduce((acc, key) => acc?.[key], obj);
|
|
49216
49283
|
}
|
|
49217
49284
|
function promiseAllObject(promisesObj) {
|
|
49218
49285
|
const keys3 = Object.keys(promisesObj);
|
|
@@ -49621,11 +49688,11 @@ function explicitlyAborted(x2, startIndex = 0) {
|
|
|
49621
49688
|
}
|
|
49622
49689
|
return false;
|
|
49623
49690
|
}
|
|
49624
|
-
function prefixIssues(
|
|
49691
|
+
function prefixIssues(path13, issues) {
|
|
49625
49692
|
return issues.map((iss) => {
|
|
49626
49693
|
var _a4;
|
|
49627
49694
|
(_a4 = iss).path ?? (_a4.path = []);
|
|
49628
|
-
iss.path.unshift(
|
|
49695
|
+
iss.path.unshift(path13);
|
|
49629
49696
|
return iss;
|
|
49630
49697
|
});
|
|
49631
49698
|
}
|
|
@@ -49772,16 +49839,16 @@ function flattenError(error52, mapper = (issue2) => issue2.message) {
|
|
|
49772
49839
|
}
|
|
49773
49840
|
function formatError(error52, mapper = (issue2) => issue2.message) {
|
|
49774
49841
|
const fieldErrors = { _errors: [] };
|
|
49775
|
-
const processError = (error53,
|
|
49842
|
+
const processError = (error53, path13 = []) => {
|
|
49776
49843
|
for (const issue2 of error53.issues) {
|
|
49777
49844
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
49778
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
49845
|
+
issue2.errors.map((issues) => processError({ issues }, [...path13, ...issue2.path]));
|
|
49779
49846
|
} else if (issue2.code === "invalid_key") {
|
|
49780
|
-
processError({ issues: issue2.issues }, [...
|
|
49847
|
+
processError({ issues: issue2.issues }, [...path13, ...issue2.path]);
|
|
49781
49848
|
} else if (issue2.code === "invalid_element") {
|
|
49782
|
-
processError({ issues: issue2.issues }, [...
|
|
49849
|
+
processError({ issues: issue2.issues }, [...path13, ...issue2.path]);
|
|
49783
49850
|
} else {
|
|
49784
|
-
const fullpath = [...
|
|
49851
|
+
const fullpath = [...path13, ...issue2.path];
|
|
49785
49852
|
if (fullpath.length === 0) {
|
|
49786
49853
|
fieldErrors._errors.push(mapper(issue2));
|
|
49787
49854
|
} else {
|
|
@@ -49808,17 +49875,17 @@ function formatError(error52, mapper = (issue2) => issue2.message) {
|
|
|
49808
49875
|
}
|
|
49809
49876
|
function treeifyError(error52, mapper = (issue2) => issue2.message) {
|
|
49810
49877
|
const result = { errors: [] };
|
|
49811
|
-
const processError = (error53,
|
|
49878
|
+
const processError = (error53, path13 = []) => {
|
|
49812
49879
|
var _a4, _b2;
|
|
49813
49880
|
for (const issue2 of error53.issues) {
|
|
49814
49881
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
49815
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
49882
|
+
issue2.errors.map((issues) => processError({ issues }, [...path13, ...issue2.path]));
|
|
49816
49883
|
} else if (issue2.code === "invalid_key") {
|
|
49817
|
-
processError({ issues: issue2.issues }, [...
|
|
49884
|
+
processError({ issues: issue2.issues }, [...path13, ...issue2.path]);
|
|
49818
49885
|
} else if (issue2.code === "invalid_element") {
|
|
49819
|
-
processError({ issues: issue2.issues }, [...
|
|
49886
|
+
processError({ issues: issue2.issues }, [...path13, ...issue2.path]);
|
|
49820
49887
|
} else {
|
|
49821
|
-
const fullpath = [...
|
|
49888
|
+
const fullpath = [...path13, ...issue2.path];
|
|
49822
49889
|
if (fullpath.length === 0) {
|
|
49823
49890
|
result.errors.push(mapper(issue2));
|
|
49824
49891
|
continue;
|
|
@@ -49850,8 +49917,8 @@ function treeifyError(error52, mapper = (issue2) => issue2.message) {
|
|
|
49850
49917
|
}
|
|
49851
49918
|
function toDotPath(_path) {
|
|
49852
49919
|
const segs = [];
|
|
49853
|
-
const
|
|
49854
|
-
for (const seg of
|
|
49920
|
+
const path13 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
49921
|
+
for (const seg of path13) {
|
|
49855
49922
|
if (typeof seg === "number")
|
|
49856
49923
|
segs.push(`[${seg}]`);
|
|
49857
49924
|
else if (typeof seg === "symbol")
|
|
@@ -62543,13 +62610,13 @@ function resolveRef(ref2, ctx) {
|
|
|
62543
62610
|
if (!ref2.startsWith("#")) {
|
|
62544
62611
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
62545
62612
|
}
|
|
62546
|
-
const
|
|
62547
|
-
if (
|
|
62613
|
+
const path13 = ref2.slice(1).split("/").filter(Boolean);
|
|
62614
|
+
if (path13.length === 0) {
|
|
62548
62615
|
return ctx.rootSchema;
|
|
62549
62616
|
}
|
|
62550
62617
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
62551
|
-
if (
|
|
62552
|
-
const key =
|
|
62618
|
+
if (path13[0] === defsKey) {
|
|
62619
|
+
const key = path13[1];
|
|
62553
62620
|
if (!key || !ctx.defs[key]) {
|
|
62554
62621
|
throw new Error(`Reference not found: ${ref2}`);
|
|
62555
62622
|
}
|
|
@@ -67305,9 +67372,9 @@ __export(expression_object_exports, {
|
|
|
67305
67372
|
pick: () => pick3,
|
|
67306
67373
|
values: () => values2
|
|
67307
67374
|
});
|
|
67308
|
-
function getNestedValue(obj,
|
|
67375
|
+
function getNestedValue(obj, path13) {
|
|
67309
67376
|
if (obj == null) return void 0;
|
|
67310
|
-
const parts =
|
|
67377
|
+
const parts = path13.split(".");
|
|
67311
67378
|
let value2 = obj;
|
|
67312
67379
|
for (const part of parts) {
|
|
67313
67380
|
if (value2 == null) return void 0;
|
|
@@ -67346,11 +67413,11 @@ function entries(obj) {
|
|
|
67346
67413
|
}
|
|
67347
67414
|
return Object.entries(obj);
|
|
67348
67415
|
}
|
|
67349
|
-
function get(obj,
|
|
67350
|
-
if (typeof
|
|
67416
|
+
function get(obj, path13, defaultValue) {
|
|
67417
|
+
if (typeof path13 !== "string") {
|
|
67351
67418
|
throw new Error("get: path must be a string");
|
|
67352
67419
|
}
|
|
67353
|
-
const value2 = getNestedValue(obj,
|
|
67420
|
+
const value2 = getNestedValue(obj, path13);
|
|
67354
67421
|
return value2 !== void 0 ? value2 : defaultValue;
|
|
67355
67422
|
}
|
|
67356
67423
|
function pick3(obj, fields) {
|
|
@@ -69246,17 +69313,17 @@ function readFromChanges(chain2) {
|
|
|
69246
69313
|
if (first3.kind === "bracket-number" || first3.kind === "bracket-expr") {
|
|
69247
69314
|
fail(first3.node, "changes is keyed by field name, not numeric index.");
|
|
69248
69315
|
}
|
|
69249
|
-
const
|
|
69316
|
+
const path13 = [{ at: "key", key: first3.key }];
|
|
69250
69317
|
for (const seg of segments.slice(1)) {
|
|
69251
69318
|
if (seg.kind === "bracket-number") {
|
|
69252
|
-
|
|
69319
|
+
path13.push({ at: "index", index: seg.index });
|
|
69253
69320
|
} else if (seg.kind === "bracket-expr") {
|
|
69254
|
-
|
|
69321
|
+
path13.push({ at: "index", index: seg.expr });
|
|
69255
69322
|
} else {
|
|
69256
|
-
|
|
69323
|
+
path13.push({ at: "key", key: seg.key });
|
|
69257
69324
|
}
|
|
69258
69325
|
}
|
|
69259
|
-
return { kind: "read", source: { from: "trigger_changes" }, path:
|
|
69326
|
+
return { kind: "read", source: { from: "trigger_changes" }, path: path13 };
|
|
69260
69327
|
});
|
|
69261
69328
|
}
|
|
69262
69329
|
var TRIGGER_RECORD_VIEWS = /* @__PURE__ */ new Map([
|
|
@@ -69274,17 +69341,17 @@ function readFromTrigger(chain2) {
|
|
|
69274
69341
|
return view === "trigger_changes" ? readFromChanges(lowered) : readFromRecord(view, lowered);
|
|
69275
69342
|
}
|
|
69276
69343
|
return wrapOptionalGuards(chain2, (segments) => {
|
|
69277
|
-
const
|
|
69344
|
+
const path13 = [];
|
|
69278
69345
|
for (const seg of segments) {
|
|
69279
69346
|
if (seg.kind === "bracket-number") {
|
|
69280
|
-
|
|
69347
|
+
path13.push({ at: "index", index: seg.index });
|
|
69281
69348
|
} else if (seg.kind === "bracket-expr") {
|
|
69282
|
-
|
|
69349
|
+
path13.push({ at: "index", index: seg.expr });
|
|
69283
69350
|
} else {
|
|
69284
|
-
|
|
69351
|
+
path13.push({ at: "key", key: seg.key });
|
|
69285
69352
|
}
|
|
69286
69353
|
}
|
|
69287
|
-
return { kind: "read", source: { from: "trigger" }, path:
|
|
69354
|
+
return { kind: "read", source: { from: "trigger" }, path: path13 };
|
|
69288
69355
|
});
|
|
69289
69356
|
}
|
|
69290
69357
|
function readFromRuntime(chain2) {
|
|
@@ -69306,17 +69373,17 @@ function readFromRuntime(chain2) {
|
|
|
69306
69373
|
const parked = PARKED_RUNTIME_KEYS.get(key);
|
|
69307
69374
|
if (parked) fail(first3.node, parked, parkedRuntimeKeyConstruct(key));
|
|
69308
69375
|
const source = { from: "runtime", key };
|
|
69309
|
-
const
|
|
69376
|
+
const path13 = [];
|
|
69310
69377
|
for (const seg of segments.slice(1)) {
|
|
69311
69378
|
if (seg.kind === "bracket-number") {
|
|
69312
|
-
|
|
69379
|
+
path13.push({ at: "index", index: seg.index });
|
|
69313
69380
|
} else if (seg.kind === "bracket-expr") {
|
|
69314
|
-
|
|
69381
|
+
path13.push({ at: "index", index: seg.expr });
|
|
69315
69382
|
} else {
|
|
69316
|
-
|
|
69383
|
+
path13.push({ at: "key", key: seg.key });
|
|
69317
69384
|
}
|
|
69318
69385
|
}
|
|
69319
|
-
return { kind: "read", source, path:
|
|
69386
|
+
return { kind: "read", source, path: path13 };
|
|
69320
69387
|
});
|
|
69321
69388
|
}
|
|
69322
69389
|
function readFromForeachItem(name2, chain2) {
|
|
@@ -69355,17 +69422,17 @@ function readFromLexical(name2, chain2) {
|
|
|
69355
69422
|
}
|
|
69356
69423
|
function readFromStepOutput(stepId, chain2) {
|
|
69357
69424
|
return wrapOptionalGuards(chain2, (segments) => {
|
|
69358
|
-
const
|
|
69425
|
+
const path13 = [];
|
|
69359
69426
|
for (const seg of segments) {
|
|
69360
69427
|
if (seg.kind === "bracket-number") {
|
|
69361
|
-
|
|
69428
|
+
path13.push({ at: "index", index: seg.index });
|
|
69362
69429
|
} else if (seg.kind === "bracket-expr") {
|
|
69363
|
-
|
|
69430
|
+
path13.push({ at: "index", index: seg.expr });
|
|
69364
69431
|
} else {
|
|
69365
|
-
|
|
69432
|
+
path13.push({ at: "key", key: seg.key });
|
|
69366
69433
|
}
|
|
69367
69434
|
}
|
|
69368
|
-
return { kind: "read", source: { from: "step_output", step_id: stepId }, path:
|
|
69435
|
+
return { kind: "read", source: { from: "step_output", step_id: stepId }, path: path13 };
|
|
69369
69436
|
});
|
|
69370
69437
|
}
|
|
69371
69438
|
function classifyRecordPath(segs) {
|
|
@@ -71038,7 +71105,7 @@ function subsetIssues(bodySource, offset) {
|
|
|
71038
71105
|
];
|
|
71039
71106
|
}
|
|
71040
71107
|
async function loadProjectTypescript(projectDir) {
|
|
71041
|
-
const requireFromProject = createRequire(
|
|
71108
|
+
const requireFromProject = createRequire(path8.join(projectDir, "package.json"));
|
|
71042
71109
|
let resolved;
|
|
71043
71110
|
try {
|
|
71044
71111
|
resolved = requireFromProject.resolve("typescript");
|
|
@@ -71051,9 +71118,9 @@ async function loadProjectTypescript(projectDir) {
|
|
|
71051
71118
|
return mod2.default ?? mod2;
|
|
71052
71119
|
}
|
|
71053
71120
|
function pathToImportUrl(p) {
|
|
71054
|
-
const resolved =
|
|
71121
|
+
const resolved = path8.resolve(p);
|
|
71055
71122
|
const prefixed = resolved.startsWith("/") ? resolved : `/${resolved}`;
|
|
71056
|
-
return `file://${prefixed.split(
|
|
71123
|
+
return `file://${prefixed.split(path8.sep).join("/")}`;
|
|
71057
71124
|
}
|
|
71058
71125
|
function checkOneWorkflowBody(tsApi, input) {
|
|
71059
71126
|
const wrapped = fs7.readFileSync(input.bodyPath, "utf-8");
|
|
@@ -71103,7 +71170,7 @@ function checkOneWorkflowBody(tsApi, input) {
|
|
|
71103
71170
|
}
|
|
71104
71171
|
function createCheckedSourceHost(tsApi, options, bodyPath, bodyText) {
|
|
71105
71172
|
const base = tsApi.createCompilerHost(options, false);
|
|
71106
|
-
const key = (fileName) => base.getCanonicalFileName(
|
|
71173
|
+
const key = (fileName) => base.getCanonicalFileName(path8.resolve(fileName).replace(/\\/g, "/"));
|
|
71107
71174
|
const bodyKey = key(bodyPath);
|
|
71108
71175
|
return {
|
|
71109
71176
|
...base,
|
|
@@ -71229,10 +71296,10 @@ function syncedEntry(entry) {
|
|
|
71229
71296
|
}
|
|
71230
71297
|
function readSynced(projectDir) {
|
|
71231
71298
|
try {
|
|
71232
|
-
const
|
|
71233
|
-
fs8.readFileSync(
|
|
71299
|
+
const pkg = JSON.parse(
|
|
71300
|
+
fs8.readFileSync(path9.join(projectDir, "package.json"), "utf-8")
|
|
71234
71301
|
);
|
|
71235
|
-
const raw =
|
|
71302
|
+
const raw = pkg.lotics?.synced ?? {};
|
|
71236
71303
|
return {
|
|
71237
71304
|
workflows: normalizeSyncedMap(raw.workflows),
|
|
71238
71305
|
agents: normalizeSyncedMap(raw.agents),
|
|
@@ -71251,19 +71318,19 @@ function normalizeSyncedMap(map3) {
|
|
|
71251
71318
|
);
|
|
71252
71319
|
}
|
|
71253
71320
|
function writeSynced(projectDir, kind, alias, entry) {
|
|
71254
|
-
const
|
|
71255
|
-
const
|
|
71256
|
-
if (!
|
|
71257
|
-
|
|
71258
|
-
|
|
71259
|
-
fs8.writeFileSync(
|
|
71321
|
+
const pkgPath = path9.join(projectDir, "package.json");
|
|
71322
|
+
const pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
|
|
71323
|
+
if (!pkg.lotics) return;
|
|
71324
|
+
pkg.lotics.synced ??= {};
|
|
71325
|
+
pkg.lotics.synced[kind] = { ...pkg.lotics.synced[kind], [alias]: entry };
|
|
71326
|
+
fs8.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
71260
71327
|
}
|
|
71261
71328
|
function readManifestEntry(projectDir, kind, alias) {
|
|
71262
|
-
const
|
|
71263
|
-
if (!
|
|
71329
|
+
const pkg = readManifest(projectDir);
|
|
71330
|
+
if (!pkg.lotics) return { found: false };
|
|
71264
71331
|
const entry = { found: true };
|
|
71265
71332
|
let found = false;
|
|
71266
|
-
const declarations =
|
|
71333
|
+
const declarations = pkg.lotics[kind];
|
|
71267
71334
|
if (declarations && typeof declarations === "object" && !Array.isArray(declarations)) {
|
|
71268
71335
|
const map3 = declarations;
|
|
71269
71336
|
if (alias in map3) {
|
|
@@ -71271,7 +71338,7 @@ function readManifestEntry(projectDir, kind, alias) {
|
|
|
71271
71338
|
found = true;
|
|
71272
71339
|
}
|
|
71273
71340
|
}
|
|
71274
|
-
const baselines =
|
|
71341
|
+
const baselines = pkg.lotics.synced?.[kind];
|
|
71275
71342
|
if (baselines && alias in baselines) {
|
|
71276
71343
|
entry.synced = baselines[alias];
|
|
71277
71344
|
found = true;
|
|
@@ -71279,31 +71346,31 @@ function readManifestEntry(projectDir, kind, alias) {
|
|
|
71279
71346
|
return found ? entry : { found: false };
|
|
71280
71347
|
}
|
|
71281
71348
|
function readManifest(projectDir) {
|
|
71282
|
-
const
|
|
71283
|
-
return JSON.parse(fs8.readFileSync(
|
|
71349
|
+
const pkgPath = path9.join(projectDir, "package.json");
|
|
71350
|
+
return JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
|
|
71284
71351
|
}
|
|
71285
71352
|
function removeFromManifest(projectDir, kind, alias) {
|
|
71286
|
-
const
|
|
71287
|
-
const
|
|
71288
|
-
if (!
|
|
71289
|
-
const declarations =
|
|
71353
|
+
const pkgPath = path9.join(projectDir, "package.json");
|
|
71354
|
+
const pkg = readManifest(projectDir);
|
|
71355
|
+
if (!pkg.lotics) return;
|
|
71356
|
+
const declarations = pkg.lotics[kind];
|
|
71290
71357
|
if (declarations && typeof declarations === "object" && !Array.isArray(declarations)) {
|
|
71291
71358
|
delete declarations[alias];
|
|
71292
71359
|
}
|
|
71293
|
-
const baselines =
|
|
71360
|
+
const baselines = pkg.lotics.synced?.[kind];
|
|
71294
71361
|
if (baselines) delete baselines[alias];
|
|
71295
|
-
fs8.writeFileSync(
|
|
71362
|
+
fs8.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
71296
71363
|
}
|
|
71297
71364
|
function parkPrunedDeclaration(projectDir, kind, alias, removed) {
|
|
71298
|
-
const dir =
|
|
71365
|
+
const dir = path9.join(projectDir, ".lotics", "pruned", kind);
|
|
71299
71366
|
fs8.mkdirSync(dir, { recursive: true });
|
|
71300
|
-
const file2 =
|
|
71367
|
+
const file2 = path9.join(dir, `${alias}.json`);
|
|
71301
71368
|
fs8.writeFileSync(file2, JSON.stringify(removed, null, 2) + "\n");
|
|
71302
|
-
return
|
|
71369
|
+
return path9.relative(projectDir, file2);
|
|
71303
71370
|
}
|
|
71304
|
-
var WORKFLOWS_DIR =
|
|
71305
|
-
var WORKFLOW_GLOBALS_DIR =
|
|
71306
|
-
var AGENTS_DIR =
|
|
71371
|
+
var WORKFLOWS_DIR = path9.join("src", "workflows");
|
|
71372
|
+
var WORKFLOW_GLOBALS_DIR = path9.join(".lotics", "workflows");
|
|
71373
|
+
var AGENTS_DIR = path9.join("src", "agents");
|
|
71307
71374
|
var WORKFLOW_TSCONFIG_EXCLUDES = ["src/workflows", ".lotics/workflows"];
|
|
71308
71375
|
var LOTICS_INCLUDE_GLOB = ".lotics/**/*";
|
|
71309
71376
|
var STALE_LOTICS_INCLUDES = /* @__PURE__ */ new Set([".lotics", "./.lotics", ".lotics/"]);
|
|
@@ -71314,7 +71381,7 @@ function isMissingWorkflowBodyError(error52) {
|
|
|
71314
71381
|
return /has no step source|cannot be rendered|unsupported step/i.test(error52);
|
|
71315
71382
|
}
|
|
71316
71383
|
function workflowFileHeader(alias) {
|
|
71317
|
-
const refPath =
|
|
71384
|
+
const refPath = path9.join("..", "..", WORKFLOW_GLOBALS_DIR, `${alias}.globals.d.ts`).split(path9.sep).join("/");
|
|
71318
71385
|
return (
|
|
71319
71386
|
// The scaffold ships oxlint, whose `triple-slash-reference` rule flags the
|
|
71320
71387
|
// line below — so every pulled body arrived with a warning its author could
|
|
@@ -71337,27 +71404,27 @@ export {};
|
|
|
71337
71404
|
);
|
|
71338
71405
|
}
|
|
71339
71406
|
function workflowFilePath(projectDir, alias) {
|
|
71340
|
-
return
|
|
71407
|
+
return path9.join(projectDir, WORKFLOWS_DIR, `${alias}.ts`);
|
|
71341
71408
|
}
|
|
71342
71409
|
var GLOBALS_SUFFIX = ".globals.d.ts";
|
|
71343
71410
|
function workflowGlobalsPath(projectDir, alias) {
|
|
71344
|
-
return
|
|
71411
|
+
return path9.join(projectDir, WORKFLOW_GLOBALS_DIR, `${alias}${GLOBALS_SUFFIX}`);
|
|
71345
71412
|
}
|
|
71346
71413
|
function pruneOrphanWorkflowGlobals(projectDir, declared) {
|
|
71347
|
-
const dir =
|
|
71414
|
+
const dir = path9.join(projectDir, WORKFLOW_GLOBALS_DIR);
|
|
71348
71415
|
if (!fs8.existsSync(dir)) return [];
|
|
71349
71416
|
const removed = [];
|
|
71350
71417
|
for (const entry of fs8.readdirSync(dir)) {
|
|
71351
71418
|
if (!entry.endsWith(GLOBALS_SUFFIX)) continue;
|
|
71352
71419
|
const alias = entry.slice(0, -GLOBALS_SUFFIX.length);
|
|
71353
71420
|
if (declared.has(alias)) continue;
|
|
71354
|
-
fs8.unlinkSync(
|
|
71421
|
+
fs8.unlinkSync(path9.join(dir, entry));
|
|
71355
71422
|
removed.push(alias);
|
|
71356
71423
|
}
|
|
71357
71424
|
return removed.sort();
|
|
71358
71425
|
}
|
|
71359
71426
|
function orphanWorkflowBodies(projectDir, declared) {
|
|
71360
|
-
const dir =
|
|
71427
|
+
const dir = path9.join(projectDir, WORKFLOWS_DIR);
|
|
71361
71428
|
if (!fs8.existsSync(dir)) return [];
|
|
71362
71429
|
return fs8.readdirSync(dir).filter((e) => e.endsWith(".ts") && !e.endsWith(".d.ts") && !e.endsWith(".test.ts")).map((e) => e.slice(0, -".ts".length)).filter((alias) => !declared.has(alias)).sort();
|
|
71363
71430
|
}
|
|
@@ -71395,7 +71462,7 @@ function staleWorkflowGlobals(projectDir, workflows) {
|
|
|
71395
71462
|
return out;
|
|
71396
71463
|
}
|
|
71397
71464
|
function writeWorkflowGlobals(projectDir, alias, dts, declaration) {
|
|
71398
|
-
const dir =
|
|
71465
|
+
const dir = path9.join(projectDir, WORKFLOW_GLOBALS_DIR);
|
|
71399
71466
|
fs8.mkdirSync(dir, { recursive: true });
|
|
71400
71467
|
const file2 = workflowGlobalsPath(projectDir, alias);
|
|
71401
71468
|
const stamp = `${GLOBALS_STAMP_PREFIX}${workflowDeclarationStamp(declaration)}`;
|
|
@@ -71408,7 +71475,7 @@ function normalizeWorkflowBody(source) {
|
|
|
71408
71475
|
return source.replace(/\s+$/, "");
|
|
71409
71476
|
}
|
|
71410
71477
|
function writeWorkflowFile(projectDir, alias, source, envelope2 = { prefix: WORKFLOW_ENVELOPE_PREFIX, suffix: WORKFLOW_ENVELOPE_SUFFIX }) {
|
|
71411
|
-
const dir =
|
|
71478
|
+
const dir = path9.join(projectDir, WORKFLOWS_DIR);
|
|
71412
71479
|
fs8.mkdirSync(dir, { recursive: true });
|
|
71413
71480
|
const file2 = workflowFilePath(projectDir, alias);
|
|
71414
71481
|
const body = normalizeWorkflowBody(source);
|
|
@@ -71418,14 +71485,14 @@ ${envelope2.prefix}${body}${envelope2.suffix}
|
|
|
71418
71485
|
return file2;
|
|
71419
71486
|
}
|
|
71420
71487
|
function agentFilePath2(projectDir, alias) {
|
|
71421
|
-
return
|
|
71488
|
+
return path9.join(projectDir, ...agentFilePath(alias).split("/"));
|
|
71422
71489
|
}
|
|
71423
71490
|
var CLI_AGENT_NOTES = [
|
|
71424
71491
|
"Pulled from the LIVE app row; edit here, then: lotics app agent set <alias>",
|
|
71425
71492
|
"The typed fields (inputs/outputs/tool_names/model_tier) live in package.json#lotics.agents"
|
|
71426
71493
|
];
|
|
71427
71494
|
function writeAgentFile(projectDir, alias, instructions) {
|
|
71428
|
-
fs8.mkdirSync(
|
|
71495
|
+
fs8.mkdirSync(path9.join(projectDir, AGENTS_DIR), { recursive: true });
|
|
71429
71496
|
const file2 = agentFilePath2(projectDir, alias);
|
|
71430
71497
|
fs8.writeFileSync(
|
|
71431
71498
|
file2,
|
|
@@ -71451,15 +71518,15 @@ function writeAgentFiles(projectDir, agents, opts) {
|
|
|
71451
71518
|
return written;
|
|
71452
71519
|
}
|
|
71453
71520
|
function parkLiveAgentProse(projectDir, alias, instructions) {
|
|
71454
|
-
const dir =
|
|
71455
|
-
const file2 =
|
|
71521
|
+
const dir = path9.join(projectDir, ".lotics", "agents");
|
|
71522
|
+
const file2 = path9.join(dir, `${alias}.live.md`);
|
|
71456
71523
|
try {
|
|
71457
71524
|
fs8.mkdirSync(dir, { recursive: true });
|
|
71458
71525
|
fs8.writeFileSync(file2, normalizeAgentInstructions(instructions) + "\n");
|
|
71459
|
-
return
|
|
71526
|
+
return path9.relative(projectDir, file2);
|
|
71460
71527
|
} catch (err2) {
|
|
71461
71528
|
console.error(
|
|
71462
|
-
`\u26A0 Could not write the live prose for ${alias} to ${
|
|
71529
|
+
`\u26A0 Could not write the live prose for ${alias} to ${path9.relative(projectDir, file2)}: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
71463
71530
|
);
|
|
71464
71531
|
return null;
|
|
71465
71532
|
}
|
|
@@ -71475,15 +71542,15 @@ function reportUnseenLive(kind, unseen, appId) {
|
|
|
71475
71542
|
);
|
|
71476
71543
|
}
|
|
71477
71544
|
function parkLiveWorkflowBody(projectDir, alias, source) {
|
|
71478
|
-
const dir =
|
|
71479
|
-
const file2 =
|
|
71545
|
+
const dir = path9.join(projectDir, WORKFLOW_GLOBALS_DIR);
|
|
71546
|
+
const file2 = path9.join(dir, `${alias}.live.ts`);
|
|
71480
71547
|
try {
|
|
71481
71548
|
fs8.mkdirSync(dir, { recursive: true });
|
|
71482
71549
|
fs8.writeFileSync(file2, normalizeWorkflowBody(source) + "\n");
|
|
71483
|
-
return
|
|
71550
|
+
return path9.relative(projectDir, file2);
|
|
71484
71551
|
} catch (err2) {
|
|
71485
71552
|
console.error(
|
|
71486
|
-
`\u26A0 Could not write the live body for ${alias} to ${
|
|
71553
|
+
`\u26A0 Could not write the live body for ${alias} to ${path9.relative(projectDir, file2)}: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
71487
71554
|
);
|
|
71488
71555
|
return null;
|
|
71489
71556
|
}
|
|
@@ -71573,12 +71640,12 @@ async function writeWorkflowFiles(client, projectDir, app_id, appName, workflows
|
|
|
71573
71640
|
return { written, kept, unseenLive };
|
|
71574
71641
|
}
|
|
71575
71642
|
function writeWorkflowDescription(projectDir, alias, description) {
|
|
71576
|
-
const
|
|
71577
|
-
const
|
|
71578
|
-
const declaration =
|
|
71643
|
+
const pkgPath = path9.join(projectDir, "package.json");
|
|
71644
|
+
const pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
|
|
71645
|
+
const declaration = pkg.lotics?.workflows?.[alias];
|
|
71579
71646
|
if (!declaration) return;
|
|
71580
71647
|
declaration.description = description;
|
|
71581
|
-
fs8.writeFileSync(
|
|
71648
|
+
fs8.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
71582
71649
|
}
|
|
71583
71650
|
async function fetchWorkflowGlobals(client, projectDir, app_id, alias, declaration) {
|
|
71584
71651
|
try {
|
|
@@ -71617,62 +71684,101 @@ function runTar(args, cwd) {
|
|
|
71617
71684
|
});
|
|
71618
71685
|
}
|
|
71619
71686
|
function runNpm(args, cwd) {
|
|
71687
|
+
const quiet = isMachineOutput();
|
|
71620
71688
|
return new Promise((resolve2, reject2) => {
|
|
71621
|
-
const proc = spawn2("npm", args, {
|
|
71689
|
+
const proc = spawn2("npm", args, {
|
|
71690
|
+
cwd,
|
|
71691
|
+
// On Windows `npm` is `npm.cmd`, a batch file Node will not execute
|
|
71692
|
+
// without a shell — bare `spawn("npm")` dies at ENOENT, which took every
|
|
71693
|
+
// command that installs or builds with it. A shell is safe here because
|
|
71694
|
+
// the arguments are literals this file writes (`run build`, `ci
|
|
71695
|
+
// --ignore-scripts`); nothing a caller supplies reaches the command line.
|
|
71696
|
+
//
|
|
71697
|
+
// The alternative — run npm's own JS entry with `process.execPath`, as
|
|
71698
|
+
// `dev/server.ts` does for vite — works there because vite sits at a known
|
|
71699
|
+
// path inside the project. npm does not: nvm-windows, volta, corepack and
|
|
71700
|
+
// the installer each put it somewhere different, and letting the platform
|
|
71701
|
+
// resolve its own shim is the one approach that finds all of them.
|
|
71702
|
+
shell: process.platform === "win32",
|
|
71703
|
+
stdio: quiet ? ["ignore", "pipe", "pipe"] : "inherit",
|
|
71704
|
+
env: ipv4ChildEnv(process.env)
|
|
71705
|
+
});
|
|
71706
|
+
let captured = "";
|
|
71707
|
+
if (quiet) {
|
|
71708
|
+
const collect = (chunk) => {
|
|
71709
|
+
captured += chunk.toString();
|
|
71710
|
+
if (captured.length > NPM_LOG_TAIL_BYTES * 2) {
|
|
71711
|
+
captured = captured.slice(-NPM_LOG_TAIL_BYTES);
|
|
71712
|
+
}
|
|
71713
|
+
};
|
|
71714
|
+
proc.stdout?.on("data", collect);
|
|
71715
|
+
proc.stderr?.on("data", collect);
|
|
71716
|
+
}
|
|
71622
71717
|
proc.on("error", reject2);
|
|
71623
71718
|
proc.on("exit", (code) => {
|
|
71624
|
-
if (code === 0)
|
|
71625
|
-
|
|
71719
|
+
if (code === 0) {
|
|
71720
|
+
resolve2();
|
|
71721
|
+
return;
|
|
71722
|
+
}
|
|
71723
|
+
const tail = captured.slice(-NPM_LOG_TAIL_BYTES).trim();
|
|
71724
|
+
reject2(
|
|
71725
|
+
new Error(
|
|
71726
|
+
`npm ${args.join(" ")} exited with code ${code}` + (tail === "" ? "" : `
|
|
71727
|
+
--- npm output ---
|
|
71728
|
+
${tail}`)
|
|
71729
|
+
)
|
|
71730
|
+
);
|
|
71626
71731
|
});
|
|
71627
71732
|
});
|
|
71628
71733
|
}
|
|
71734
|
+
var NPM_LOG_TAIL_BYTES = 8e3;
|
|
71629
71735
|
function npmInstallArgs(hasLockfile) {
|
|
71630
71736
|
return [hasLockfile ? "ci" : "install", "--ignore-scripts"];
|
|
71631
71737
|
}
|
|
71632
71738
|
function runNpmInstall(cwd) {
|
|
71633
|
-
const hasLockfile = fs8.existsSync(
|
|
71634
|
-
|
|
71739
|
+
const hasLockfile = fs8.existsSync(path9.join(cwd, "package-lock.json"));
|
|
71740
|
+
note(
|
|
71635
71741
|
hasLockfile ? "Installing npm dependencies (npm ci \u2014 the lockfile's exact tree, no install scripts)..." : "Installing npm dependencies (no lockfile yet \u2014 resolving ranges, no install scripts)..."
|
|
71636
71742
|
);
|
|
71637
71743
|
return runNpm(npmInstallArgs(hasLockfile), cwd);
|
|
71638
71744
|
}
|
|
71639
71745
|
function readAppWorkspaceId(projectDir) {
|
|
71640
71746
|
try {
|
|
71641
|
-
const
|
|
71642
|
-
if (!fs8.existsSync(
|
|
71643
|
-
const
|
|
71644
|
-
return
|
|
71747
|
+
const pkgPath = path9.join(projectDir, "package.json");
|
|
71748
|
+
if (!fs8.existsSync(pkgPath)) return null;
|
|
71749
|
+
const pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
|
|
71750
|
+
return pkg.lotics?.workspace_id ?? null;
|
|
71645
71751
|
} catch {
|
|
71646
71752
|
return null;
|
|
71647
71753
|
}
|
|
71648
71754
|
}
|
|
71649
71755
|
function readAppMeta(projectDir) {
|
|
71650
|
-
const
|
|
71651
|
-
if (!fs8.existsSync(
|
|
71756
|
+
const pkgPath = path9.join(projectDir, "package.json");
|
|
71757
|
+
if (!fs8.existsSync(pkgPath)) {
|
|
71652
71758
|
throw new Error(`No package.json found at ${projectDir}. Run 'lotics app create' first.`);
|
|
71653
71759
|
}
|
|
71654
|
-
const
|
|
71655
|
-
if (!
|
|
71760
|
+
const pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
|
|
71761
|
+
if (!pkg.lotics?.app_id || !pkg.lotics.workspace_id) {
|
|
71656
71762
|
throw new Error(
|
|
71657
71763
|
`package.json is missing the 'lotics' field with app_id and workspace_id. Was this folder created with 'lotics app create'?`
|
|
71658
71764
|
);
|
|
71659
71765
|
}
|
|
71660
|
-
noteScope({ app_id:
|
|
71766
|
+
noteScope({ app_id: pkg.lotics.app_id });
|
|
71661
71767
|
return {
|
|
71662
|
-
app_id:
|
|
71663
|
-
workspace_id:
|
|
71664
|
-
current_version_id:
|
|
71665
|
-
version_number:
|
|
71666
|
-
workflows:
|
|
71667
|
-
queries:
|
|
71668
|
-
agents:
|
|
71669
|
-
capabilities:
|
|
71768
|
+
app_id: pkg.lotics.app_id,
|
|
71769
|
+
workspace_id: pkg.lotics.workspace_id,
|
|
71770
|
+
current_version_id: pkg.lotics.current_version_id ?? null,
|
|
71771
|
+
version_number: pkg.lotics.version_number ?? null,
|
|
71772
|
+
workflows: pkg.lotics.workflows ?? {},
|
|
71773
|
+
queries: pkg.lotics.queries ?? {},
|
|
71774
|
+
agents: pkg.lotics.agents ?? {},
|
|
71775
|
+
capabilities: pkg.lotics.capabilities
|
|
71670
71776
|
};
|
|
71671
71777
|
}
|
|
71672
71778
|
function writeAppMeta(projectDir, meta3) {
|
|
71673
|
-
const
|
|
71674
|
-
const
|
|
71675
|
-
const existing =
|
|
71779
|
+
const pkgPath = path9.join(projectDir, "package.json");
|
|
71780
|
+
const pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
|
|
71781
|
+
const existing = pkg.lotics && typeof pkg.lotics === "object" ? pkg.lotics : {};
|
|
71676
71782
|
const supplied = new Set(
|
|
71677
71783
|
Object.entries(meta3).filter(([, value2]) => value2 !== void 0).map(([key]) => key)
|
|
71678
71784
|
);
|
|
@@ -71680,20 +71786,20 @@ function writeAppMeta(projectDir, meta3) {
|
|
|
71680
71786
|
for (const [key, value2] of Object.entries(existing)) {
|
|
71681
71787
|
if (!supplied.has(key)) preserved[key] = value2;
|
|
71682
71788
|
}
|
|
71683
|
-
|
|
71684
|
-
fs8.writeFileSync(
|
|
71789
|
+
pkg.lotics = { ...meta3, ...preserved };
|
|
71790
|
+
fs8.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
71685
71791
|
}
|
|
71686
71792
|
function writeWorkflowOutputs(projectDir, alias, outputs) {
|
|
71687
|
-
const
|
|
71688
|
-
const
|
|
71689
|
-
const declaration =
|
|
71793
|
+
const pkgPath = path9.join(projectDir, "package.json");
|
|
71794
|
+
const pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
|
|
71795
|
+
const declaration = pkg.lotics?.workflows?.[alias];
|
|
71690
71796
|
if (!declaration) {
|
|
71691
71797
|
throw new Error(
|
|
71692
71798
|
`package.json#lotics.workflows.${alias} disappeared before the derived-outputs write-back.`
|
|
71693
71799
|
);
|
|
71694
71800
|
}
|
|
71695
71801
|
declaration.outputs = outputs;
|
|
71696
|
-
fs8.writeFileSync(
|
|
71802
|
+
fs8.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
71697
71803
|
}
|
|
71698
71804
|
function workflowBodyDrift(projectDir, workflows, synced = {}) {
|
|
71699
71805
|
const drifted = [];
|
|
@@ -71709,7 +71815,7 @@ function workflowBodyDrift(projectDir, workflows, synced = {}) {
|
|
|
71709
71815
|
return drifted;
|
|
71710
71816
|
}
|
|
71711
71817
|
function ensureAppTsconfig(projectDir) {
|
|
71712
|
-
const tsconfigPath =
|
|
71818
|
+
const tsconfigPath = path9.join(projectDir, "tsconfig.json");
|
|
71713
71819
|
if (!fs8.existsSync(tsconfigPath)) {
|
|
71714
71820
|
console.error(
|
|
71715
71821
|
`\u26A0 No tsconfig.json at ${projectDir} \u2014 could not ensure "include" has "${LOTICS_INCLUDE_GLOB}" (a bare .lotics loads none of the generated types) or "exclude" has ${WORKFLOW_TSCONFIG_EXCLUDES.join(", ")}.`
|
|
@@ -71761,15 +71867,15 @@ function writeDevLinkTsconfig(projectDir) {
|
|
|
71761
71867
|
if (uiSrc) {
|
|
71762
71868
|
paths["@lotics/ui/*"] = [`${uiSrc}/*`];
|
|
71763
71869
|
for (const peer of readKitPeerNames(projectDir)) {
|
|
71764
|
-
const typesDir =
|
|
71765
|
-
const runtimeDir =
|
|
71870
|
+
const typesDir = path9.join(projectDir, "node_modules", typesPackageFor(peer));
|
|
71871
|
+
const runtimeDir = path9.join(projectDir, "node_modules", peer);
|
|
71766
71872
|
const target = fs8.existsSync(typesDir) ? `../node_modules/${typesPackageFor(peer)}` : fs8.existsSync(runtimeDir) ? `../node_modules/${peer}` : null;
|
|
71767
71873
|
if (!target) continue;
|
|
71768
71874
|
paths[peer] = [target];
|
|
71769
71875
|
paths[`${peer}/*`] = [`${target}/*`];
|
|
71770
71876
|
}
|
|
71771
71877
|
}
|
|
71772
|
-
const file2 =
|
|
71878
|
+
const file2 = path9.join(projectDir, ".lotics", "tsconfig.link.json");
|
|
71773
71879
|
const header = uiSrc ? `// GENERATED by \`lotics app codegen\` \u2014 do not edit.
|
|
71774
71880
|
// LOTICS_UI_SRC is set, so @lotics/ui resolves to your working copy for tsc,
|
|
71775
71881
|
// vitest, eslint and your editor \u2014 the same copy Vite is bundling. The peer
|
|
@@ -71786,8 +71892,8 @@ function writeDevLinkTsconfig(projectDir) {
|
|
|
71786
71892
|
}
|
|
71787
71893
|
function writeKitTypeAugmentation(projectDir) {
|
|
71788
71894
|
const uiSrc = process.env.LOTICS_UI_SRC;
|
|
71789
|
-
const source = uiSrc ?
|
|
71790
|
-
const target =
|
|
71895
|
+
const source = uiSrc ? path9.join(uiSrc, "react_native.d.ts") : path9.join(projectDir, "node_modules", "@lotics", "ui", "src", "react_native.d.ts");
|
|
71896
|
+
const target = path9.join(projectDir, ".lotics", "react_native.d.ts");
|
|
71791
71897
|
if (!fs8.existsSync(source)) {
|
|
71792
71898
|
if (fs8.existsSync(target)) fs8.rmSync(target);
|
|
71793
71899
|
return;
|
|
@@ -71804,7 +71910,7 @@ function typesPackageFor(peer) {
|
|
|
71804
71910
|
return peer.startsWith("@") ? `@types/${peer.slice(1).replace("/", "__")}` : `@types/${peer}`;
|
|
71805
71911
|
}
|
|
71806
71912
|
function readKitPeerNames(projectDir) {
|
|
71807
|
-
const kitPkg =
|
|
71913
|
+
const kitPkg = path9.join(projectDir, "node_modules", "@lotics", "ui", "package.json");
|
|
71808
71914
|
if (!fs8.existsSync(kitPkg)) return [];
|
|
71809
71915
|
const parsed = JSON.parse(fs8.readFileSync(kitPkg, "utf-8"));
|
|
71810
71916
|
const peers = parsed.peerDependencies;
|
|
@@ -71815,12 +71921,12 @@ function writeAppDtsKitLinks(projectDir) {
|
|
|
71815
71921
|
writeKitTypeAugmentation(projectDir);
|
|
71816
71922
|
}
|
|
71817
71923
|
function writeAppDts(projectDir, manifest) {
|
|
71818
|
-
const dotLotics =
|
|
71924
|
+
const dotLotics = path9.join(projectDir, ".lotics");
|
|
71819
71925
|
fs8.mkdirSync(dotLotics, { recursive: true });
|
|
71820
71926
|
const written = [
|
|
71821
|
-
[
|
|
71822
|
-
[
|
|
71823
|
-
[
|
|
71927
|
+
[path9.join(dotLotics, "app_workflows.d.ts"), generateAppWorkflowsDts(manifest.workflows)],
|
|
71928
|
+
[path9.join(dotLotics, "app_queries.d.ts"), generateAppQueriesDts(manifest.queries)],
|
|
71929
|
+
[path9.join(dotLotics, "app_agents.d.ts"), generateAppAgentsDts(manifest.agents)]
|
|
71824
71930
|
];
|
|
71825
71931
|
for (const [file2, content] of written) fs8.writeFileSync(file2, content);
|
|
71826
71932
|
writeAppDtsKitLinks(projectDir);
|
|
@@ -71829,8 +71935,8 @@ function writeAppDts(projectDir, manifest) {
|
|
|
71829
71935
|
return written.map(([file2]) => file2);
|
|
71830
71936
|
}
|
|
71831
71937
|
function readCodegenTablesAllowlist(projectDir) {
|
|
71832
|
-
const
|
|
71833
|
-
const tables =
|
|
71938
|
+
const pkg = JSON.parse(fs8.readFileSync(path9.join(projectDir, "package.json"), "utf-8"));
|
|
71939
|
+
const tables = pkg.lotics?.codegen?.tables;
|
|
71834
71940
|
return Array.isArray(tables) ? tables.filter((t) => typeof t === "string") : [];
|
|
71835
71941
|
}
|
|
71836
71942
|
function resolveCodegenTableIds(projectDir, queries) {
|
|
@@ -71842,9 +71948,9 @@ function resolveCodegenTableIds(projectDir, queries) {
|
|
|
71842
71948
|
return [...ids];
|
|
71843
71949
|
}
|
|
71844
71950
|
function writeAppFields(projectDir, tables) {
|
|
71845
|
-
const dotLotics =
|
|
71951
|
+
const dotLotics = path9.join(projectDir, ".lotics");
|
|
71846
71952
|
fs8.mkdirSync(dotLotics, { recursive: true });
|
|
71847
|
-
const file2 =
|
|
71953
|
+
const file2 = path9.join(dotLotics, "app_fields.ts");
|
|
71848
71954
|
fs8.writeFileSync(file2, generateAppFields(tables));
|
|
71849
71955
|
return file2;
|
|
71850
71956
|
}
|
|
@@ -71869,7 +71975,7 @@ async function writeGeneratedAppFields(client, projectDir, app, queries) {
|
|
|
71869
71975
|
return;
|
|
71870
71976
|
}
|
|
71871
71977
|
const fieldsPath = writeAppFields(projectDir, tables);
|
|
71872
|
-
|
|
71978
|
+
note(
|
|
71873
71979
|
`Wrote ${fieldsPath} (baked form \u2014 bespoke; ${tables.length} table${tables.length === 1 ? "" : "s"})`
|
|
71874
71980
|
);
|
|
71875
71981
|
}
|
|
@@ -71879,7 +71985,7 @@ async function writeGeneratedAppFields(client, projectDir, app, queries) {
|
|
|
71879
71985
|
}
|
|
71880
71986
|
function warnAppFieldsUnwritten(projectDir, err2) {
|
|
71881
71987
|
const reason = err2 instanceof Error ? err2.message : String(err2);
|
|
71882
|
-
if (fs8.existsSync(
|
|
71988
|
+
if (fs8.existsSync(path9.join(projectDir, ".lotics", "app_fields.ts"))) {
|
|
71883
71989
|
console.error(`\u26A0 Could not regenerate .lotics/app_fields.ts (${reason}). Kept the existing file.`);
|
|
71884
71990
|
return;
|
|
71885
71991
|
}
|
|
@@ -71890,7 +71996,7 @@ function warnAppFieldsUnwritten(projectDir, err2) {
|
|
|
71890
71996
|
function warnAboutDevLink(projectDir, command) {
|
|
71891
71997
|
const uiSrc = process.env.LOTICS_UI_SRC;
|
|
71892
71998
|
if (!uiSrc) return;
|
|
71893
|
-
const viteConfigPath =
|
|
71999
|
+
const viteConfigPath = path9.join(projectDir, "vite.config.ts");
|
|
71894
72000
|
const config2 = fs8.existsSync(viteConfigPath) ? fs8.readFileSync(viteConfigPath, "utf-8") : "";
|
|
71895
72001
|
const linked = config2.includes("loticsResolve") || config2.includes("LOTICS_UI_SRC");
|
|
71896
72002
|
if (!linked) {
|
|
@@ -71909,9 +72015,9 @@ function warnAboutDevLink(projectDir, command) {
|
|
|
71909
72015
|
}
|
|
71910
72016
|
}
|
|
71911
72017
|
var KIT_PACKAGES = ["@lotics/ui", "@lotics/app-sdk"];
|
|
71912
|
-
function installedKitVersion(projectDir,
|
|
72018
|
+
function installedKitVersion(projectDir, pkg) {
|
|
71913
72019
|
try {
|
|
71914
|
-
const manifest =
|
|
72020
|
+
const manifest = path9.join(projectDir, "node_modules", ...pkg.split("/"), "package.json");
|
|
71915
72021
|
const parsed = JSON.parse(fs8.readFileSync(manifest, "utf-8"));
|
|
71916
72022
|
const version2 = parsed.version;
|
|
71917
72023
|
return typeof version2 === "string" ? version2 : null;
|
|
@@ -71919,12 +72025,12 @@ function installedKitVersion(projectDir, pkg2) {
|
|
|
71919
72025
|
return null;
|
|
71920
72026
|
}
|
|
71921
72027
|
}
|
|
71922
|
-
async function publishedKitVersion(
|
|
72028
|
+
async function publishedKitVersion(pkg) {
|
|
71923
72029
|
const controller = new AbortController();
|
|
71924
72030
|
const timeout = setTimeout(() => controller.abort(), 3e3);
|
|
71925
72031
|
timeout.unref();
|
|
71926
72032
|
try {
|
|
71927
|
-
const response = await fetch(`https://registry.npmjs.org/${
|
|
72033
|
+
const response = await fetch(`https://registry.npmjs.org/${pkg}/latest`, {
|
|
71928
72034
|
signal: controller.signal
|
|
71929
72035
|
});
|
|
71930
72036
|
if (!response.ok) return null;
|
|
@@ -71938,13 +72044,13 @@ async function publishedKitVersion(pkg2) {
|
|
|
71938
72044
|
}
|
|
71939
72045
|
async function warnIfKitBehind(projectDir) {
|
|
71940
72046
|
const checks = await Promise.all(
|
|
71941
|
-
KIT_PACKAGES.map(async (
|
|
71942
|
-
const installed = installedKitVersion(projectDir,
|
|
72047
|
+
KIT_PACKAGES.map(async (pkg) => {
|
|
72048
|
+
const installed = installedKitVersion(projectDir, pkg);
|
|
71943
72049
|
if (!installed) return null;
|
|
71944
|
-
const latest = await publishedKitVersion(
|
|
72050
|
+
const latest = await publishedKitVersion(pkg);
|
|
71945
72051
|
if (!latest || !isNewerVersion(latest, installed)) return null;
|
|
71946
72052
|
const behindMajor = (Number.parseInt(latest, 10) || 0) > (Number.parseInt(installed, 10) || 0);
|
|
71947
|
-
return { pkg
|
|
72053
|
+
return { pkg, installed, latest, behindMajor };
|
|
71948
72054
|
})
|
|
71949
72055
|
);
|
|
71950
72056
|
const findings = checks.filter((c) => c !== null);
|
|
@@ -71959,7 +72065,7 @@ async function warnIfKitBehind(projectDir) {
|
|
|
71959
72065
|
|
|
71960
72066
|
Breaking changes are listed newest-first in
|
|
71961
72067
|
node_modules/@lotics/ui/MIGRATION.md.` : "";
|
|
71962
|
-
|
|
72068
|
+
warn(
|
|
71963
72069
|
`
|
|
71964
72070
|
\u26A0 This app builds against a kit a major release behind:
|
|
71965
72071
|
` + lines.join("\n") + migration + `
|
|
@@ -71975,12 +72081,12 @@ A newer kit is published \u2014 \`npm update ${findings.map((f) => f.pkg).join("
|
|
|
71975
72081
|
);
|
|
71976
72082
|
}
|
|
71977
72083
|
function ensureAppVitestSetup(projectDir) {
|
|
71978
|
-
const setupPath =
|
|
72084
|
+
const setupPath = path9.join(projectDir, VITEST_SETUP_FILENAME);
|
|
71979
72085
|
if (!fs8.existsSync(setupPath)) {
|
|
71980
72086
|
fs8.writeFileSync(setupPath, VITEST_SETUP_CONTENT);
|
|
71981
72087
|
console.error(`Wrote ${VITEST_SETUP_FILENAME} (wired by vite.config.ts; empty until you fill it).`);
|
|
71982
72088
|
}
|
|
71983
|
-
const viteConfigPath =
|
|
72089
|
+
const viteConfigPath = path9.join(projectDir, "vite.config.ts");
|
|
71984
72090
|
if (!fs8.existsSync(viteConfigPath)) return;
|
|
71985
72091
|
const viteConfig = fs8.readFileSync(viteConfigPath, "utf-8");
|
|
71986
72092
|
if (/setupFiles\s*:/.test(viteConfig) && viteConfig.includes(VITEST_SETUP_FILENAME)) return;
|
|
@@ -71990,7 +72096,7 @@ function ensureAppVitestSetup(projectDir) {
|
|
|
71990
72096
|
);
|
|
71991
72097
|
}
|
|
71992
72098
|
async function appCodegen(args) {
|
|
71993
|
-
const projectDir =
|
|
72099
|
+
const projectDir = path9.resolve(args.projectDir ?? process.cwd());
|
|
71994
72100
|
const meta3 = readAppMeta(projectDir);
|
|
71995
72101
|
const dtsPaths = writeAppDts(projectDir, {
|
|
71996
72102
|
workflows: meta3.workflows,
|
|
@@ -72004,7 +72110,7 @@ async function appCodegen(args) {
|
|
|
72004
72110
|
}
|
|
72005
72111
|
for (const alias of orphanWorkflowBodies(projectDir, declared)) {
|
|
72006
72112
|
console.error(
|
|
72007
|
-
`\u26A0 ${
|
|
72113
|
+
`\u26A0 ${path9.join(WORKFLOWS_DIR, `${alias}.ts`)} is not declared in package.json#lotics.workflows \u2014 'workflow check' and 'workflow set' both skip it. Declare the alias or delete the file.`
|
|
72008
72114
|
);
|
|
72009
72115
|
}
|
|
72010
72116
|
if (!args.client) {
|
|
@@ -72063,15 +72169,15 @@ async function refreshWorkflowTypes(client, projectDir, app_id, alias, declarati
|
|
|
72063
72169
|
return true;
|
|
72064
72170
|
}
|
|
72065
72171
|
function readPriorStamp(projectDir) {
|
|
72066
|
-
const
|
|
72067
|
-
if (!fs8.existsSync(
|
|
72068
|
-
let
|
|
72172
|
+
const pkgPath = path9.join(projectDir, "package.json");
|
|
72173
|
+
if (!fs8.existsSync(pkgPath)) return null;
|
|
72174
|
+
let pkg;
|
|
72069
72175
|
try {
|
|
72070
|
-
|
|
72176
|
+
pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
|
|
72071
72177
|
} catch {
|
|
72072
72178
|
return null;
|
|
72073
72179
|
}
|
|
72074
|
-
const lotics =
|
|
72180
|
+
const lotics = pkg.lotics && typeof pkg.lotics === "object" ? pkg.lotics : null;
|
|
72075
72181
|
if (!lotics) return null;
|
|
72076
72182
|
const id = lotics.current_version_id;
|
|
72077
72183
|
const number4 = lotics.version_number;
|
|
@@ -72132,8 +72238,8 @@ function appDirName(name2) {
|
|
|
72132
72238
|
}
|
|
72133
72239
|
async function materializeScaffold(targetPath, files) {
|
|
72134
72240
|
for (const file2 of files) {
|
|
72135
|
-
const fullPath =
|
|
72136
|
-
fs8.mkdirSync(
|
|
72241
|
+
const fullPath = path9.join(targetPath, file2.path);
|
|
72242
|
+
fs8.mkdirSync(path9.dirname(fullPath), { recursive: true });
|
|
72137
72243
|
fs8.writeFileSync(fullPath, file2.content);
|
|
72138
72244
|
}
|
|
72139
72245
|
console.error(`Scaffolded ${files.length} files into ${targetPath}`);
|
|
@@ -72142,7 +72248,7 @@ async function materializeScaffold(targetPath, files) {
|
|
|
72142
72248
|
writeAppDtsKitLinks(targetPath);
|
|
72143
72249
|
}
|
|
72144
72250
|
async function appCreate(client, args) {
|
|
72145
|
-
const targetPath =
|
|
72251
|
+
const targetPath = path9.resolve(args.targetPath ?? appDirName(args.name));
|
|
72146
72252
|
if (fs8.existsSync(targetPath)) {
|
|
72147
72253
|
const entries2 = fs8.readdirSync(targetPath);
|
|
72148
72254
|
if (entries2.length > 0) {
|
|
@@ -72171,7 +72277,7 @@ async function appCreate(client, args) {
|
|
|
72171
72277
|
});
|
|
72172
72278
|
console.error(`
|
|
72173
72279
|
Ready. Next steps:`);
|
|
72174
|
-
console.error(` cd ${
|
|
72280
|
+
console.error(` cd ${path9.relative(process.cwd(), targetPath) || "."}`);
|
|
72175
72281
|
console.error(` lotics docs # the contracts, at the versions installed here`);
|
|
72176
72282
|
console.error(` # edit src/App.tsx, then:`);
|
|
72177
72283
|
console.error(` lotics app check # every pre-flight a deploy runs`);
|
|
@@ -72230,17 +72336,17 @@ async function appVersions(client, args) {
|
|
|
72230
72336
|
}
|
|
72231
72337
|
}
|
|
72232
72338
|
function defaultPullTarget(appId, appName) {
|
|
72233
|
-
const cwdPkgPath =
|
|
72339
|
+
const cwdPkgPath = path9.join(process.cwd(), "package.json");
|
|
72234
72340
|
if (fs8.existsSync(cwdPkgPath)) {
|
|
72235
|
-
let
|
|
72341
|
+
let pkg = null;
|
|
72236
72342
|
try {
|
|
72237
|
-
|
|
72343
|
+
pkg = JSON.parse(fs8.readFileSync(cwdPkgPath, "utf-8"));
|
|
72238
72344
|
} catch (err2) {
|
|
72239
72345
|
console.error(
|
|
72240
72346
|
`\u26A0 Could not parse ${cwdPkgPath} (${err2 instanceof Error ? err2.message : String(err2)}) \u2014 pulling into a fresh ${appDirName(appName)}/ subdir.`
|
|
72241
72347
|
);
|
|
72242
72348
|
}
|
|
72243
|
-
if (
|
|
72349
|
+
if (pkg?.lotics?.app_id === appId) return process.cwd();
|
|
72244
72350
|
}
|
|
72245
72351
|
return appDirName(appName);
|
|
72246
72352
|
}
|
|
@@ -72280,7 +72386,7 @@ async function hydrateAppProject(client, targetPath, app, opts) {
|
|
|
72280
72386
|
);
|
|
72281
72387
|
opts.kept.push(...kept);
|
|
72282
72388
|
if (written.length > 0) {
|
|
72283
|
-
|
|
72389
|
+
note(
|
|
72284
72390
|
`Wrote ${written.length} workflow ${written.length === 1 ? "body" : "bodies"} to ${WORKFLOWS_DIR}/ (${written.join(", ")})`
|
|
72285
72391
|
);
|
|
72286
72392
|
}
|
|
@@ -72312,7 +72418,7 @@ async function hydrateAppProject(client, targetPath, app, opts) {
|
|
|
72312
72418
|
unseenLiveProse.push({ alias, parked: parkLiveAgentProse(targetPath, alias, instructions) });
|
|
72313
72419
|
}
|
|
72314
72420
|
if (written.length > 0) {
|
|
72315
|
-
|
|
72421
|
+
note(
|
|
72316
72422
|
`Wrote ${written.length} agent instruction ${written.length === 1 ? "file" : "files"} to ${AGENTS_DIR}/ (${written.join(", ")})`
|
|
72317
72423
|
);
|
|
72318
72424
|
}
|
|
@@ -72332,21 +72438,21 @@ async function appPull(client, args) {
|
|
|
72332
72438
|
if (!versionId) throw new Error(`App ${app.id} has no version to pull.`);
|
|
72333
72439
|
const version2 = await client.getAppVersion(app.id, versionId);
|
|
72334
72440
|
const sourceUrl = await client.getAppVersionSourceUrl(app.id, version2.id);
|
|
72335
|
-
const targetPath =
|
|
72441
|
+
const targetPath = path9.resolve(args.targetPath ?? defaultPullTarget(app.id, app.name));
|
|
72336
72442
|
fs8.mkdirSync(targetPath, { recursive: true });
|
|
72337
72443
|
const prior = readPriorStamp(targetPath);
|
|
72338
|
-
const tmpFile =
|
|
72444
|
+
const tmpFile = path9.join(tmpdir(), `lotics-app-${app.id}-${Date.now()}.tar.gz`);
|
|
72339
72445
|
console.error(`Downloading source archive...`);
|
|
72340
72446
|
await downloadToFile(sourceUrl, tmpFile);
|
|
72341
72447
|
const keptLocal = [];
|
|
72342
72448
|
const restoredFromArchive = [];
|
|
72343
|
-
const stagingDir = fs8.mkdtempSync(
|
|
72449
|
+
const stagingDir = fs8.mkdtempSync(path9.join(tmpdir(), `lotics-pull-${app.id}-`));
|
|
72344
72450
|
try {
|
|
72345
72451
|
await runTar(["-xzf", tmpFile, "-C", stagingDir], stagingDir);
|
|
72346
72452
|
console.error(`Extracting to ${targetPath}...`);
|
|
72347
72453
|
const copied = copyTree(stagingDir, targetPath, {
|
|
72348
72454
|
overwrite: args.force === true,
|
|
72349
|
-
skip: [WORKFLOWS_DIR, AGENTS_DIR].map((d) => d.split(
|
|
72455
|
+
skip: [WORKFLOWS_DIR, AGENTS_DIR].map((d) => d.split(path9.sep).join("/"))
|
|
72350
72456
|
});
|
|
72351
72457
|
keptLocal.push(...copied.kept);
|
|
72352
72458
|
restoredFromArchive.push(...copied.created);
|
|
@@ -72375,20 +72481,20 @@ async function appPull(client, args) {
|
|
|
72375
72481
|
});
|
|
72376
72482
|
console.error(`
|
|
72377
72483
|
Ready. Next steps:`);
|
|
72378
|
-
console.error(` cd ${
|
|
72484
|
+
console.error(` cd ${path9.relative(process.cwd(), targetPath) || "."}`);
|
|
72379
72485
|
console.error(` lotics docs # the contracts, at the versions installed here`);
|
|
72380
72486
|
console.error(` # edit src/App.tsx, then:`);
|
|
72381
72487
|
console.error(` lotics app deploy`);
|
|
72382
72488
|
}
|
|
72383
72489
|
function readAppSourceText(projectDir) {
|
|
72384
|
-
const srcDir =
|
|
72490
|
+
const srcDir = path9.join(projectDir, "src");
|
|
72385
72491
|
if (!fs8.existsSync(srcDir)) return "";
|
|
72386
72492
|
const parts = [];
|
|
72387
72493
|
const walk2 = (dir) => {
|
|
72388
72494
|
for (const entry of fs8.readdirSync(dir, { withFileTypes: true })) {
|
|
72389
|
-
const full =
|
|
72495
|
+
const full = path9.join(dir, entry.name);
|
|
72390
72496
|
if (entry.isDirectory()) walk2(full);
|
|
72391
|
-
else if (isAppSourcePath(
|
|
72497
|
+
else if (isAppSourcePath(path9.relative(projectDir, full))) {
|
|
72392
72498
|
parts.push(fs8.readFileSync(full, "utf8"));
|
|
72393
72499
|
}
|
|
72394
72500
|
}
|
|
@@ -72397,7 +72503,7 @@ function readAppSourceText(projectDir) {
|
|
|
72397
72503
|
return parts.join("\n");
|
|
72398
72504
|
}
|
|
72399
72505
|
async function appDeploy(client, args) {
|
|
72400
|
-
const projectDir =
|
|
72506
|
+
const projectDir = path9.resolve(args.projectDir ?? process.cwd());
|
|
72401
72507
|
const meta3 = readAppMeta(projectDir);
|
|
72402
72508
|
warnAboutDevLink(projectDir, "deploy");
|
|
72403
72509
|
const liveApp = await client.getApp(meta3.app_id);
|
|
@@ -72426,23 +72532,23 @@ async function appDeploy(client, args) {
|
|
|
72426
72532
|
meta3.queries ?? {}
|
|
72427
72533
|
);
|
|
72428
72534
|
} catch (err2) {
|
|
72429
|
-
|
|
72535
|
+
warn(
|
|
72430
72536
|
`\u26A0 Could not regenerate .lotics/app_fields.ts (${err2.message}).
|
|
72431
72537
|
The build will use whatever is on disk \u2014 run 'lotics app codegen' if this app is published.`
|
|
72432
72538
|
);
|
|
72433
72539
|
}
|
|
72434
|
-
|
|
72540
|
+
note("Building...");
|
|
72435
72541
|
await runNpm(["run", "build"], projectDir);
|
|
72436
|
-
const distDir =
|
|
72542
|
+
const distDir = path9.join(projectDir, "dist");
|
|
72437
72543
|
if (!fs8.existsSync(distDir)) {
|
|
72438
72544
|
throw new Error(
|
|
72439
72545
|
`Build did not produce a dist/ directory in ${projectDir}. Check that 'npm run build' is configured correctly (Vite/etc. defaults to dist/).`
|
|
72440
72546
|
);
|
|
72441
72547
|
}
|
|
72442
|
-
const tmpSource =
|
|
72443
|
-
const tmpDist =
|
|
72548
|
+
const tmpSource = path9.join(tmpdir(), `lotics-source-${Date.now()}.tar.gz`);
|
|
72549
|
+
const tmpDist = path9.join(tmpdir(), `lotics-dist-${Date.now()}.tar.gz`);
|
|
72444
72550
|
try {
|
|
72445
|
-
|
|
72551
|
+
note("Packaging source...");
|
|
72446
72552
|
await runTar(
|
|
72447
72553
|
[
|
|
72448
72554
|
"-czf",
|
|
@@ -72456,10 +72562,10 @@ async function appDeploy(client, args) {
|
|
|
72456
72562
|
],
|
|
72457
72563
|
projectDir
|
|
72458
72564
|
);
|
|
72459
|
-
|
|
72565
|
+
note("Packaging dist...");
|
|
72460
72566
|
await runTar(["-czf", tmpDist, "-C", distDir, "."], projectDir);
|
|
72461
72567
|
const liveQueries = await readLiveQueries(client, meta3.app_id);
|
|
72462
|
-
|
|
72568
|
+
note("Uploading...");
|
|
72463
72569
|
try {
|
|
72464
72570
|
const result = await client.deployAppVersion({
|
|
72465
72571
|
queries: liveQueries,
|
|
@@ -72498,23 +72604,23 @@ async function appDeploy(client, args) {
|
|
|
72498
72604
|
current_version_id: result.version_id,
|
|
72499
72605
|
version_number: result.version_number
|
|
72500
72606
|
});
|
|
72501
|
-
|
|
72502
|
-
|
|
72607
|
+
note(`Deployed v${result.version_number} (${result.version_id})`);
|
|
72608
|
+
note(`Bundle size: ${(result.bundle_size_bytes / 1024).toFixed(1)} KB`);
|
|
72503
72609
|
try {
|
|
72504
72610
|
const drifted = staleWorkflowGlobals(projectDir, meta3.workflows ?? {});
|
|
72505
72611
|
for (const { alias, declaration } of drifted) {
|
|
72506
72612
|
if (await refreshWorkflowTypes(client, projectDir, meta3.app_id, alias, declaration)) {
|
|
72507
|
-
|
|
72613
|
+
note(`Refreshed workflow types for ${alias} \u2014 this deploy moved its declaration.`);
|
|
72508
72614
|
}
|
|
72509
72615
|
}
|
|
72510
72616
|
} catch (err2) {
|
|
72511
|
-
|
|
72617
|
+
warn(`(types not refreshed: ${err2.message})`);
|
|
72512
72618
|
}
|
|
72513
72619
|
let liveAfter;
|
|
72514
72620
|
try {
|
|
72515
72621
|
liveAfter = await client.getApp(meta3.app_id);
|
|
72516
72622
|
} catch (err2) {
|
|
72517
|
-
|
|
72623
|
+
warn(`(skipped post-deploy checks: ${err2.message})`);
|
|
72518
72624
|
}
|
|
72519
72625
|
if (liveAfter) {
|
|
72520
72626
|
warnIfUnbranded(liveAfter);
|
|
@@ -72555,7 +72661,7 @@ function warnIfUnbranded(app) {
|
|
|
72555
72661
|
if (!app.icon) missing.push("icon");
|
|
72556
72662
|
if (!app.theme?.color) missing.push("color");
|
|
72557
72663
|
if (missing.length === 0) return;
|
|
72558
|
-
|
|
72664
|
+
warn(
|
|
72559
72665
|
`
|
|
72560
72666
|
\u26A0 This app has no ${missing.join(" or ")} set \u2014 it shows a generic tile in the launcher.
|
|
72561
72667
|
Set it: lotics run update_app '{"app_id":"${app.id}","icon":"<lucide-name>","theme":{"color":"blue"}}'
|
|
@@ -72584,7 +72690,7 @@ async function readLiveQueries(client, appId) {
|
|
|
72584
72690
|
}
|
|
72585
72691
|
}
|
|
72586
72692
|
async function appCheck(client, args = {}) {
|
|
72587
|
-
const projectDir =
|
|
72693
|
+
const projectDir = path9.resolve(args.projectDir ?? process.cwd());
|
|
72588
72694
|
const meta3 = readAppMeta(projectDir);
|
|
72589
72695
|
const app = await client.getApp(meta3.app_id);
|
|
72590
72696
|
assertProjectIsCurrent(meta3, app);
|
|
@@ -72859,10 +72965,10 @@ function copyTree(from, to, opts, relative = "") {
|
|
|
72859
72965
|
const kept = [];
|
|
72860
72966
|
const created = [];
|
|
72861
72967
|
for (const entry of fs8.readdirSync(from, { withFileTypes: true })) {
|
|
72862
|
-
const src =
|
|
72863
|
-
const dest =
|
|
72864
|
-
const rel =
|
|
72865
|
-
if (opts.skip?.includes(rel.split(
|
|
72968
|
+
const src = path9.join(from, entry.name);
|
|
72969
|
+
const dest = path9.join(to, entry.name);
|
|
72970
|
+
const rel = path9.join(relative, entry.name);
|
|
72971
|
+
if (opts.skip?.includes(rel.split(path9.sep).join("/"))) continue;
|
|
72866
72972
|
if (entry.isDirectory()) {
|
|
72867
72973
|
fs8.mkdirSync(dest, { recursive: true });
|
|
72868
72974
|
const child = copyTree(src, dest, opts, rel);
|
|
@@ -73035,9 +73141,9 @@ function warnIfProjectFootguns(projectDir, sourceText) {
|
|
|
73035
73141
|
].join("\n")
|
|
73036
73142
|
);
|
|
73037
73143
|
}
|
|
73038
|
-
const configName = VITE_CONFIG_NAMES.find((name2) => fs8.existsSync(
|
|
73144
|
+
const configName = VITE_CONFIG_NAMES.find((name2) => fs8.existsSync(path9.join(projectDir, name2)));
|
|
73039
73145
|
if (configName !== void 0) {
|
|
73040
|
-
const config2 = fs8.readFileSync(
|
|
73146
|
+
const config2 = fs8.readFileSync(path9.join(projectDir, configName), "utf-8");
|
|
73041
73147
|
const defined = defineBlockKeys(config2);
|
|
73042
73148
|
const missing = ["global", "__DEV__"].filter((name2) => !defined.has(name2));
|
|
73043
73149
|
if (missing.length > 0) {
|
|
@@ -73133,7 +73239,7 @@ function warnIfUnboundAliases(app, called) {
|
|
|
73133
73239
|
console.error(lines.join("\n"));
|
|
73134
73240
|
}
|
|
73135
73241
|
async function appDev(client, args) {
|
|
73136
|
-
const projectDir =
|
|
73242
|
+
const projectDir = path9.resolve(args.projectDir ?? process.cwd());
|
|
73137
73243
|
const meta3 = readAppMeta(projectDir);
|
|
73138
73244
|
warnAboutDevLink(projectDir, "dev");
|
|
73139
73245
|
writeAppDts(projectDir, { workflows: meta3.workflows, queries: meta3.queries, agents: meta3.agents });
|
|
@@ -73267,7 +73373,7 @@ async function appAgentSet(client, args) {
|
|
|
73267
73373
|
}
|
|
73268
73374
|
if (!hasDeclaration) {
|
|
73269
73375
|
console.error(
|
|
73270
|
-
`No instructions at ${
|
|
73376
|
+
`No instructions at ${path9.relative(projectDir, file2)}, and nothing declared in package.json#lotics.agents.${args.alias} to push instead.
|
|
73271
73377
|
Run 'lotics app pull ${meta3.app_id}' to write ${AGENTS_DIR}/${args.alias}.md, then edit it.`
|
|
73272
73378
|
);
|
|
73273
73379
|
process.exit(1);
|
|
@@ -73276,7 +73382,7 @@ async function appAgentSet(client, args) {
|
|
|
73276
73382
|
const instructions = hasProse ? stripAgentHeader(fs8.readFileSync(file2, "utf-8")) : void 0;
|
|
73277
73383
|
if (instructions === "") {
|
|
73278
73384
|
console.error(
|
|
73279
|
-
`${
|
|
73385
|
+
`${path9.relative(projectDir, file2)} is empty after stripping the header \u2014 refusing to push an empty prompt.`
|
|
73280
73386
|
);
|
|
73281
73387
|
process.exit(1);
|
|
73282
73388
|
}
|
|
@@ -73343,7 +73449,7 @@ async function appWorkflowSet(client, args) {
|
|
|
73343
73449
|
const file2 = workflowFilePath(projectDir, args.alias);
|
|
73344
73450
|
if (!fs8.existsSync(file2)) {
|
|
73345
73451
|
console.error(
|
|
73346
|
-
`No workflow body at ${
|
|
73452
|
+
`No workflow body at ${path9.relative(projectDir, file2)}.
|
|
73347
73453
|
If "${args.alias}" is already bound: lotics app pull ${meta3.app_id} (writes the body)
|
|
73348
73454
|
If it is a NEW alias you declared: create that file yourself, then re-run this.`
|
|
73349
73455
|
);
|
|
@@ -73352,7 +73458,7 @@ async function appWorkflowSet(client, args) {
|
|
|
73352
73458
|
noteScope({ alias: args.alias });
|
|
73353
73459
|
const source = stripWorkflowHeader(fs8.readFileSync(file2, "utf-8"));
|
|
73354
73460
|
if (source.trim() === "") {
|
|
73355
|
-
console.error(`Workflow body ${
|
|
73461
|
+
console.error(`Workflow body ${path9.relative(projectDir, file2)} is empty after stripping the header.`);
|
|
73356
73462
|
process.exit(1);
|
|
73357
73463
|
}
|
|
73358
73464
|
const res = await client.setAppWorkflow(meta3.app_id, args.alias, {
|
|
@@ -73491,13 +73597,13 @@ async function appWorkflowCheck(args) {
|
|
|
73491
73597
|
const globalsPath = workflowGlobalsPath(projectDir, alias);
|
|
73492
73598
|
if (!fs8.existsSync(bodyPath)) {
|
|
73493
73599
|
console.error(
|
|
73494
|
-
`\u26A0 Skipped "${alias}" \u2014 no body at ${
|
|
73600
|
+
`\u26A0 Skipped "${alias}" \u2014 no body at ${path9.relative(projectDir, bodyPath)}. Run 'lotics app workflow pull' to write it.`
|
|
73495
73601
|
);
|
|
73496
73602
|
continue;
|
|
73497
73603
|
}
|
|
73498
73604
|
if (!fs8.existsSync(globalsPath)) {
|
|
73499
73605
|
console.error(
|
|
73500
|
-
`Cannot check "${alias}" \u2014 missing types at ${
|
|
73606
|
+
`Cannot check "${alias}" \u2014 missing types at ${path9.relative(projectDir, globalsPath)}. Run 'lotics app codegen' to fetch them (it refreshes types WITHOUT touching your body; a pull would overwrite it).`
|
|
73501
73607
|
);
|
|
73502
73608
|
process.exit(1);
|
|
73503
73609
|
}
|
|
@@ -73533,7 +73639,7 @@ async function appWorkflowCheck(args) {
|
|
|
73533
73639
|
function printWorkflowCheckResults(projectDir, results) {
|
|
73534
73640
|
let totalErrors = 0;
|
|
73535
73641
|
for (const r of results) {
|
|
73536
|
-
const rel =
|
|
73642
|
+
const rel = path9.relative(projectDir, r.bodyPath);
|
|
73537
73643
|
if (r.issues.length === 0) {
|
|
73538
73644
|
console.error(`\u2713 ${r.alias} (${rel}) \u2014 clean`);
|
|
73539
73645
|
continue;
|
|
@@ -73585,6 +73691,7 @@ function parseArgs(argv) {
|
|
|
73585
73691
|
remove: void 0,
|
|
73586
73692
|
includeHidden: false,
|
|
73587
73693
|
timezone: void 0,
|
|
73694
|
+
email: void 0,
|
|
73588
73695
|
message: void 0,
|
|
73589
73696
|
session: void 0,
|
|
73590
73697
|
port: void 0,
|
|
@@ -73669,6 +73776,9 @@ function parseArgs(argv) {
|
|
|
73669
73776
|
case "--name":
|
|
73670
73777
|
flags.name = argv[++i2];
|
|
73671
73778
|
break;
|
|
73779
|
+
case "--email":
|
|
73780
|
+
flags.email = argv[++i2];
|
|
73781
|
+
break;
|
|
73672
73782
|
case "--description":
|
|
73673
73783
|
flags.description = argv[++i2];
|
|
73674
73784
|
break;
|
|
@@ -73779,8 +73889,53 @@ function parseArgs(argv) {
|
|
|
73779
73889
|
|
|
73780
73890
|
// src/starter_commands.ts
|
|
73781
73891
|
import fs9 from "node:fs";
|
|
73782
|
-
import
|
|
73892
|
+
import path10 from "node:path";
|
|
73783
73893
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
73894
|
+
function printStarterRows(rows) {
|
|
73895
|
+
const width = Math.max(...rows.map((row) => row.id.length));
|
|
73896
|
+
for (const row of rows) {
|
|
73897
|
+
const tags = row.tags ?? [];
|
|
73898
|
+
console.log(
|
|
73899
|
+
` ${row.id.padEnd(width)} ${row.name}${tags.length > 0 ? ` [${tags.join(", ")}]` : ""}`
|
|
73900
|
+
);
|
|
73901
|
+
if (row.description) console.log(` ${" ".repeat(width)} ${row.description}`);
|
|
73902
|
+
}
|
|
73903
|
+
}
|
|
73904
|
+
function noteCopiedContent(templates, knowledgeDocs) {
|
|
73905
|
+
if (templates.length > 0) {
|
|
73906
|
+
note(
|
|
73907
|
+
`
|
|
73908
|
+
${templates.length} document template${templates.length === 1 ? "" : "s"}: ${templates.join(", ")}
|
|
73909
|
+
These carry the publisher's wording and details, not yours \u2014 decide which should
|
|
73910
|
+
become your own documents. Editing them: lotics docs document_templates`
|
|
73911
|
+
);
|
|
73912
|
+
}
|
|
73913
|
+
if (knowledgeDocs.length > 0) {
|
|
73914
|
+
note(
|
|
73915
|
+
`
|
|
73916
|
+
${knowledgeDocs.length} knowledge doc${knowledgeDocs.length === 1 ? "" : "s"}: ${knowledgeDocs.join(", ")}
|
|
73917
|
+
These describe how the publisher works, and the app's agents read them.
|
|
73918
|
+
Rewrite what differs: lotics docs knowledge_docs`
|
|
73919
|
+
);
|
|
73920
|
+
}
|
|
73921
|
+
}
|
|
73922
|
+
async function starterListPublic() {
|
|
73923
|
+
const starters = await fetchOfficialStarters();
|
|
73924
|
+
if (starters.length === 0) {
|
|
73925
|
+
console.error("No starters are published yet \u2014 build one with `lotics docs building_an_app`.");
|
|
73926
|
+
return;
|
|
73927
|
+
}
|
|
73928
|
+
console.error(`${starters.length} starter${starters.length === 1 ? "" : "s"} published by Lotics:
|
|
73929
|
+
`);
|
|
73930
|
+
printStarterRows(starters);
|
|
73931
|
+
console.error(
|
|
73932
|
+
`
|
|
73933
|
+
lotics start <starter_id> --email you@company.com Copy one \u2014 creates your account too
|
|
73934
|
+
|
|
73935
|
+
This machine has no Lotics account yet, so this is the published shelf.
|
|
73936
|
+
Signed in, the same command also lists what your own organization published.`
|
|
73937
|
+
);
|
|
73938
|
+
}
|
|
73784
73939
|
async function starterList(client) {
|
|
73785
73940
|
const starters = await client.listStarters();
|
|
73786
73941
|
if (starters.length === 0) {
|
|
@@ -73789,19 +73944,19 @@ async function starterList(client) {
|
|
|
73789
73944
|
);
|
|
73790
73945
|
return;
|
|
73791
73946
|
}
|
|
73792
|
-
const width = Math.max(...starters.map((s) => s.id.length));
|
|
73793
73947
|
console.error(`${starters.length} starter${starters.length === 1 ? "" : "s"}:
|
|
73794
73948
|
`);
|
|
73795
|
-
|
|
73796
|
-
|
|
73797
|
-
s.
|
|
73798
|
-
s.
|
|
73799
|
-
|
|
73800
|
-
|
|
73801
|
-
|
|
73802
|
-
|
|
73803
|
-
|
|
73804
|
-
|
|
73949
|
+
printStarterRows(
|
|
73950
|
+
starters.map((s) => ({
|
|
73951
|
+
id: s.id,
|
|
73952
|
+
name: s.name,
|
|
73953
|
+
description: s.description,
|
|
73954
|
+
tags: [
|
|
73955
|
+
s.is_official ? "official" : null,
|
|
73956
|
+
s.owned_by_caller === true ? "yours" : null
|
|
73957
|
+
].filter((t) => t !== null)
|
|
73958
|
+
}))
|
|
73959
|
+
);
|
|
73805
73960
|
console.error(`
|
|
73806
73961
|
lotics starter init <starter_id> Copy one into this workspace`);
|
|
73807
73962
|
}
|
|
@@ -73814,6 +73969,9 @@ async function starterShow(client, starter_id) {
|
|
|
73814
73969
|
version ${starter.latest_version}
|
|
73815
73970
|
trust ${starter.is_official ? "official \u2014 reviewed by Lotics" : starter.owned_by_caller === true ? "your organization's own" : "not copyable from this organization"}`
|
|
73816
73971
|
);
|
|
73972
|
+
if (starter.icon !== void 0) {
|
|
73973
|
+
console.log(`icon ${starter.icon ?? "none \u2014 copies show a generic tile"}`);
|
|
73974
|
+
}
|
|
73817
73975
|
if (starter.retired_at !== null) {
|
|
73818
73976
|
console.log(`retired ${starter.retired_at} \u2014 can no longer be copied`);
|
|
73819
73977
|
}
|
|
@@ -73821,7 +73979,7 @@ trust ${starter.is_official ? "official \u2014 reviewed by Lotics" : starter
|
|
|
73821
73979
|
function reportKnowledgeWarnings(warnings) {
|
|
73822
73980
|
const missing = warnings.missing_expected_docs;
|
|
73823
73981
|
if (missing.length === 0) return;
|
|
73824
|
-
|
|
73982
|
+
warn(
|
|
73825
73983
|
`
|
|
73826
73984
|
\u26A0 ${missing.length} knowledge doc(s) this starter's agents expect are missing here:
|
|
73827
73985
|
` + missing.map((name2) => ` \u2022 ${name2}`).join("\n") + `
|
|
@@ -73831,40 +73989,55 @@ function reportKnowledgeWarnings(warnings) {
|
|
|
73831
73989
|
}
|
|
73832
73990
|
async function starterInit(client, args) {
|
|
73833
73991
|
const starter = await client.getPackage(args.starter_id);
|
|
73834
|
-
|
|
73992
|
+
note(
|
|
73835
73993
|
`Copying ${starter.name}${starter.is_official ? " (official)" : ""} into this workspace\u2026`
|
|
73836
73994
|
);
|
|
73837
73995
|
const result = await client.instantiateStarter(args.starter_id, {
|
|
73838
73996
|
...args.noSampleData === true ? { no_sample_data: true } : {},
|
|
73839
73997
|
...args.adopt === true ? { adopt: true } : {}
|
|
73840
73998
|
});
|
|
73841
|
-
const
|
|
73842
|
-
const
|
|
73843
|
-
const templates = Object.keys(result.binding.templates ?? {}).
|
|
73999
|
+
const tables = Object.keys(result.binding.entities ?? {}).sort();
|
|
74000
|
+
const knowledgeDocs = Object.keys(result.binding.knowledge ?? {}).sort();
|
|
74001
|
+
const templates = Object.keys(result.binding.templates ?? {}).sort();
|
|
73844
74002
|
const records = Object.values(result.sample_record_ids).reduce((n, ids) => n + ids.length, 0);
|
|
73845
|
-
|
|
73846
|
-
|
|
74003
|
+
const created = {
|
|
74004
|
+
tables,
|
|
74005
|
+
templates,
|
|
74006
|
+
knowledge_docs: knowledgeDocs,
|
|
74007
|
+
sample_records: records
|
|
74008
|
+
};
|
|
74009
|
+
note(
|
|
74010
|
+
` Created ${tables.length} table${tables.length === 1 ? "" : "s"}, ${templates.length} template${templates.length === 1 ? "" : "s"}, ${knowledgeDocs.length} knowledge doc${knowledgeDocs.length === 1 ? "" : "s"}, ${records} sample record${records === 1 ? "" : "s"}.`
|
|
73847
74011
|
);
|
|
73848
74012
|
reportKnowledgeWarnings(result.knowledge_warnings);
|
|
73849
74013
|
if (result.app_id === null || result.bundle_url === null) {
|
|
73850
|
-
|
|
73851
|
-
Done
|
|
73852
|
-
|
|
74014
|
+
note(`
|
|
74015
|
+
Done \u2014 these are yours now, with no link back to the starter.`);
|
|
74016
|
+
noteCopiedContent(templates, knowledgeDocs);
|
|
74017
|
+
return {
|
|
74018
|
+
starter_id: args.starter_id,
|
|
74019
|
+
starter_name: starter.name,
|
|
74020
|
+
version: result.version,
|
|
74021
|
+
app_id: null,
|
|
74022
|
+
project_dir: null,
|
|
74023
|
+
created,
|
|
74024
|
+
signin_url: null
|
|
74025
|
+
};
|
|
73853
74026
|
}
|
|
73854
|
-
const targetPath =
|
|
74027
|
+
const targetPath = path10.resolve(args.targetPath ?? appDirName(starter.name));
|
|
73855
74028
|
if (fs9.existsSync(targetPath) && fs9.readdirSync(targetPath).length > 0) {
|
|
73856
74029
|
throw new Error(
|
|
73857
74030
|
`Target directory ${targetPath} is not empty. The app (${result.app_id}) was created \u2014 pass an empty path and re-run, or finish it with "lotics app pull ${result.app_id}".`
|
|
73858
74031
|
);
|
|
73859
74032
|
}
|
|
73860
74033
|
fs9.mkdirSync(targetPath, { recursive: true });
|
|
73861
|
-
|
|
73862
|
-
const bundleFile =
|
|
73863
|
-
const wrapperDir = fs9.mkdtempSync(
|
|
74034
|
+
note(`Downloading source\u2026`);
|
|
74035
|
+
const bundleFile = path10.join(tmpdir2(), `lotics-starter-${args.starter_id}-${process.pid}.tar.gz`);
|
|
74036
|
+
const wrapperDir = fs9.mkdtempSync(path10.join(tmpdir2(), `lotics-starter-`));
|
|
73864
74037
|
try {
|
|
73865
74038
|
await downloadToFile(result.bundle_url, bundleFile);
|
|
73866
74039
|
await runTar(["-xzf", bundleFile, "-C", wrapperDir], wrapperDir);
|
|
73867
|
-
const sourceArchive =
|
|
74040
|
+
const sourceArchive = path10.join(wrapperDir, "source.tar.gz");
|
|
73868
74041
|
if (!fs9.existsSync(sourceArchive)) {
|
|
73869
74042
|
throw new Error(
|
|
73870
74043
|
`Starter bundle carried no source.tar.gz \u2014 the app (${result.app_id}) exists but has no code. Report this to the starter's publisher.`
|
|
@@ -73876,7 +74049,7 @@ Done. The documents and knowledge are yours to edit \u2014 nothing links back.`)
|
|
|
73876
74049
|
fs9.rmSync(wrapperDir, { recursive: true, force: true });
|
|
73877
74050
|
}
|
|
73878
74051
|
for (const dir of ["knowledge", "fixtures"]) {
|
|
73879
|
-
fs9.rmSync(
|
|
74052
|
+
fs9.rmSync(path10.join(targetPath, dir), { recursive: true, force: true });
|
|
73880
74053
|
}
|
|
73881
74054
|
const app = await client.getApp(result.app_id);
|
|
73882
74055
|
const kept = [];
|
|
@@ -73886,15 +74059,14 @@ Done. The documents and knowledge are yours to edit \u2014 nothing links back.`)
|
|
|
73886
74059
|
kept
|
|
73887
74060
|
});
|
|
73888
74061
|
if (starter.owned_by_caller !== true) {
|
|
73889
|
-
|
|
74062
|
+
warn(
|
|
73890
74063
|
`
|
|
73891
74064
|
Building ${starter.name} \u2014 this runs its build on your machine (its package scripts
|
|
73892
74065
|
and vite config are the publisher's code, executed as you).${starter.is_official ? " Lotics reviewed this starter." : ""}`
|
|
73893
74066
|
);
|
|
73894
74067
|
} else {
|
|
73895
|
-
|
|
74068
|
+
note(`Building and deploying\u2026`);
|
|
73896
74069
|
}
|
|
73897
|
-
await runNpm(["run", "build"], targetPath);
|
|
73898
74070
|
await appDeploy(client, {
|
|
73899
74071
|
projectDir: targetPath,
|
|
73900
74072
|
message: `Copied from starter ${starter.name}`
|
|
@@ -73907,14 +74079,14 @@ Building ${starter.name} \u2014 this runs its build on your machine (its package
|
|
|
73907
74079
|
});
|
|
73908
74080
|
signInUrl = link.url ?? null;
|
|
73909
74081
|
} catch (error52) {
|
|
73910
|
-
|
|
74082
|
+
warn(
|
|
73911
74083
|
`
|
|
73912
74084
|
(no sign-in link: ${error52 instanceof Error ? error52.message : String(error52)})
|
|
73913
74085
|
The copy is complete either way \u2014 open it with "lotics auth web".`
|
|
73914
74086
|
);
|
|
73915
74087
|
signInUrl = null;
|
|
73916
74088
|
}
|
|
73917
|
-
|
|
74089
|
+
note(
|
|
73918
74090
|
`
|
|
73919
74091
|
Done \u2014 ${starter.name} is live and yours.
|
|
73920
74092
|
App: ${result.app_id}
|
|
@@ -73922,42 +74094,55 @@ Done \u2014 ${starter.name} is live and yours.
|
|
|
73922
74094
|
|
|
73923
74095
|
Edit anything: the tables, the app source, the templates, the docs. There is no
|
|
73924
74096
|
link back to the starter and nothing to upgrade \u2014 this is your app now.
|
|
73925
|
-
Ship a change: cd ${
|
|
74097
|
+
Ship a change: cd ${path10.relative(process.cwd(), targetPath) || "."} && lotics app deploy -m "<what changed>"
|
|
74098
|
+
|
|
74099
|
+
How to change it: lotics docs building_an_app (then \`lotics docs\` for the rest \u2014
|
|
74100
|
+
the SDK and UI references are installed in this project, so they match its versions)`
|
|
73926
74101
|
);
|
|
73927
74102
|
if (records > 0) {
|
|
73928
|
-
|
|
74103
|
+
note(
|
|
73929
74104
|
`
|
|
73930
74105
|
${records} sample record${records === 1 ? "" : "s"} came with it. They are ordinary records \u2014
|
|
73931
74106
|
delete them whenever you like, or re-run with --no-sample-data next time.`
|
|
73932
74107
|
);
|
|
73933
74108
|
}
|
|
74109
|
+
noteCopiedContent(templates, knowledgeDocs);
|
|
73934
74110
|
if (signInUrl !== null) {
|
|
73935
|
-
|
|
74111
|
+
note(
|
|
73936
74112
|
`
|
|
73937
74113
|
Open it \u2014 one-time sign-in link, expires in 15 minutes:
|
|
73938
74114
|
${signInUrl}`
|
|
73939
74115
|
);
|
|
73940
74116
|
}
|
|
74117
|
+
return {
|
|
74118
|
+
starter_id: args.starter_id,
|
|
74119
|
+
starter_name: starter.name,
|
|
74120
|
+
version: result.version,
|
|
74121
|
+
app_id: result.app_id,
|
|
74122
|
+
project_dir: targetPath,
|
|
74123
|
+
created,
|
|
74124
|
+
signin_url: signInUrl
|
|
74125
|
+
};
|
|
73941
74126
|
}
|
|
73942
74127
|
async function starterFixturesCapture(client, args) {
|
|
73943
|
-
const projectDir =
|
|
74128
|
+
const projectDir = path10.resolve(args.projectDir ?? process.cwd());
|
|
73944
74129
|
const meta3 = readAppMeta(projectDir);
|
|
73945
74130
|
const result = await client.captureStarterFixtures(meta3.app_id, {
|
|
73946
74131
|
entities: args.entities,
|
|
73947
74132
|
...args.limit !== void 0 ? { limit: args.limit } : {}
|
|
73948
74133
|
});
|
|
73949
|
-
const fixturesDir =
|
|
74134
|
+
const fixturesDir = path10.join(projectDir, "fixtures");
|
|
73950
74135
|
fs9.mkdirSync(fixturesDir, { recursive: true });
|
|
73951
74136
|
let totalRows = 0;
|
|
73952
74137
|
for (const entry of result.captured) {
|
|
73953
|
-
const file2 =
|
|
74138
|
+
const file2 = path10.join(projectDir, entry.content_ref);
|
|
73954
74139
|
fs9.writeFileSync(file2, `${JSON.stringify(entry.file, null, 2)}
|
|
73955
74140
|
`, "utf-8");
|
|
73956
74141
|
totalRows += entry.file.rows.length;
|
|
73957
74142
|
console.error(
|
|
73958
74143
|
` ${entry.content_ref} \u2014 ${entry.file.rows.length} row${entry.file.rows.length === 1 ? "" : "s"}`
|
|
73959
74144
|
);
|
|
73960
|
-
for (const
|
|
74145
|
+
for (const line of entry.notes) console.error(` \u26A0 ${line}`);
|
|
73961
74146
|
}
|
|
73962
74147
|
if (result.captured.length === 0) {
|
|
73963
74148
|
console.error(
|
|
@@ -74041,7 +74226,7 @@ import fs11 from "node:fs";
|
|
|
74041
74226
|
|
|
74042
74227
|
// src/file_command_io.ts
|
|
74043
74228
|
import fs10 from "node:fs";
|
|
74044
|
-
import
|
|
74229
|
+
import path11 from "node:path";
|
|
74045
74230
|
var CliError = class extends Error {
|
|
74046
74231
|
constructor(message2) {
|
|
74047
74232
|
super(message2);
|
|
@@ -74064,8 +74249,8 @@ function rejectExtraArgs(rest2, arity, usage) {
|
|
|
74064
74249
|
fail2(`${usage} takes ${arity} argument${arity === 1 ? "" : "s"} after <file>, got ${rest2.length}. Unused: ${rest2.slice(arity).join(" ")}`);
|
|
74065
74250
|
}
|
|
74066
74251
|
function writeFileAtomic(filePath, bytes) {
|
|
74067
|
-
const dir =
|
|
74068
|
-
const tmp =
|
|
74252
|
+
const dir = path11.dirname(path11.resolve(filePath));
|
|
74253
|
+
const tmp = path11.join(dir, `.${path11.basename(filePath)}.${process.pid}.${Date.now()}.tmp`);
|
|
74069
74254
|
fs10.writeFileSync(tmp, bytes);
|
|
74070
74255
|
try {
|
|
74071
74256
|
fs10.renameSync(tmp, filePath);
|
|
@@ -76868,16 +77053,16 @@ var MatcherView = class {
|
|
|
76868
77053
|
* @returns {string|undefined}
|
|
76869
77054
|
*/
|
|
76870
77055
|
getCurrentTag() {
|
|
76871
|
-
const
|
|
76872
|
-
return
|
|
77056
|
+
const path13 = this._matcher.path;
|
|
77057
|
+
return path13.length > 0 ? path13[path13.length - 1].tag : void 0;
|
|
76873
77058
|
}
|
|
76874
77059
|
/**
|
|
76875
77060
|
* Get current namespace.
|
|
76876
77061
|
* @returns {string|undefined}
|
|
76877
77062
|
*/
|
|
76878
77063
|
getCurrentNamespace() {
|
|
76879
|
-
const
|
|
76880
|
-
return
|
|
77064
|
+
const path13 = this._matcher.path;
|
|
77065
|
+
return path13.length > 0 ? path13[path13.length - 1].namespace : void 0;
|
|
76881
77066
|
}
|
|
76882
77067
|
/**
|
|
76883
77068
|
* Get current node's attribute value.
|
|
@@ -76885,9 +77070,9 @@ var MatcherView = class {
|
|
|
76885
77070
|
* @returns {*}
|
|
76886
77071
|
*/
|
|
76887
77072
|
getAttrValue(attrName) {
|
|
76888
|
-
const
|
|
76889
|
-
if (
|
|
76890
|
-
return
|
|
77073
|
+
const path13 = this._matcher.path;
|
|
77074
|
+
if (path13.length === 0) return void 0;
|
|
77075
|
+
return path13[path13.length - 1].values?.[attrName];
|
|
76891
77076
|
}
|
|
76892
77077
|
/**
|
|
76893
77078
|
* Check if current node has an attribute.
|
|
@@ -76895,9 +77080,9 @@ var MatcherView = class {
|
|
|
76895
77080
|
* @returns {boolean}
|
|
76896
77081
|
*/
|
|
76897
77082
|
hasAttr(attrName) {
|
|
76898
|
-
const
|
|
76899
|
-
if (
|
|
76900
|
-
const current =
|
|
77083
|
+
const path13 = this._matcher.path;
|
|
77084
|
+
if (path13.length === 0) return false;
|
|
77085
|
+
const current = path13[path13.length - 1];
|
|
76901
77086
|
return current.values !== void 0 && attrName in current.values;
|
|
76902
77087
|
}
|
|
76903
77088
|
/**
|
|
@@ -76923,18 +77108,18 @@ var MatcherView = class {
|
|
|
76923
77108
|
* @returns {number}
|
|
76924
77109
|
*/
|
|
76925
77110
|
getPosition() {
|
|
76926
|
-
const
|
|
76927
|
-
if (
|
|
76928
|
-
return
|
|
77111
|
+
const path13 = this._matcher.path;
|
|
77112
|
+
if (path13.length === 0) return -1;
|
|
77113
|
+
return path13[path13.length - 1].position ?? 0;
|
|
76929
77114
|
}
|
|
76930
77115
|
/**
|
|
76931
77116
|
* Get current node's repeat counter (occurrence count of this tag name).
|
|
76932
77117
|
* @returns {number}
|
|
76933
77118
|
*/
|
|
76934
77119
|
getCounter() {
|
|
76935
|
-
const
|
|
76936
|
-
if (
|
|
76937
|
-
return
|
|
77120
|
+
const path13 = this._matcher.path;
|
|
77121
|
+
if (path13.length === 0) return -1;
|
|
77122
|
+
return path13[path13.length - 1].counter ?? 0;
|
|
76938
77123
|
}
|
|
76939
77124
|
/**
|
|
76940
77125
|
* Get current node's sibling index (alias for getPosition).
|
|
@@ -82592,10 +82777,10 @@ function resolveRelativePath(basePath, relativePath) {
|
|
|
82592
82777
|
}
|
|
82593
82778
|
return resolved.join("/");
|
|
82594
82779
|
}
|
|
82595
|
-
function findZipEntry(zipEntries,
|
|
82596
|
-
if (zipEntries[
|
|
82597
|
-
if (zipEntries[`xl/${
|
|
82598
|
-
const noSlash =
|
|
82780
|
+
function findZipEntry(zipEntries, path13) {
|
|
82781
|
+
if (zipEntries[path13]) return zipEntries[path13];
|
|
82782
|
+
if (zipEntries[`xl/${path13}`]) return zipEntries[`xl/${path13}`];
|
|
82783
|
+
const noSlash = path13.replace(/^\//, "");
|
|
82599
82784
|
if (zipEntries[noSlash]) return zipEntries[noSlash];
|
|
82600
82785
|
return void 0;
|
|
82601
82786
|
}
|
|
@@ -84496,9 +84681,9 @@ function parseExcelFromZip(zip, options) {
|
|
|
84496
84681
|
}
|
|
84497
84682
|
return result;
|
|
84498
84683
|
}
|
|
84499
|
-
function findEntry(zip,
|
|
84500
|
-
if (zip[
|
|
84501
|
-
const lower2 =
|
|
84684
|
+
function findEntry(zip, path13) {
|
|
84685
|
+
if (zip[path13]) return zip[path13];
|
|
84686
|
+
const lower2 = path13.toLowerCase();
|
|
84502
84687
|
for (const key of Object.keys(zip)) {
|
|
84503
84688
|
if (key.toLowerCase() === lower2) return zip[key];
|
|
84504
84689
|
}
|
|
@@ -85135,12 +85320,12 @@ function extractPivotRoundTripInfo(originalZip) {
|
|
|
85135
85320
|
if (paths.length > 0) pivotTablesBySheetIndex.set(i2, paths);
|
|
85136
85321
|
}
|
|
85137
85322
|
const pivotXmlPaths = [];
|
|
85138
|
-
for (const
|
|
85139
|
-
if (
|
|
85140
|
-
pivotXmlPaths.push(
|
|
85323
|
+
for (const path13 of Object.keys(originalZip)) {
|
|
85324
|
+
if (path13.startsWith("xl/pivotTables/") && path13.endsWith(".xml")) {
|
|
85325
|
+
pivotXmlPaths.push(path13);
|
|
85141
85326
|
}
|
|
85142
|
-
if (
|
|
85143
|
-
pivotXmlPaths.push(
|
|
85327
|
+
if (path13.startsWith("xl/pivotCache/") && path13.endsWith(".xml")) {
|
|
85328
|
+
pivotXmlPaths.push(path13);
|
|
85144
85329
|
}
|
|
85145
85330
|
}
|
|
85146
85331
|
return { cachesByWorkbook, pivotTablesBySheetIndex, pivotXmlPaths };
|
|
@@ -85148,15 +85333,15 @@ function extractPivotRoundTripInfo(originalZip) {
|
|
|
85148
85333
|
function decode3(bytes) {
|
|
85149
85334
|
return new TextDecoder().decode(bytes);
|
|
85150
85335
|
}
|
|
85151
|
-
function pivotContentTypeFor(
|
|
85152
|
-
if (
|
|
85153
|
-
return `<Override PartName="/${
|
|
85336
|
+
function pivotContentTypeFor(path13) {
|
|
85337
|
+
if (path13.startsWith("xl/pivotTables/") && path13.endsWith(".xml")) {
|
|
85338
|
+
return `<Override PartName="/${path13}" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml"/>`;
|
|
85154
85339
|
}
|
|
85155
|
-
if (
|
|
85156
|
-
return `<Override PartName="/${
|
|
85340
|
+
if (path13.includes("/pivotCacheDefinition") && path13.endsWith(".xml")) {
|
|
85341
|
+
return `<Override PartName="/${path13}" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml"/>`;
|
|
85157
85342
|
}
|
|
85158
|
-
if (
|
|
85159
|
-
return `<Override PartName="/${
|
|
85343
|
+
if (path13.includes("/pivotCacheRecords") && path13.endsWith(".xml")) {
|
|
85344
|
+
return `<Override PartName="/${path13}" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml"/>`;
|
|
85160
85345
|
}
|
|
85161
85346
|
return void 0;
|
|
85162
85347
|
}
|
|
@@ -85229,16 +85414,16 @@ function exportWorkbook(workbook, originalZip) {
|
|
|
85229
85414
|
regeneratedPaths.add(`xl/worksheets/sheet${i2 + 1}.xml`);
|
|
85230
85415
|
regeneratedPaths.add(`xl/worksheets/_rels/sheet${i2 + 1}.xml.rels`);
|
|
85231
85416
|
}
|
|
85232
|
-
for (const
|
|
85233
|
-
if (
|
|
85234
|
-
regeneratedPaths.add(
|
|
85417
|
+
for (const path13 of Object.keys(originalZip)) {
|
|
85418
|
+
if (path13.startsWith("xl/drawings/") || path13.startsWith("xl/charts/") || path13.startsWith("xl/tables/") || path13.startsWith("xl/media/")) {
|
|
85419
|
+
regeneratedPaths.add(path13);
|
|
85235
85420
|
}
|
|
85236
85421
|
}
|
|
85237
|
-
for (const [
|
|
85238
|
-
if (regeneratedPaths.has(
|
|
85239
|
-
const ext =
|
|
85422
|
+
for (const [path13, data2] of Object.entries(originalZip)) {
|
|
85423
|
+
if (regeneratedPaths.has(path13)) continue;
|
|
85424
|
+
const ext = path13.slice(path13.lastIndexOf(".") + 1).toLowerCase();
|
|
85240
85425
|
if (!DECLARED_EXTENSIONS.includes(ext)) continue;
|
|
85241
|
-
entries2[
|
|
85426
|
+
entries2[path13] = data2;
|
|
85242
85427
|
}
|
|
85243
85428
|
}
|
|
85244
85429
|
const sharedStrings = buildSharedStrings(workbook);
|
|
@@ -85254,8 +85439,8 @@ function exportWorkbook(workbook, originalZip) {
|
|
|
85254
85439
|
buildWorkbookRels(workbook, pivotInfo)
|
|
85255
85440
|
);
|
|
85256
85441
|
const extraContentTypes = [];
|
|
85257
|
-
for (const
|
|
85258
|
-
const ct = pivotContentTypeFor(
|
|
85442
|
+
for (const path13 of pivotInfo.pivotXmlPaths) {
|
|
85443
|
+
const ct = pivotContentTypeFor(path13);
|
|
85259
85444
|
if (ct) extraContentTypes.push(ct);
|
|
85260
85445
|
}
|
|
85261
85446
|
let globalChartIndex = 1;
|
|
@@ -94441,14 +94626,14 @@ var DependencyGraph = class {
|
|
|
94441
94626
|
stack.push({ cell: p, path: [cell, p] });
|
|
94442
94627
|
}
|
|
94443
94628
|
while (stack.length > 0) {
|
|
94444
|
-
const { cell: current, path:
|
|
94445
|
-
if (current === cell || originCoarse.has(current)) return
|
|
94629
|
+
const { cell: current, path: path13 } = stack.pop();
|
|
94630
|
+
if (current === cell || originCoarse.has(current)) return path13;
|
|
94446
94631
|
if (visited.has(current)) continue;
|
|
94447
94632
|
visited.add(current);
|
|
94448
94633
|
const nextPrec = this.precedents.get(current);
|
|
94449
94634
|
if (!nextPrec) continue;
|
|
94450
94635
|
for (const p of nextPrec) {
|
|
94451
|
-
stack.push({ cell: p, path: [...
|
|
94636
|
+
stack.push({ cell: p, path: [...path13, p] });
|
|
94452
94637
|
}
|
|
94453
94638
|
}
|
|
94454
94639
|
return null;
|
|
@@ -98510,15 +98695,15 @@ function finalizeParagraph(ctx, parts, startCp, markCp, isCellMark, numbering) {
|
|
|
98510
98695
|
};
|
|
98511
98696
|
}
|
|
98512
98697
|
function readPictureAt(ctx, raw, cp) {
|
|
98513
|
-
const
|
|
98698
|
+
const note2 = (detail) => {
|
|
98514
98699
|
ctx.diagnostics.push({ kind: "image", location: { cp }, detail });
|
|
98515
98700
|
return null;
|
|
98516
98701
|
};
|
|
98517
|
-
if (raw.picLocation === void 0) return
|
|
98518
|
-
if (!ctx.data) return
|
|
98702
|
+
if (raw.picLocation === void 0) return note2("Picture anchor carries no Data-stream location; dropped");
|
|
98703
|
+
if (!ctx.data) return note2("Picture anchor found but the document has no Data stream; dropped");
|
|
98519
98704
|
const picture = readInlinePicture(ctx.data, raw.picLocation);
|
|
98520
98705
|
if (!picture) {
|
|
98521
|
-
return
|
|
98706
|
+
return note2(`Picture at Data+${raw.picLocation} is not a readable inline image; dropped`);
|
|
98522
98707
|
}
|
|
98523
98708
|
return picture;
|
|
98524
98709
|
}
|
|
@@ -101208,9 +101393,9 @@ function buildFootnotesXml(footnotes, ctx) {
|
|
|
101208
101393
|
boilerplateNote("separator", "-1", "w:separator"),
|
|
101209
101394
|
boilerplateNote("continuationSeparator", "0", "w:continuationSeparator")
|
|
101210
101395
|
];
|
|
101211
|
-
for (const
|
|
101212
|
-
const content =
|
|
101213
|
-
notes.push({ "w:footnote": content, ":@": { "@_w:id": String(
|
|
101396
|
+
for (const note2 of footnotes) {
|
|
101397
|
+
const content = note2.content.length > 0 ? note2.content.map((b) => buildBlockElement(b, ctx)) : [{ "w:p": [] }];
|
|
101398
|
+
notes.push({ "w:footnote": content, ":@": { "@_w:id": String(note2.index) } });
|
|
101214
101399
|
}
|
|
101215
101400
|
const root = { "w:footnotes": notes, ":@": { "@_xmlns:w": W_NS3 } };
|
|
101216
101401
|
return buildXml([root]);
|
|
@@ -101247,7 +101432,7 @@ function collectFonts(fonts, acc) {
|
|
|
101247
101432
|
function walkModel(model) {
|
|
101248
101433
|
const acc = { referencedStyleIstds: /* @__PURE__ */ new Set(), fontNames: /* @__PURE__ */ new Set() };
|
|
101249
101434
|
walkBlocks(model.body, acc);
|
|
101250
|
-
for (const
|
|
101435
|
+
for (const note2 of model.footnotes) walkBlocks(note2.content, acc);
|
|
101251
101436
|
for (const style of model.styles) {
|
|
101252
101437
|
if (style.chp) collectFonts(style.chp.fonts, acc);
|
|
101253
101438
|
}
|
|
@@ -101402,8 +101587,8 @@ async function docModelToDocx(model) {
|
|
|
101402
101587
|
// ../ooxml/src/opc.ts
|
|
101403
101588
|
var import_jszip = __toESM(require_lib4(), 1);
|
|
101404
101589
|
function dropFolderEntries(zip) {
|
|
101405
|
-
for (const [
|
|
101406
|
-
if (entry.dir) delete zip.files[
|
|
101590
|
+
for (const [path13, entry] of Object.entries(zip.files)) {
|
|
101591
|
+
if (entry.dir) delete zip.files[path13];
|
|
101407
101592
|
}
|
|
101408
101593
|
}
|
|
101409
101594
|
|
|
@@ -101658,11 +101843,11 @@ async function parseDocx(buffer) {
|
|
|
101658
101843
|
const zip = await import_jszip3.default.loadAsync(buffer);
|
|
101659
101844
|
const parts = /* @__PURE__ */ new Map();
|
|
101660
101845
|
const filePromises = [];
|
|
101661
|
-
zip.forEach((
|
|
101846
|
+
zip.forEach((path13, file2) => {
|
|
101662
101847
|
if (file2.dir) return;
|
|
101663
101848
|
filePromises.push(
|
|
101664
101849
|
file2.async("uint8array").then((bytes) => {
|
|
101665
|
-
parts.set(
|
|
101850
|
+
parts.set(path13, bytes);
|
|
101666
101851
|
})
|
|
101667
101852
|
);
|
|
101668
101853
|
});
|
|
@@ -101894,9 +102079,9 @@ var DEFAULT_PARTS = [
|
|
|
101894
102079
|
["word/theme/theme1.xml", () => encoder.encode(THEME_XML)]
|
|
101895
102080
|
];
|
|
101896
102081
|
function fillDefaultParts(parts) {
|
|
101897
|
-
for (const [
|
|
101898
|
-
if (!parts.has(
|
|
101899
|
-
parts.set(
|
|
102082
|
+
for (const [path13, makeBytes] of DEFAULT_PARTS) {
|
|
102083
|
+
if (!parts.has(path13)) {
|
|
102084
|
+
parts.set(path13, makeBytes());
|
|
101900
102085
|
}
|
|
101901
102086
|
}
|
|
101902
102087
|
return parts;
|
|
@@ -101906,9 +102091,9 @@ function fillDefaultParts(parts) {
|
|
|
101906
102091
|
async function serializeDocx(doc) {
|
|
101907
102092
|
const zip = new import_jszip4.default();
|
|
101908
102093
|
const parts = fillDefaultParts(new Map(doc.parts));
|
|
101909
|
-
for (const [
|
|
101910
|
-
if (
|
|
101911
|
-
zip.file(
|
|
102094
|
+
for (const [path13, bytes] of parts) {
|
|
102095
|
+
if (path13 === "word/document.xml") continue;
|
|
102096
|
+
zip.file(path13, bytes);
|
|
101912
102097
|
}
|
|
101913
102098
|
const documentXml = serializeDocumentXml(doc);
|
|
101914
102099
|
zip.file("word/document.xml", documentXml);
|
|
@@ -102697,12 +102882,12 @@ async function runKnowledgeCommand(client, subcommand, toolArgs, flags, restArgs
|
|
|
102697
102882
|
// src/preview.ts
|
|
102698
102883
|
import { spawn as spawn3 } from "node:child_process";
|
|
102699
102884
|
import { createServer } from "node:http";
|
|
102700
|
-
import { readFileSync
|
|
102885
|
+
import { readFileSync, writeFileSync, existsSync as existsSync2, mkdtempSync, rmSync, readdirSync } from "node:fs";
|
|
102701
102886
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
102702
102887
|
import { join as join2, dirname, resolve, extname, basename } from "node:path";
|
|
102703
|
-
import { fileURLToPath as
|
|
102888
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
102704
102889
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
102705
|
-
var HERE = dirname(
|
|
102890
|
+
var HERE = dirname(fileURLToPath2(import.meta.url));
|
|
102706
102891
|
function fail3(msg) {
|
|
102707
102892
|
console.error(msg);
|
|
102708
102893
|
process.exit(1);
|
|
@@ -102783,8 +102968,8 @@ async function runPreviewCommand(filePath, flags) {
|
|
|
102783
102968
|
"No Chrome/Chromium found. Set CHROME_PATH to a Chrome binary, or install one:\n npx playwright install chromium (then it's auto-detected)\n or install Google Chrome / Chromium via your package manager."
|
|
102784
102969
|
);
|
|
102785
102970
|
}
|
|
102786
|
-
const b64 =
|
|
102787
|
-
const bundle =
|
|
102971
|
+
const b64 = readFileSync(abs2).toString("base64");
|
|
102972
|
+
const bundle = readFileSync(bundlePath, "utf8");
|
|
102788
102973
|
const html = `<!doctype html><html><head><meta charset="utf-8"><style>body{margin:0;background:#fff;font-family:sans-serif}#root{padding:20px;max-width:1240px;margin:0 auto}</style></head><body><div id="root"></div><script>window.__LOTICS_RENDER=${JSON.stringify({ type, b64 })}</script><script src="/render_page.js"></script></body></html>`;
|
|
102789
102974
|
const server = createServer((req, res) => {
|
|
102790
102975
|
if (req.url === "/render_page.js") {
|
|
@@ -102830,7 +103015,7 @@ async function runPreviewCommand(filePath, flags) {
|
|
|
102830
103015
|
const portFile = join2(udd, "DevToolsActivePort");
|
|
102831
103016
|
for (let i2 = 0; i2 < 100 && !cdpPort; i2++) {
|
|
102832
103017
|
if (existsSync2(portFile)) {
|
|
102833
|
-
const p = parseInt(
|
|
103018
|
+
const p = parseInt(readFileSync(portFile, "utf8").split("\n")[0], 10);
|
|
102834
103019
|
if (p) cdpPort = p;
|
|
102835
103020
|
}
|
|
102836
103021
|
if (!cdpPort) await sleep(100);
|
|
@@ -102886,7 +103071,7 @@ async function runPreviewCommand(filePath, flags) {
|
|
|
102886
103071
|
const outPath = flags.output ? resolve(flags.output) : join2(dirname(abs2), basename(abs2, ext) + ".png");
|
|
102887
103072
|
writeFileSync(outPath, Buffer.from(shot.data, "base64"));
|
|
102888
103073
|
console.log(`Rendered ${basename(abs2)} \u2192 ${outPath} (${Math.min(w, MAX_CAPTURE)}\xD7${Math.min(h, MAX_CAPTURE)}, via ${basename(chrome)})`);
|
|
102889
|
-
for (const
|
|
103074
|
+
for (const warn2 of warnings) console.error(` \u26A0 ${warn2}`);
|
|
102890
103075
|
} finally {
|
|
102891
103076
|
cleanup();
|
|
102892
103077
|
}
|
|
@@ -103037,8 +103222,8 @@ function prompt(question) {
|
|
|
103037
103222
|
});
|
|
103038
103223
|
});
|
|
103039
103224
|
}
|
|
103040
|
-
async function publicPost(
|
|
103041
|
-
const response = await fetch(`${API_BASE_URL}${
|
|
103225
|
+
async function publicPost(path13, body) {
|
|
103226
|
+
const response = await fetch(`${API_BASE_URL}${path13}`, {
|
|
103042
103227
|
method: "POST",
|
|
103043
103228
|
headers: { "Content-Type": "application/json" },
|
|
103044
103229
|
body: JSON.stringify(body)
|
|
@@ -103046,35 +103231,73 @@ async function publicPost(path14, body) {
|
|
|
103046
103231
|
const data2 = await response.json();
|
|
103047
103232
|
return { ok: response.ok, status: response.status, data: data2 };
|
|
103048
103233
|
}
|
|
103049
|
-
async function
|
|
103050
|
-
const
|
|
103051
|
-
if (
|
|
103052
|
-
|
|
103053
|
-
process.exit(1);
|
|
103054
|
-
}
|
|
103055
|
-
const name2 = flags.name ?? (process.stdin.isTTY ? await prompt("Name (enter to use email): ") : void 0);
|
|
103056
|
-
const body = { email: email3 };
|
|
103057
|
-
if (name2) body.name = name2;
|
|
103058
|
-
if (flags.timezone) body.timezone = flags.timezone;
|
|
103234
|
+
async function signupAccount(args) {
|
|
103235
|
+
const body = { email: args.email };
|
|
103236
|
+
if (args.name) body.name = args.name;
|
|
103237
|
+
if (args.timezone) body.timezone = args.timezone;
|
|
103059
103238
|
const { ok, status, data: data2 } = await publicPost("/v1/cli/signup", body);
|
|
103060
103239
|
if (!ok) {
|
|
103061
103240
|
if (status === 409) {
|
|
103062
|
-
|
|
103063
|
-
|
|
103064
|
-
|
|
103065
|
-
|
|
103066
|
-
|
|
103241
|
+
throw new Error(
|
|
103242
|
+
`An account with ${args.email} already exists.
|
|
103243
|
+
If this machine is already signed in: lotics auth whoami
|
|
103244
|
+
Otherwise take an API key from Settings \u2192 API keys at ${WEB_APP_URL}, then:
|
|
103245
|
+
lotics auth api-key <key>`
|
|
103246
|
+
);
|
|
103067
103247
|
}
|
|
103068
|
-
|
|
103248
|
+
if (status === 429) {
|
|
103249
|
+
throw new Error("Too many signup attempts. Try again later.");
|
|
103250
|
+
}
|
|
103251
|
+
throw new Error(`Signup failed: ${data2.message ?? JSON.stringify(data2)}`);
|
|
103069
103252
|
}
|
|
103070
103253
|
const apiKey = data2.api_key;
|
|
103071
103254
|
const orgId = data2.organization_id;
|
|
103072
103255
|
const workspaceId = data2.workspace_id;
|
|
103073
|
-
const orgName =
|
|
103256
|
+
const orgName = args.name || args.email.split("@")[0];
|
|
103074
103257
|
upsertProfile(orgId, { api_key: apiKey, org_name: orgName, workspace_id: workspaceId });
|
|
103075
103258
|
const existing = loadGlobalConfig() ?? {};
|
|
103076
|
-
saveGlobalConfig({ ...existing, email:
|
|
103077
|
-
setActiveOrg(orgId,
|
|
103259
|
+
saveGlobalConfig({ ...existing, email: args.email });
|
|
103260
|
+
setActiveOrg(orgId, args.local ? "local" : "global");
|
|
103261
|
+
return { email: args.email, apiKey, orgId, orgName, workspaceId };
|
|
103262
|
+
}
|
|
103263
|
+
function alreadySetUp(email3) {
|
|
103264
|
+
const config2 = loadGlobalConfig();
|
|
103265
|
+
if (config2?.email !== email3) return false;
|
|
103266
|
+
return Object.keys(config2.profiles ?? {}).length > 0;
|
|
103267
|
+
}
|
|
103268
|
+
async function handleSignup(positionalEmail, flags) {
|
|
103269
|
+
const email3 = positionalEmail ?? (process.stdin.isTTY ? await prompt("Email: ") : "");
|
|
103270
|
+
if (!email3) {
|
|
103271
|
+
console.error("Email is required. Usage: lotics auth signup <email>");
|
|
103272
|
+
process.exit(1);
|
|
103273
|
+
}
|
|
103274
|
+
if (alreadySetUp(email3)) {
|
|
103275
|
+
console.error(
|
|
103276
|
+
`This machine is already signed in as ${email3} \u2014 no new account needed.
|
|
103277
|
+
Carry on: lotics starter list
|
|
103278
|
+
Which account: lotics auth whoami` + // `--local` asked for a pin, and returning early gives none. Saying
|
|
103279
|
+
// nothing would leave a flag silently ignored, which is worse than the
|
|
103280
|
+
// 409 this replaced.
|
|
103281
|
+
(flags.local === true ? `
|
|
103282
|
+
--local pins a directory to an org, which signup does not do for an
|
|
103283
|
+
account that exists \u2014 use: lotics org use <name|id> --local` : "")
|
|
103284
|
+
);
|
|
103285
|
+
return;
|
|
103286
|
+
}
|
|
103287
|
+
const name2 = flags.name ?? (process.stdin.isTTY ? await prompt("Name (enter to use email): ") : void 0);
|
|
103288
|
+
let account;
|
|
103289
|
+
try {
|
|
103290
|
+
account = await signupAccount({
|
|
103291
|
+
email: email3,
|
|
103292
|
+
...name2 ? { name: name2 } : {},
|
|
103293
|
+
...flags.timezone ? { timezone: flags.timezone } : {},
|
|
103294
|
+
...flags.local === true ? { local: true } : {}
|
|
103295
|
+
});
|
|
103296
|
+
} catch (error52) {
|
|
103297
|
+
console.error(error52 instanceof Error ? error52.message : String(error52));
|
|
103298
|
+
process.exit(1);
|
|
103299
|
+
}
|
|
103300
|
+
const { orgId, orgName } = account;
|
|
103078
103301
|
console.error(`Account created. You can now use the CLI.`);
|
|
103079
103302
|
console.error(` Email: ${email3}`);
|
|
103080
103303
|
console.error(` Org: ${orgName} (${orgId})`);
|
|
@@ -103206,13 +103429,13 @@ async function resolveWorkspace(client, ctx) {
|
|
|
103206
103429
|
function resolveUploadPaths(rawPaths) {
|
|
103207
103430
|
const result = [];
|
|
103208
103431
|
for (const p of rawPaths) {
|
|
103209
|
-
const resolved =
|
|
103432
|
+
const resolved = path12.resolve(p);
|
|
103210
103433
|
const stat = fs14.statSync(resolved);
|
|
103211
103434
|
if (stat.isDirectory()) {
|
|
103212
103435
|
const entries2 = fs14.readdirSync(resolved, { withFileTypes: true });
|
|
103213
103436
|
for (const entry of entries2) {
|
|
103214
103437
|
if (entry.isFile()) {
|
|
103215
|
-
result.push(
|
|
103438
|
+
result.push(path12.join(resolved, entry.name));
|
|
103216
103439
|
}
|
|
103217
103440
|
}
|
|
103218
103441
|
} else {
|
|
@@ -103261,8 +103484,65 @@ async function main() {
|
|
|
103261
103484
|
console.log(VERSION);
|
|
103262
103485
|
return;
|
|
103263
103486
|
}
|
|
103487
|
+
if (command === "start") {
|
|
103488
|
+
const starterId = subcommand;
|
|
103489
|
+
if (!starterId) {
|
|
103490
|
+
console.error("Usage: lotics start <starter_id> [path] [--email <you@co.com>] [--json]");
|
|
103491
|
+
console.error(" Creates an account if this machine has none, then copies the starter");
|
|
103492
|
+
console.error(" into its workspace: schema, templates, knowledge docs, sample records");
|
|
103493
|
+
console.error(" and a deployed app. Ends with a one-time sign-in link.");
|
|
103494
|
+
console.error(" --json prints one object and nothing else.");
|
|
103495
|
+
process.exit(1);
|
|
103496
|
+
}
|
|
103497
|
+
if (flags.json) setMachineOutput(true);
|
|
103498
|
+
const existing = resolveContext(flags);
|
|
103499
|
+
if (existing === null) {
|
|
103500
|
+
const email3 = flags.email ?? (process.stdin.isTTY ? await prompt("Email: ") : "");
|
|
103501
|
+
if (!email3) {
|
|
103502
|
+
console.error(
|
|
103503
|
+
"This machine has no Lotics credential yet, so `start` needs an email to create one:\n lotics start " + starterId + " --email you@company.com"
|
|
103504
|
+
);
|
|
103505
|
+
process.exit(1);
|
|
103506
|
+
}
|
|
103507
|
+
try {
|
|
103508
|
+
const account = await signupAccount({
|
|
103509
|
+
email: email3,
|
|
103510
|
+
...flags.name ? { name: flags.name } : {},
|
|
103511
|
+
...flags.timezone ? { timezone: flags.timezone } : {},
|
|
103512
|
+
...flags.local === true ? { local: true } : {}
|
|
103513
|
+
});
|
|
103514
|
+
note(`Account created for ${account.email} \u2014 org ${account.orgName} (${account.orgId}).`);
|
|
103515
|
+
} catch (error52) {
|
|
103516
|
+
console.error(error52 instanceof Error ? error52.message : String(error52));
|
|
103517
|
+
process.exit(1);
|
|
103518
|
+
}
|
|
103519
|
+
} else if (flags.email !== void 0) {
|
|
103520
|
+
console.error(
|
|
103521
|
+
`Already authenticated (${SOURCE_LABELS[existing.source]}), so --email would create a SECOND account and copy into it.
|
|
103522
|
+
Copy into the account you have: lotics start ${starterId}
|
|
103523
|
+
Or create another one first: lotics auth signup ${flags.email}`
|
|
103524
|
+
);
|
|
103525
|
+
process.exit(1);
|
|
103526
|
+
}
|
|
103527
|
+
const { client: client2, ctx: ctx2 } = requireClient(flags);
|
|
103528
|
+
await resolveWorkspace(client2, ctx2);
|
|
103529
|
+
const result = await starterInit(client2, {
|
|
103530
|
+
starter_id: starterId,
|
|
103531
|
+
...toolArgs !== void 0 ? { targetPath: toolArgs } : {},
|
|
103532
|
+
...flags.noSampleData === true ? { noSampleData: true } : {},
|
|
103533
|
+
...flags.adopt === true ? { adopt: true } : {}
|
|
103534
|
+
});
|
|
103535
|
+
if (flags.json) {
|
|
103536
|
+
emitJson({ organization_id: ctx2.orgId, workspace_id: ctx2.workspaceId, ...result });
|
|
103537
|
+
}
|
|
103538
|
+
return;
|
|
103539
|
+
}
|
|
103264
103540
|
if (command === "starter") {
|
|
103265
103541
|
if (subcommand === "list") {
|
|
103542
|
+
if (resolveContext(flags) === null) {
|
|
103543
|
+
await starterListPublic();
|
|
103544
|
+
return;
|
|
103545
|
+
}
|
|
103266
103546
|
const { client: client2, ctx: ctx2 } = requireClient(flags);
|
|
103267
103547
|
await resolveWorkspace(client2, ctx2);
|
|
103268
103548
|
await starterList(client2);
|
|
@@ -103286,14 +103566,18 @@ async function main() {
|
|
|
103286
103566
|
console.error(" locally, so it needs node and a few minutes.");
|
|
103287
103567
|
process.exit(1);
|
|
103288
103568
|
}
|
|
103569
|
+
if (flags.json) setMachineOutput(true);
|
|
103289
103570
|
const { client: client2, ctx: ctx2 } = requireClient(flags);
|
|
103290
103571
|
await resolveWorkspace(client2, ctx2);
|
|
103291
|
-
await starterInit(client2, {
|
|
103572
|
+
const result = await starterInit(client2, {
|
|
103292
103573
|
starter_id: toolArgs,
|
|
103293
103574
|
...restArgs[0] !== void 0 ? { targetPath: restArgs[0] } : {},
|
|
103294
103575
|
...flags.noSampleData === true ? { noSampleData: true } : {},
|
|
103295
103576
|
...flags.adopt === true ? { adopt: true } : {}
|
|
103296
103577
|
});
|
|
103578
|
+
if (flags.json) {
|
|
103579
|
+
emitJson({ organization_id: ctx2.orgId, workspace_id: ctx2.workspaceId, ...result });
|
|
103580
|
+
}
|
|
103297
103581
|
return;
|
|
103298
103582
|
}
|
|
103299
103583
|
if (subcommand === "fixtures") {
|
|
@@ -103464,7 +103748,7 @@ async function main() {
|
|
|
103464
103748
|
if (command === "preview") {
|
|
103465
103749
|
if (subcommand && isStoredFileId(subcommand)) {
|
|
103466
103750
|
const { client: client2 } = requireClient(flags);
|
|
103467
|
-
const tmpDir = fs14.mkdtempSync(
|
|
103751
|
+
const tmpDir = fs14.mkdtempSync(path12.join(os4.tmpdir(), "lotics-preview-"));
|
|
103468
103752
|
try {
|
|
103469
103753
|
const { path: localPath, filename } = await client2.downloadFileById(subcommand, tmpDir);
|
|
103470
103754
|
const output = flags.output ?? defaultPreviewOutputPath(filename, process.cwd());
|
|
@@ -104067,6 +104351,7 @@ ${JSON.stringify(info.input_schema, null, 2)}`);
|
|
|
104067
104351
|
}
|
|
104068
104352
|
}
|
|
104069
104353
|
main().then(() => checkForUpdate(VERSION)).catch((error52) => {
|
|
104354
|
+
flushPendingWarnings();
|
|
104070
104355
|
console.error(describeCliError(error52));
|
|
104071
104356
|
process.exit(1);
|
|
104072
104357
|
});
|