@akanjs/cli 2.1.1-rc.1 → 2.1.1-rc.2
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/incrementalBuilder.proc.js +344 -456
- package/index.js +581 -494
- package/package.json +3 -2
- package/typecheck.proc.js +0 -31
package/index.js
CHANGED
|
@@ -1,329 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
var __create = Object.create;
|
|
4
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
5
|
-
var __defProp = Object.defineProperty;
|
|
6
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
function __accessProp(key) {
|
|
9
|
-
return this[key];
|
|
10
|
-
}
|
|
11
|
-
var __toESMCache_node;
|
|
12
|
-
var __toESMCache_esm;
|
|
13
|
-
var __toESM = (mod, isNodeMode, target) => {
|
|
14
|
-
var canCache = mod != null && typeof mod === "object";
|
|
15
|
-
if (canCache) {
|
|
16
|
-
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
|
|
17
|
-
var cached = cache.get(mod);
|
|
18
|
-
if (cached)
|
|
19
|
-
return cached;
|
|
20
|
-
}
|
|
21
|
-
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
22
|
-
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
23
|
-
for (let key of __getOwnPropNames(mod))
|
|
24
|
-
if (!__hasOwnProp.call(to, key))
|
|
25
|
-
__defProp(to, key, {
|
|
26
|
-
get: __accessProp.bind(mod, key),
|
|
27
|
-
enumerable: true
|
|
28
|
-
});
|
|
29
|
-
if (canCache)
|
|
30
|
-
cache.set(mod, to);
|
|
31
|
-
return to;
|
|
32
|
-
};
|
|
33
|
-
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
34
3
|
var __require = import.meta.require;
|
|
35
4
|
|
|
36
|
-
// node_modules/dayjs/dayjs.min.js
|
|
37
|
-
var require_dayjs_min = __commonJS((exports, module) => {
|
|
38
|
-
(function(t, e) {
|
|
39
|
-
typeof exports == "object" && typeof module != "undefined" ? module.exports = e() : typeof define == "function" && define.amd ? define(e) : (t = typeof globalThis != "undefined" ? globalThis : t || self).dayjs = e();
|
|
40
|
-
})(exports, function() {
|
|
41
|
-
var t = 1000, e = 60000, n = 3600000, r = "millisecond", i = "second", s = "minute", u = "hour", a = "day", o = "week", c = "month", f = "quarter", h = "year", d = "date", l = "Invalid Date", $2 = /^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/, y = /\[([^\]]+)]|YYYY|YY|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g, M = { name: "en", weekdays: "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), months: "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), ordinal: function(t2) {
|
|
42
|
-
var e2 = ["th", "st", "nd", "rd"], n2 = t2 % 100;
|
|
43
|
-
return "[" + t2 + (e2[(n2 - 20) % 10] || e2[n2] || e2[0]) + "]";
|
|
44
|
-
} }, m = function(t2, e2, n2) {
|
|
45
|
-
var r2 = String(t2);
|
|
46
|
-
return !r2 || r2.length >= e2 ? t2 : "" + Array(e2 + 1 - r2.length).join(n2) + t2;
|
|
47
|
-
}, v = { s: m, z: function(t2) {
|
|
48
|
-
var e2 = -t2.utcOffset(), n2 = Math.abs(e2), r2 = Math.floor(n2 / 60), i2 = n2 % 60;
|
|
49
|
-
return (e2 <= 0 ? "+" : "-") + m(r2, 2, "0") + ":" + m(i2, 2, "0");
|
|
50
|
-
}, m: function t2(e2, n2) {
|
|
51
|
-
if (e2.date() < n2.date())
|
|
52
|
-
return -t2(n2, e2);
|
|
53
|
-
var r2 = 12 * (n2.year() - e2.year()) + (n2.month() - e2.month()), i2 = e2.clone().add(r2, c), s2 = n2 - i2 < 0, u2 = e2.clone().add(r2 + (s2 ? -1 : 1), c);
|
|
54
|
-
return +(-(r2 + (n2 - i2) / (s2 ? i2 - u2 : u2 - i2)) || 0);
|
|
55
|
-
}, a: function(t2) {
|
|
56
|
-
return t2 < 0 ? Math.ceil(t2) || 0 : Math.floor(t2);
|
|
57
|
-
}, p: function(t2) {
|
|
58
|
-
return { M: c, y: h, w: o, d: a, D: d, h: u, m: s, s: i, ms: r, Q: f }[t2] || String(t2 || "").toLowerCase().replace(/s$/, "");
|
|
59
|
-
}, u: function(t2) {
|
|
60
|
-
return t2 === undefined;
|
|
61
|
-
} }, g = "en", D = {};
|
|
62
|
-
D[g] = M;
|
|
63
|
-
var p = "$isDayjsObject", S = function(t2) {
|
|
64
|
-
return t2 instanceof _ || !(!t2 || !t2[p]);
|
|
65
|
-
}, w = function t2(e2, n2, r2) {
|
|
66
|
-
var i2;
|
|
67
|
-
if (!e2)
|
|
68
|
-
return g;
|
|
69
|
-
if (typeof e2 == "string") {
|
|
70
|
-
var s2 = e2.toLowerCase();
|
|
71
|
-
D[s2] && (i2 = s2), n2 && (D[s2] = n2, i2 = s2);
|
|
72
|
-
var u2 = e2.split("-");
|
|
73
|
-
if (!i2 && u2.length > 1)
|
|
74
|
-
return t2(u2[0]);
|
|
75
|
-
} else {
|
|
76
|
-
var a2 = e2.name;
|
|
77
|
-
D[a2] = e2, i2 = a2;
|
|
78
|
-
}
|
|
79
|
-
return !r2 && i2 && (g = i2), i2 || !r2 && g;
|
|
80
|
-
}, O = function(t2, e2) {
|
|
81
|
-
if (S(t2))
|
|
82
|
-
return t2.clone();
|
|
83
|
-
var n2 = typeof e2 == "object" ? e2 : {};
|
|
84
|
-
return n2.date = t2, n2.args = arguments, new _(n2);
|
|
85
|
-
}, b = v;
|
|
86
|
-
b.l = w, b.i = S, b.w = function(t2, e2) {
|
|
87
|
-
return O(t2, { locale: e2.$L, utc: e2.$u, x: e2.$x, $offset: e2.$offset });
|
|
88
|
-
};
|
|
89
|
-
var _ = function() {
|
|
90
|
-
function M2(t2) {
|
|
91
|
-
this.$L = w(t2.locale, null, true), this.parse(t2), this.$x = this.$x || t2.x || {}, this[p] = true;
|
|
92
|
-
}
|
|
93
|
-
var m2 = M2.prototype;
|
|
94
|
-
return m2.parse = function(t2) {
|
|
95
|
-
this.$d = function(t3) {
|
|
96
|
-
var { date: e2, utc: n2 } = t3;
|
|
97
|
-
if (e2 === null)
|
|
98
|
-
return new Date(NaN);
|
|
99
|
-
if (b.u(e2))
|
|
100
|
-
return new Date;
|
|
101
|
-
if (e2 instanceof Date)
|
|
102
|
-
return new Date(e2);
|
|
103
|
-
if (typeof e2 == "string" && !/Z$/i.test(e2)) {
|
|
104
|
-
var r2 = e2.match($2);
|
|
105
|
-
if (r2) {
|
|
106
|
-
var i2 = r2[2] - 1 || 0, s2 = (r2[7] || "0").substring(0, 3);
|
|
107
|
-
return n2 ? new Date(Date.UTC(r2[1], i2, r2[3] || 1, r2[4] || 0, r2[5] || 0, r2[6] || 0, s2)) : new Date(r2[1], i2, r2[3] || 1, r2[4] || 0, r2[5] || 0, r2[6] || 0, s2);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
return new Date(e2);
|
|
111
|
-
}(t2), this.init();
|
|
112
|
-
}, m2.init = function() {
|
|
113
|
-
var t2 = this.$d;
|
|
114
|
-
this.$y = t2.getFullYear(), this.$M = t2.getMonth(), this.$D = t2.getDate(), this.$W = t2.getDay(), this.$H = t2.getHours(), this.$m = t2.getMinutes(), this.$s = t2.getSeconds(), this.$ms = t2.getMilliseconds();
|
|
115
|
-
}, m2.$utils = function() {
|
|
116
|
-
return b;
|
|
117
|
-
}, m2.isValid = function() {
|
|
118
|
-
return !(this.$d.toString() === l);
|
|
119
|
-
}, m2.isSame = function(t2, e2) {
|
|
120
|
-
var n2 = O(t2);
|
|
121
|
-
return this.startOf(e2) <= n2 && n2 <= this.endOf(e2);
|
|
122
|
-
}, m2.isAfter = function(t2, e2) {
|
|
123
|
-
return O(t2) < this.startOf(e2);
|
|
124
|
-
}, m2.isBefore = function(t2, e2) {
|
|
125
|
-
return this.endOf(e2) < O(t2);
|
|
126
|
-
}, m2.$g = function(t2, e2, n2) {
|
|
127
|
-
return b.u(t2) ? this[e2] : this.set(n2, t2);
|
|
128
|
-
}, m2.unix = function() {
|
|
129
|
-
return Math.floor(this.valueOf() / 1000);
|
|
130
|
-
}, m2.valueOf = function() {
|
|
131
|
-
return this.$d.getTime();
|
|
132
|
-
}, m2.startOf = function(t2, e2) {
|
|
133
|
-
var n2 = this, r2 = !!b.u(e2) || e2, f2 = b.p(t2), l2 = function(t3, e3) {
|
|
134
|
-
var i2 = b.w(n2.$u ? Date.UTC(n2.$y, e3, t3) : new Date(n2.$y, e3, t3), n2);
|
|
135
|
-
return r2 ? i2 : i2.endOf(a);
|
|
136
|
-
}, $3 = function(t3, e3) {
|
|
137
|
-
return b.w(n2.toDate()[t3].apply(n2.toDate("s"), (r2 ? [0, 0, 0, 0] : [23, 59, 59, 999]).slice(e3)), n2);
|
|
138
|
-
}, y2 = this.$W, M3 = this.$M, m3 = this.$D, v2 = "set" + (this.$u ? "UTC" : "");
|
|
139
|
-
switch (f2) {
|
|
140
|
-
case h:
|
|
141
|
-
return r2 ? l2(1, 0) : l2(31, 11);
|
|
142
|
-
case c:
|
|
143
|
-
return r2 ? l2(1, M3) : l2(0, M3 + 1);
|
|
144
|
-
case o:
|
|
145
|
-
var g2 = this.$locale().weekStart || 0, D2 = (y2 < g2 ? y2 + 7 : y2) - g2;
|
|
146
|
-
return l2(r2 ? m3 - D2 : m3 + (6 - D2), M3);
|
|
147
|
-
case a:
|
|
148
|
-
case d:
|
|
149
|
-
return $3(v2 + "Hours", 0);
|
|
150
|
-
case u:
|
|
151
|
-
return $3(v2 + "Minutes", 1);
|
|
152
|
-
case s:
|
|
153
|
-
return $3(v2 + "Seconds", 2);
|
|
154
|
-
case i:
|
|
155
|
-
return $3(v2 + "Milliseconds", 3);
|
|
156
|
-
default:
|
|
157
|
-
return this.clone();
|
|
158
|
-
}
|
|
159
|
-
}, m2.endOf = function(t2) {
|
|
160
|
-
return this.startOf(t2, false);
|
|
161
|
-
}, m2.$set = function(t2, e2) {
|
|
162
|
-
var n2, o2 = b.p(t2), f2 = "set" + (this.$u ? "UTC" : ""), l2 = (n2 = {}, n2[a] = f2 + "Date", n2[d] = f2 + "Date", n2[c] = f2 + "Month", n2[h] = f2 + "FullYear", n2[u] = f2 + "Hours", n2[s] = f2 + "Minutes", n2[i] = f2 + "Seconds", n2[r] = f2 + "Milliseconds", n2)[o2], $3 = o2 === a ? this.$D + (e2 - this.$W) : e2;
|
|
163
|
-
if (o2 === c || o2 === h) {
|
|
164
|
-
var y2 = this.clone().set(d, 1);
|
|
165
|
-
y2.$d[l2]($3), y2.init(), this.$d = y2.set(d, Math.min(this.$D, y2.daysInMonth())).$d;
|
|
166
|
-
} else
|
|
167
|
-
l2 && this.$d[l2]($3);
|
|
168
|
-
return this.init(), this;
|
|
169
|
-
}, m2.set = function(t2, e2) {
|
|
170
|
-
return this.clone().$set(t2, e2);
|
|
171
|
-
}, m2.get = function(t2) {
|
|
172
|
-
return this[b.p(t2)]();
|
|
173
|
-
}, m2.add = function(r2, f2) {
|
|
174
|
-
var d2, l2 = this;
|
|
175
|
-
r2 = Number(r2);
|
|
176
|
-
var $3 = b.p(f2), y2 = function(t2) {
|
|
177
|
-
var e2 = O(l2);
|
|
178
|
-
return b.w(e2.date(e2.date() + Math.round(t2 * r2)), l2);
|
|
179
|
-
};
|
|
180
|
-
if ($3 === c)
|
|
181
|
-
return this.set(c, this.$M + r2);
|
|
182
|
-
if ($3 === h)
|
|
183
|
-
return this.set(h, this.$y + r2);
|
|
184
|
-
if ($3 === a)
|
|
185
|
-
return y2(1);
|
|
186
|
-
if ($3 === o)
|
|
187
|
-
return y2(7);
|
|
188
|
-
var M3 = (d2 = {}, d2[s] = e, d2[u] = n, d2[i] = t, d2)[$3] || 1, m3 = this.$d.getTime() + r2 * M3;
|
|
189
|
-
return b.w(m3, this);
|
|
190
|
-
}, m2.subtract = function(t2, e2) {
|
|
191
|
-
return this.add(-1 * t2, e2);
|
|
192
|
-
}, m2.format = function(t2) {
|
|
193
|
-
var e2 = this, n2 = this.$locale();
|
|
194
|
-
if (!this.isValid())
|
|
195
|
-
return n2.invalidDate || l;
|
|
196
|
-
var r2 = t2 || "YYYY-MM-DDTHH:mm:ssZ", i2 = b.z(this), s2 = this.$H, u2 = this.$m, a2 = this.$M, o2 = n2.weekdays, c2 = n2.months, f2 = n2.meridiem, h2 = function(t3, n3, i3, s3) {
|
|
197
|
-
return t3 && (t3[n3] || t3(e2, r2)) || i3[n3].slice(0, s3);
|
|
198
|
-
}, d2 = function(t3) {
|
|
199
|
-
return b.s(s2 % 12 || 12, t3, "0");
|
|
200
|
-
}, $3 = f2 || function(t3, e3, n3) {
|
|
201
|
-
var r3 = t3 < 12 ? "AM" : "PM";
|
|
202
|
-
return n3 ? r3.toLowerCase() : r3;
|
|
203
|
-
};
|
|
204
|
-
return r2.replace(y, function(t3, r3) {
|
|
205
|
-
return r3 || function(t4) {
|
|
206
|
-
switch (t4) {
|
|
207
|
-
case "YY":
|
|
208
|
-
return String(e2.$y).slice(-2);
|
|
209
|
-
case "YYYY":
|
|
210
|
-
return b.s(e2.$y, 4, "0");
|
|
211
|
-
case "M":
|
|
212
|
-
return a2 + 1;
|
|
213
|
-
case "MM":
|
|
214
|
-
return b.s(a2 + 1, 2, "0");
|
|
215
|
-
case "MMM":
|
|
216
|
-
return h2(n2.monthsShort, a2, c2, 3);
|
|
217
|
-
case "MMMM":
|
|
218
|
-
return h2(c2, a2);
|
|
219
|
-
case "D":
|
|
220
|
-
return e2.$D;
|
|
221
|
-
case "DD":
|
|
222
|
-
return b.s(e2.$D, 2, "0");
|
|
223
|
-
case "d":
|
|
224
|
-
return String(e2.$W);
|
|
225
|
-
case "dd":
|
|
226
|
-
return h2(n2.weekdaysMin, e2.$W, o2, 2);
|
|
227
|
-
case "ddd":
|
|
228
|
-
return h2(n2.weekdaysShort, e2.$W, o2, 3);
|
|
229
|
-
case "dddd":
|
|
230
|
-
return o2[e2.$W];
|
|
231
|
-
case "H":
|
|
232
|
-
return String(s2);
|
|
233
|
-
case "HH":
|
|
234
|
-
return b.s(s2, 2, "0");
|
|
235
|
-
case "h":
|
|
236
|
-
return d2(1);
|
|
237
|
-
case "hh":
|
|
238
|
-
return d2(2);
|
|
239
|
-
case "a":
|
|
240
|
-
return $3(s2, u2, true);
|
|
241
|
-
case "A":
|
|
242
|
-
return $3(s2, u2, false);
|
|
243
|
-
case "m":
|
|
244
|
-
return String(u2);
|
|
245
|
-
case "mm":
|
|
246
|
-
return b.s(u2, 2, "0");
|
|
247
|
-
case "s":
|
|
248
|
-
return String(e2.$s);
|
|
249
|
-
case "ss":
|
|
250
|
-
return b.s(e2.$s, 2, "0");
|
|
251
|
-
case "SSS":
|
|
252
|
-
return b.s(e2.$ms, 3, "0");
|
|
253
|
-
case "Z":
|
|
254
|
-
return i2;
|
|
255
|
-
}
|
|
256
|
-
return null;
|
|
257
|
-
}(t3) || i2.replace(":", "");
|
|
258
|
-
});
|
|
259
|
-
}, m2.utcOffset = function() {
|
|
260
|
-
return 15 * -Math.round(this.$d.getTimezoneOffset() / 15);
|
|
261
|
-
}, m2.diff = function(r2, d2, l2) {
|
|
262
|
-
var $3, y2 = this, M3 = b.p(d2), m3 = O(r2), v2 = (m3.utcOffset() - this.utcOffset()) * e, g2 = this - m3, D2 = function() {
|
|
263
|
-
return b.m(y2, m3);
|
|
264
|
-
};
|
|
265
|
-
switch (M3) {
|
|
266
|
-
case h:
|
|
267
|
-
$3 = D2() / 12;
|
|
268
|
-
break;
|
|
269
|
-
case c:
|
|
270
|
-
$3 = D2();
|
|
271
|
-
break;
|
|
272
|
-
case f:
|
|
273
|
-
$3 = D2() / 3;
|
|
274
|
-
break;
|
|
275
|
-
case o:
|
|
276
|
-
$3 = (g2 - v2) / 604800000;
|
|
277
|
-
break;
|
|
278
|
-
case a:
|
|
279
|
-
$3 = (g2 - v2) / 86400000;
|
|
280
|
-
break;
|
|
281
|
-
case u:
|
|
282
|
-
$3 = g2 / n;
|
|
283
|
-
break;
|
|
284
|
-
case s:
|
|
285
|
-
$3 = g2 / e;
|
|
286
|
-
break;
|
|
287
|
-
case i:
|
|
288
|
-
$3 = g2 / t;
|
|
289
|
-
break;
|
|
290
|
-
default:
|
|
291
|
-
$3 = g2;
|
|
292
|
-
}
|
|
293
|
-
return l2 ? $3 : b.a($3);
|
|
294
|
-
}, m2.daysInMonth = function() {
|
|
295
|
-
return this.endOf(c).$D;
|
|
296
|
-
}, m2.$locale = function() {
|
|
297
|
-
return D[this.$L];
|
|
298
|
-
}, m2.locale = function(t2, e2) {
|
|
299
|
-
if (!t2)
|
|
300
|
-
return this.$L;
|
|
301
|
-
var n2 = this.clone(), r2 = w(t2, e2, true);
|
|
302
|
-
return r2 && (n2.$L = r2), n2;
|
|
303
|
-
}, m2.clone = function() {
|
|
304
|
-
return b.w(this.$d, this);
|
|
305
|
-
}, m2.toDate = function() {
|
|
306
|
-
return new Date(this.valueOf());
|
|
307
|
-
}, m2.toJSON = function() {
|
|
308
|
-
return this.isValid() ? this.toISOString() : null;
|
|
309
|
-
}, m2.toISOString = function() {
|
|
310
|
-
return this.$d.toISOString();
|
|
311
|
-
}, m2.toString = function() {
|
|
312
|
-
return this.$d.toUTCString();
|
|
313
|
-
}, M2;
|
|
314
|
-
}(), Y = _.prototype;
|
|
315
|
-
return O.prototype = Y, [["$ms", r], ["$s", i], ["$m", s], ["$H", u], ["$W", a], ["$M", c], ["$y", h], ["$D", d]].forEach(function(t2) {
|
|
316
|
-
Y[t2[1]] = function(e2) {
|
|
317
|
-
return this.$g(e2, t2[0], t2[1]);
|
|
318
|
-
};
|
|
319
|
-
}), O.extend = function(t2, e2) {
|
|
320
|
-
return t2.$i || (t2(e2, _, O), t2.$i = true), O;
|
|
321
|
-
}, O.locale = w, O.isDayjs = S, O.unix = function(t2) {
|
|
322
|
-
return O(1000 * t2);
|
|
323
|
-
}, O.en = D[g], O.Ls = D, O.p = {}, O;
|
|
324
|
-
});
|
|
325
|
-
});
|
|
326
|
-
|
|
327
5
|
// pkgs/@akanjs/devkit/aiEditor.ts
|
|
328
6
|
import { input, select } from "@inquirer/prompts";
|
|
329
7
|
import {
|
|
@@ -337,10 +15,7 @@ import { ChatOpenAI } from "@langchain/openai";
|
|
|
337
15
|
import { Logger as Logger2 } from "akanjs/common";
|
|
338
16
|
import chalk from "chalk";
|
|
339
17
|
|
|
340
|
-
// pkgs/@akanjs/devkit/
|
|
341
|
-
import { mkdir } from "fs/promises";
|
|
342
|
-
|
|
343
|
-
// pkgs/@akanjs/devkit/constants.ts
|
|
18
|
+
// pkgs/@akanjs/devkit/cloud/constants.ts
|
|
344
19
|
var basePath = `${Bun.env.HOME ?? Bun.env.USERPROFILE}/.akan`;
|
|
345
20
|
var configPath = `${basePath}/config.json`;
|
|
346
21
|
var akanCloudHost = process.env.AKAN_PUBLIC_OPERATION_MODE === "local" ? "http://localhost" : "https://cloud.akanjs.com";
|
|
@@ -348,9 +23,14 @@ var akanCloudUrl = `${akanCloudHost}${process.env.AKAN_PUBLIC_OPERATION_MODE ===
|
|
|
348
23
|
var defaultHostConfig = {};
|
|
349
24
|
var defaultAkanGlobalConfig = {
|
|
350
25
|
cloudHost: {},
|
|
26
|
+
remoteEnvServers: {},
|
|
351
27
|
llm: null
|
|
352
28
|
};
|
|
353
29
|
|
|
30
|
+
// pkgs/@akanjs/devkit/cloud/globalConfig.ts
|
|
31
|
+
import { mkdir } from "fs/promises";
|
|
32
|
+
import dayjs from "dayjs";
|
|
33
|
+
|
|
354
34
|
// pkgs/@akanjs/devkit/fileSys.ts
|
|
355
35
|
import { stat } from "fs/promises";
|
|
356
36
|
import { Logger } from "akanjs/common";
|
|
@@ -389,35 +69,198 @@ class FileSys {
|
|
|
389
69
|
}
|
|
390
70
|
}
|
|
391
71
|
|
|
392
|
-
// pkgs/@akanjs/devkit/
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
const akanConfig = await getAkanGlobalConfig();
|
|
404
|
-
return akanConfig.cloudHost[host] ?? defaultHostConfig;
|
|
405
|
-
};
|
|
406
|
-
var setHostConfig = async (host = akanCloudHost, config = {}) => {
|
|
407
|
-
const akanConfig = await getAkanGlobalConfig();
|
|
408
|
-
akanConfig.cloudHost[host] = config;
|
|
409
|
-
await setAkanGlobalConfig(akanConfig);
|
|
410
|
-
};
|
|
411
|
-
var getSelf = async (token) => {
|
|
412
|
-
try {
|
|
413
|
-
const res = await fetch(`${akanCloudUrl}/user/getSelf`, { headers: { Authorization: `Bearer ${token}` } });
|
|
414
|
-
const user = await res.json();
|
|
415
|
-
return user;
|
|
416
|
-
} catch (e) {
|
|
417
|
-
return null;
|
|
72
|
+
// pkgs/@akanjs/devkit/cloud/globalConfig.ts
|
|
73
|
+
class GlobalConfig {
|
|
74
|
+
static async#getAkanGlobalConfig() {
|
|
75
|
+
const exists = await FileSys.fileExists(configPath);
|
|
76
|
+
const akanConfig = exists ? await FileSys.readJson(configPath) : {};
|
|
77
|
+
return {
|
|
78
|
+
...defaultAkanGlobalConfig,
|
|
79
|
+
...akanConfig,
|
|
80
|
+
cloudHost: akanConfig.cloudHost ?? defaultAkanGlobalConfig.cloudHost,
|
|
81
|
+
remoteEnvServers: akanConfig.remoteEnvServers ?? defaultAkanGlobalConfig.remoteEnvServers
|
|
82
|
+
};
|
|
418
83
|
}
|
|
419
|
-
|
|
84
|
+
static async#setAkanGlobalConfig(akanConfig) {
|
|
85
|
+
await mkdir(basePath, { recursive: true });
|
|
86
|
+
await Bun.write(configPath, JSON.stringify(akanConfig, null, 2));
|
|
87
|
+
}
|
|
88
|
+
static async getHostConfig(host = akanCloudHost) {
|
|
89
|
+
const akanConfig = await GlobalConfig.#getAkanGlobalConfig();
|
|
90
|
+
return GlobalConfig.toHostConfig(akanConfig.cloudHost[host] ?? defaultHostConfig);
|
|
91
|
+
}
|
|
92
|
+
static async setHostConfig(host = akanCloudHost, config = {}) {
|
|
93
|
+
const akanConfig = await GlobalConfig.#getAkanGlobalConfig();
|
|
94
|
+
akanConfig.cloudHost[host] = GlobalConfig.toHostConfigDto(config);
|
|
95
|
+
await GlobalConfig.#setAkanGlobalConfig(akanConfig);
|
|
96
|
+
}
|
|
97
|
+
static async getLlmConfig() {
|
|
98
|
+
const akanConfig = await GlobalConfig.#getAkanGlobalConfig();
|
|
99
|
+
return akanConfig.llm ?? null;
|
|
100
|
+
}
|
|
101
|
+
static async setLlmConfig(llmConfig) {
|
|
102
|
+
const akanConfig = await GlobalConfig.#getAkanGlobalConfig();
|
|
103
|
+
await GlobalConfig.#setAkanGlobalConfig({ ...akanConfig, llm: llmConfig });
|
|
104
|
+
}
|
|
105
|
+
static async getRemoteEnvServers() {
|
|
106
|
+
const akanConfig = await GlobalConfig.#getAkanGlobalConfig();
|
|
107
|
+
return akanConfig.remoteEnvServers;
|
|
108
|
+
}
|
|
109
|
+
static async setRemoteEnvServer(name, config) {
|
|
110
|
+
const akanConfig = await GlobalConfig.#getAkanGlobalConfig();
|
|
111
|
+
await GlobalConfig.#setAkanGlobalConfig({
|
|
112
|
+
...akanConfig,
|
|
113
|
+
remoteEnvServers: {
|
|
114
|
+
...akanConfig.remoteEnvServers,
|
|
115
|
+
[name]: config
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
static async removeRemoteEnvServer(name) {
|
|
120
|
+
const akanConfig = await GlobalConfig.#getAkanGlobalConfig();
|
|
121
|
+
const { [name]: _, ...remoteEnvServers } = akanConfig.remoteEnvServers;
|
|
122
|
+
await GlobalConfig.#setAkanGlobalConfig({
|
|
123
|
+
...akanConfig,
|
|
124
|
+
remoteEnvServers
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
static needRefreshToken(accessToken) {
|
|
128
|
+
return !!accessToken?.expiresAt?.isBefore(dayjs().add(1, "hour"));
|
|
129
|
+
}
|
|
130
|
+
static toAccessToken(accessToken) {
|
|
131
|
+
return {
|
|
132
|
+
jwt: accessToken.jwt,
|
|
133
|
+
refreshToken: accessToken.refreshToken ?? null,
|
|
134
|
+
expiresAt: accessToken.expiresAt ? dayjs(accessToken.expiresAt) : null
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
static toAccessTokenDto(accessToken) {
|
|
138
|
+
return {
|
|
139
|
+
jwt: accessToken.jwt,
|
|
140
|
+
refreshToken: accessToken.refreshToken ?? null,
|
|
141
|
+
expiresAt: accessToken.expiresAt?.toString() ?? null
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
static toHostConfigDto(hostConfig) {
|
|
145
|
+
return {
|
|
146
|
+
auth: {
|
|
147
|
+
accessToken: hostConfig.auth?.accessToken ? GlobalConfig.toAccessTokenDto(hostConfig.auth.accessToken) : undefined,
|
|
148
|
+
self: hostConfig.auth?.self
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
static toHostConfig(hostConfigDto) {
|
|
153
|
+
return {
|
|
154
|
+
auth: {
|
|
155
|
+
accessToken: hostConfigDto.auth?.accessToken ? GlobalConfig.toAccessToken(hostConfigDto.auth.accessToken) : undefined,
|
|
156
|
+
self: hostConfigDto.auth?.self
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
}
|
|
420
161
|
|
|
162
|
+
// pkgs/@akanjs/devkit/cloud/cloudApi.ts
|
|
163
|
+
class HttpClient {
|
|
164
|
+
baseUrl;
|
|
165
|
+
headers = {};
|
|
166
|
+
constructor(baseUrl, headers = {}) {
|
|
167
|
+
this.baseUrl = baseUrl;
|
|
168
|
+
this.headers = headers;
|
|
169
|
+
}
|
|
170
|
+
async get(url, { headers } = {}) {
|
|
171
|
+
const response = await fetch(`${this.baseUrl}${url}`, {
|
|
172
|
+
headers: {
|
|
173
|
+
"Content-Type": "application/json",
|
|
174
|
+
...this.headers,
|
|
175
|
+
...headers
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
return response.json();
|
|
179
|
+
}
|
|
180
|
+
async getFile(url, localPath, headers) {
|
|
181
|
+
const response = await fetch(`${this.baseUrl}${url}`, {
|
|
182
|
+
headers: { ...this.headers, ...headers }
|
|
183
|
+
});
|
|
184
|
+
if (!response.ok)
|
|
185
|
+
throw new Error(`Failed to download file: ${response.status} ${response.statusText}`);
|
|
186
|
+
await Bun.write(localPath, response);
|
|
187
|
+
}
|
|
188
|
+
async post(url, data, { headers } = {}) {
|
|
189
|
+
const isFormData = data instanceof FormData;
|
|
190
|
+
const response = await fetch(`${this.baseUrl}${url}`, {
|
|
191
|
+
method: "POST",
|
|
192
|
+
body: isFormData ? data : JSON.stringify(data),
|
|
193
|
+
headers: isFormData ? { ...this.headers, ...headers } : { "Content-Type": "application/json", ...this.headers, ...headers }
|
|
194
|
+
});
|
|
195
|
+
return response.json();
|
|
196
|
+
}
|
|
197
|
+
setHeaders(headers) {
|
|
198
|
+
Object.assign(this.headers, headers);
|
|
199
|
+
return this;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
class CloudApi {
|
|
204
|
+
#api;
|
|
205
|
+
#accessToken = null;
|
|
206
|
+
static async fromHost(host) {
|
|
207
|
+
const hostConfig = await GlobalConfig.getHostConfig(host);
|
|
208
|
+
return new CloudApi(hostConfig);
|
|
209
|
+
}
|
|
210
|
+
constructor(hostConfig) {
|
|
211
|
+
const host = akanCloudHost;
|
|
212
|
+
this.#api = new HttpClient(`${host}/api`);
|
|
213
|
+
this.#accessToken = hostConfig.auth?.accessToken ?? null;
|
|
214
|
+
if (this.#accessToken && !GlobalConfig.needRefreshToken(this.#accessToken))
|
|
215
|
+
this.#api.setHeaders({
|
|
216
|
+
Authorization: `Bearer ${this.#accessToken.jwt}`
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
async uploadEnv(devProjectId, file) {
|
|
220
|
+
const formData = new FormData;
|
|
221
|
+
formData.append("devProjectId", devProjectId);
|
|
222
|
+
formData.append("file", file);
|
|
223
|
+
const data = await this.#api.post(`/uploadEnv/${devProjectId}`, formData);
|
|
224
|
+
return data;
|
|
225
|
+
}
|
|
226
|
+
async downloadEnv(devProjectId, localPath) {
|
|
227
|
+
await this.#api.getFile(`/downloadEnv/${devProjectId}`, localPath);
|
|
228
|
+
}
|
|
229
|
+
async getRemoteAuthToken(remoteId) {
|
|
230
|
+
try {
|
|
231
|
+
if (this.#accessToken) {
|
|
232
|
+
if (GlobalConfig.needRefreshToken(this.#accessToken))
|
|
233
|
+
return await this.refreshAuthToken();
|
|
234
|
+
else
|
|
235
|
+
return await this.refreshAuthToken();
|
|
236
|
+
}
|
|
237
|
+
const accessToken = await this.#api.get(`/getRemoteAuthToken/${remoteId}`);
|
|
238
|
+
this.#accessToken = GlobalConfig.toAccessToken(accessToken);
|
|
239
|
+
this.#api.setHeaders({
|
|
240
|
+
Authorization: `Bearer ${this.#accessToken.jwt}`
|
|
241
|
+
});
|
|
242
|
+
return this.#accessToken;
|
|
243
|
+
} catch (_) {
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
async refreshAuthToken() {
|
|
248
|
+
const response = await this.#api.post(`/refreshRemoteAuthToken`, {
|
|
249
|
+
refreshToken: this.#accessToken?.refreshToken
|
|
250
|
+
});
|
|
251
|
+
this.#accessToken = GlobalConfig.toAccessToken(response);
|
|
252
|
+
this.#api.setHeaders({ Authorization: `Bearer ${this.#accessToken.jwt}` });
|
|
253
|
+
return this.#accessToken;
|
|
254
|
+
}
|
|
255
|
+
async getRemoteSelf() {
|
|
256
|
+
try {
|
|
257
|
+
const data = await this.#api.get(`/getRemoteSelf`);
|
|
258
|
+
return data;
|
|
259
|
+
} catch {
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
421
264
|
// pkgs/@akanjs/devkit/spinner.ts
|
|
422
265
|
import ora from "ora";
|
|
423
266
|
|
|
@@ -480,12 +323,18 @@ class Spinner {
|
|
|
480
323
|
|
|
481
324
|
// pkgs/@akanjs/devkit/aiEditor.ts
|
|
482
325
|
var MAX_ASK_TRY = 300;
|
|
483
|
-
var supportedLlmModels = [
|
|
326
|
+
var supportedLlmModels = [
|
|
327
|
+
"deepseek-chat",
|
|
328
|
+
"deepseek-reasoner"
|
|
329
|
+
];
|
|
484
330
|
|
|
485
331
|
class AiSession {
|
|
486
332
|
static #cacheDir = "node_modules/.cache/akan/aiSession";
|
|
487
333
|
static #chat = null;
|
|
488
|
-
static async init({
|
|
334
|
+
static async init({
|
|
335
|
+
temperature = 0,
|
|
336
|
+
useExisting = true
|
|
337
|
+
} = {}) {
|
|
489
338
|
if (useExisting) {
|
|
490
339
|
const llmConfig2 = await AiSession.getLlmConfig();
|
|
491
340
|
if (llmConfig2) {
|
|
@@ -512,22 +361,24 @@ class AiSession {
|
|
|
512
361
|
return AiSession;
|
|
513
362
|
}
|
|
514
363
|
static async getLlmConfig() {
|
|
515
|
-
|
|
516
|
-
return akanConfig.llm ?? null;
|
|
364
|
+
return await GlobalConfig.getLlmConfig();
|
|
517
365
|
}
|
|
518
366
|
static async setLlmConfig(llmConfig) {
|
|
519
|
-
|
|
520
|
-
akanConfig.llm = llmConfig;
|
|
521
|
-
await setAkanGlobalConfig(akanConfig);
|
|
367
|
+
await GlobalConfig.setLlmConfig(llmConfig);
|
|
522
368
|
return AiSession;
|
|
523
369
|
}
|
|
524
370
|
static async#requestLlmConfig() {
|
|
525
|
-
const model = await select({
|
|
371
|
+
const model = await select({
|
|
372
|
+
message: "Select a LLM model",
|
|
373
|
+
choices: supportedLlmModels
|
|
374
|
+
});
|
|
526
375
|
const apiKey = await input({ message: "Enter your API key" });
|
|
527
376
|
return { model, apiKey };
|
|
528
377
|
}
|
|
529
378
|
static async#validateApiKey(modelName, apiKey) {
|
|
530
|
-
const spinner = new Spinner("Validating LLM API key...", {
|
|
379
|
+
const spinner = new Spinner("Validating LLM API key...", {
|
|
380
|
+
prefix: `\uD83E\uDD16akan-editor`
|
|
381
|
+
}).start();
|
|
531
382
|
const chat = new ChatOpenAI({
|
|
532
383
|
modelName,
|
|
533
384
|
temperature: 0,
|
|
@@ -550,7 +401,11 @@ class AiSession {
|
|
|
550
401
|
sessionKey;
|
|
551
402
|
isCacheLoaded = false;
|
|
552
403
|
workspace;
|
|
553
|
-
constructor(type, {
|
|
404
|
+
constructor(type, {
|
|
405
|
+
workspace,
|
|
406
|
+
cacheKey,
|
|
407
|
+
isContinued
|
|
408
|
+
}) {
|
|
554
409
|
this.workspace = workspace;
|
|
555
410
|
this.sessionKey = `${type}${cacheKey ? `-${cacheKey}` : ""}`;
|
|
556
411
|
if (isContinued)
|
|
@@ -625,7 +480,13 @@ class AiSession {
|
|
|
625
480
|
throw new Error("Failed to stream response");
|
|
626
481
|
}
|
|
627
482
|
}
|
|
628
|
-
async edit(question, {
|
|
483
|
+
async edit(question, {
|
|
484
|
+
onChunk,
|
|
485
|
+
onReasoning,
|
|
486
|
+
maxTry = MAX_ASK_TRY,
|
|
487
|
+
validate,
|
|
488
|
+
approve
|
|
489
|
+
} = {}) {
|
|
629
490
|
for (let tryCount = 0;tryCount < maxTry; tryCount++) {
|
|
630
491
|
let response = await this.ask(question, { onChunk, onReasoning });
|
|
631
492
|
if (validate?.length && tryCount === 0) {
|
|
@@ -678,7 +539,9 @@ ${validate.map((v) => `- ${v}`).join(`
|
|
|
678
539
|
async#tryFixTypescripts(writes, executor, options = {}) {
|
|
679
540
|
const MAX_EDIT_TRY = 5;
|
|
680
541
|
for (let tryCount = 0;tryCount < MAX_EDIT_TRY; tryCount++) {
|
|
681
|
-
const loader = new Spinner(`Type checking and linting...`, {
|
|
542
|
+
const loader = new Spinner(`Type checking and linting...`, {
|
|
543
|
+
prefix: `\uD83E\uDD16akan-editor`
|
|
544
|
+
}).start();
|
|
682
545
|
const fileChecks = await Promise.all(writes.map(async ({ filePath }) => {
|
|
683
546
|
const typeCheckResult = executor.typeCheck(filePath);
|
|
684
547
|
const lintResult = await executor.lint(filePath);
|
|
@@ -2486,11 +2349,26 @@ class Executor {
|
|
|
2486
2349
|
});
|
|
2487
2350
|
return new Promise((resolve, reject) => {
|
|
2488
2351
|
proc.on("error", (error) => {
|
|
2489
|
-
reject(new CommandExecutionError({
|
|
2352
|
+
reject(new CommandExecutionError({
|
|
2353
|
+
command,
|
|
2354
|
+
cwd,
|
|
2355
|
+
code: null,
|
|
2356
|
+
signal: null,
|
|
2357
|
+
stdout,
|
|
2358
|
+
stderr,
|
|
2359
|
+
cause: error
|
|
2360
|
+
}));
|
|
2490
2361
|
});
|
|
2491
2362
|
proc.on("exit", (code, signal) => {
|
|
2492
2363
|
if (!!code || signal)
|
|
2493
|
-
reject(new CommandExecutionError({
|
|
2364
|
+
reject(new CommandExecutionError({
|
|
2365
|
+
command,
|
|
2366
|
+
cwd,
|
|
2367
|
+
code,
|
|
2368
|
+
signal,
|
|
2369
|
+
stdout,
|
|
2370
|
+
stderr
|
|
2371
|
+
}));
|
|
2494
2372
|
else
|
|
2495
2373
|
resolve({ code, signal });
|
|
2496
2374
|
});
|
|
@@ -2516,11 +2394,28 @@ class Executor {
|
|
|
2516
2394
|
});
|
|
2517
2395
|
return new Promise((resolve, reject) => {
|
|
2518
2396
|
proc.on("error", (error) => {
|
|
2519
|
-
reject(new CommandExecutionError({
|
|
2397
|
+
reject(new CommandExecutionError({
|
|
2398
|
+
command,
|
|
2399
|
+
args,
|
|
2400
|
+
cwd,
|
|
2401
|
+
code: null,
|
|
2402
|
+
signal: null,
|
|
2403
|
+
stdout,
|
|
2404
|
+
stderr,
|
|
2405
|
+
cause: error
|
|
2406
|
+
}));
|
|
2520
2407
|
});
|
|
2521
2408
|
proc.on("close", (code, signal) => {
|
|
2522
2409
|
if (code !== 0 || signal)
|
|
2523
|
-
reject(new CommandExecutionError({
|
|
2410
|
+
reject(new CommandExecutionError({
|
|
2411
|
+
command,
|
|
2412
|
+
args,
|
|
2413
|
+
cwd,
|
|
2414
|
+
code,
|
|
2415
|
+
signal,
|
|
2416
|
+
stdout,
|
|
2417
|
+
stderr
|
|
2418
|
+
}));
|
|
2524
2419
|
else
|
|
2525
2420
|
resolve(stdout);
|
|
2526
2421
|
});
|
|
@@ -2564,7 +2459,15 @@ class Executor {
|
|
|
2564
2459
|
});
|
|
2565
2460
|
proc.on("exit", (code, signal) => {
|
|
2566
2461
|
if (!!code || signal)
|
|
2567
|
-
reject(new CommandExecutionError({
|
|
2462
|
+
reject(new CommandExecutionError({
|
|
2463
|
+
command: modulePath,
|
|
2464
|
+
args,
|
|
2465
|
+
cwd,
|
|
2466
|
+
code,
|
|
2467
|
+
signal,
|
|
2468
|
+
stdout,
|
|
2469
|
+
stderr
|
|
2470
|
+
}));
|
|
2568
2471
|
else
|
|
2569
2472
|
resolve({ code, signal });
|
|
2570
2473
|
});
|
|
@@ -2711,7 +2614,10 @@ class Executor {
|
|
|
2711
2614
|
const result = {
|
|
2712
2615
|
...extendsTsconfig,
|
|
2713
2616
|
...tsconfig,
|
|
2714
|
-
compilerOptions: {
|
|
2617
|
+
compilerOptions: {
|
|
2618
|
+
...extendsTsconfig.compilerOptions,
|
|
2619
|
+
...tsconfig.compilerOptions
|
|
2620
|
+
}
|
|
2715
2621
|
};
|
|
2716
2622
|
this.#tsconfig = result;
|
|
2717
2623
|
return result;
|
|
@@ -2766,7 +2672,9 @@ class Executor {
|
|
|
2766
2672
|
const convertedTargetPath = Object.entries(dict).reduce((path8, [key, value]) => path8.replace(new RegExp(`__${key}__`, "g"), value), targetPath.slice(0, -9));
|
|
2767
2673
|
const convertedContent = Object.entries(dict).reduce((data, [key, value]) => data.replace(new RegExp(`<%= ${key} %>`, "g"), value), content);
|
|
2768
2674
|
this.logger.verbose(`Apply template ${templatePath} to ${convertedTargetPath}`);
|
|
2769
|
-
return this.writeFile(convertedTargetPath, convertedContent, {
|
|
2675
|
+
return this.writeFile(convertedTargetPath, convertedContent, {
|
|
2676
|
+
overwrite
|
|
2677
|
+
});
|
|
2770
2678
|
} else if (staticTemplateFileExtensions.has(path7.extname(targetPath).toLowerCase())) {
|
|
2771
2679
|
const convertedTargetPath = Object.entries(dict).reduce((path8, [key, value]) => path8.replace(new RegExp(`__${key}__`, "g"), value), targetPath);
|
|
2772
2680
|
const writePath = this.getPath(convertedTargetPath);
|
|
@@ -2792,14 +2700,24 @@ class Executor {
|
|
|
2792
2700
|
const prefixTemplatePath = templatePath;
|
|
2793
2701
|
if ((await stat2(prefixTemplatePath)).isFile()) {
|
|
2794
2702
|
const filename = path7.basename(prefixTemplatePath);
|
|
2795
|
-
const fileContent = await this.#applyTemplateFile({
|
|
2703
|
+
const fileContent = await this.#applyTemplateFile({
|
|
2704
|
+
templatePath: prefixTemplatePath,
|
|
2705
|
+
targetPath: path7.join(basePath2, filename),
|
|
2706
|
+
scanInfo,
|
|
2707
|
+
overwrite
|
|
2708
|
+
}, dict, options);
|
|
2796
2709
|
return fileContent ? [fileContent] : [];
|
|
2797
2710
|
} else {
|
|
2798
2711
|
const subdirs = await readDirEntries(templatePath);
|
|
2799
2712
|
const fileContents = (await Promise.all(subdirs.map(async (subdir) => {
|
|
2800
2713
|
const subpath = path7.join(templatePath, subdir);
|
|
2801
2714
|
if ((await stat2(subpath)).isFile()) {
|
|
2802
|
-
const fileContent = await this.#applyTemplateFile({
|
|
2715
|
+
const fileContent = await this.#applyTemplateFile({
|
|
2716
|
+
templatePath: subpath,
|
|
2717
|
+
targetPath: path7.join(basePath2, subdir),
|
|
2718
|
+
scanInfo,
|
|
2719
|
+
overwrite
|
|
2720
|
+
}, dict, options);
|
|
2803
2721
|
return fileContent ? [fileContent] : [];
|
|
2804
2722
|
} else
|
|
2805
2723
|
return await this._applyTemplate({
|
|
@@ -2850,7 +2768,10 @@ class Executor {
|
|
|
2850
2768
|
async lint(filePath, { fix = false, dryRun = false } = {}) {
|
|
2851
2769
|
const path8 = this.getPath(filePath);
|
|
2852
2770
|
const linter = this.getLinter();
|
|
2853
|
-
const { results, errors, warnings } = await linter.lint(path8, {
|
|
2771
|
+
const { results, errors, warnings } = await linter.lint(path8, {
|
|
2772
|
+
fix,
|
|
2773
|
+
dryRun
|
|
2774
|
+
});
|
|
2854
2775
|
const message = linter.formatLintResults(results);
|
|
2855
2776
|
return { results, message, errors, warnings };
|
|
2856
2777
|
}
|
|
@@ -2876,6 +2797,7 @@ class WorkspaceExecutor extends Executor {
|
|
|
2876
2797
|
const sourceEnv = envPath ? { ...process.env, ...parseEnvFile(envPath) } : process.env;
|
|
2877
2798
|
const appName = sourceEnv.AKAN_PUBLIC_APP_NAME;
|
|
2878
2799
|
const workspaceRoot = sourceEnv.AKAN_WORKSPACE_ROOT;
|
|
2800
|
+
const workspaceId = sourceEnv.AKAN_WORKSPACE_ID;
|
|
2879
2801
|
const repoName = sourceEnv.AKAN_PUBLIC_REPO_NAME;
|
|
2880
2802
|
if (!repoName)
|
|
2881
2803
|
throw new Error("AKAN_PUBLIC_REPO_NAME is not set");
|
|
@@ -2886,7 +2808,15 @@ class WorkspaceExecutor extends Executor {
|
|
|
2886
2808
|
const env = sourceEnv.AKAN_PUBLIC_ENV ?? "debug";
|
|
2887
2809
|
if (!env)
|
|
2888
2810
|
throw new Error("AKAN_PUBLIC_ENV is not set");
|
|
2889
|
-
return { ...appName ? { appName } : {}, workspaceRoot, repoName, serveDomain, env, portOffset };
|
|
2811
|
+
return { ...appName ? { appName } : {}, workspaceRoot, repoName, serveDomain, env, portOffset, workspaceId };
|
|
2812
|
+
}
|
|
2813
|
+
getWorkspaceId({
|
|
2814
|
+
allowEmpty
|
|
2815
|
+
} = {}) {
|
|
2816
|
+
const { workspaceId } = WorkspaceExecutor.getBaseDevEnv();
|
|
2817
|
+
if (!workspaceId && !allowEmpty)
|
|
2818
|
+
throw new Error("Workspace ID is not found");
|
|
2819
|
+
return workspaceId;
|
|
2890
2820
|
}
|
|
2891
2821
|
async scan() {
|
|
2892
2822
|
return await WorkspaceInfo.fromExecutor(this);
|
|
@@ -3090,7 +3020,11 @@ class SysExecutor extends Executor {
|
|
|
3090
3020
|
} = {}) {
|
|
3091
3021
|
if (this.#scanInfo && !refresh)
|
|
3092
3022
|
return this.#scanInfo;
|
|
3093
|
-
const scanInfo = this.type === "app" ? await AppInfo.fromExecutor(this, {
|
|
3023
|
+
const scanInfo = this.type === "app" ? await AppInfo.fromExecutor(this, {
|
|
3024
|
+
refresh
|
|
3025
|
+
}) : await LibInfo.fromExecutor(this, {
|
|
3026
|
+
refresh
|
|
3027
|
+
});
|
|
3094
3028
|
if (write) {
|
|
3095
3029
|
await Promise.all(this.#getScanTemplateTasks(scanInfo));
|
|
3096
3030
|
await this.writeJson(`akan.${this.type}.json`, scanInfo.getScanResult());
|
|
@@ -3199,7 +3133,11 @@ class SysExecutor extends Executor {
|
|
|
3199
3133
|
...Object.fromEntries(Object.entries(options.dict ?? {}).map(([key, value]) => [capitalize(key), capitalize(value)]))
|
|
3200
3134
|
};
|
|
3201
3135
|
const scanInfo = await this.scan();
|
|
3202
|
-
const fileContents = await this._applyTemplate({
|
|
3136
|
+
const fileContents = await this._applyTemplate({
|
|
3137
|
+
...options,
|
|
3138
|
+
scanInfo,
|
|
3139
|
+
dict
|
|
3140
|
+
});
|
|
3203
3141
|
await this.scan();
|
|
3204
3142
|
return fileContents;
|
|
3205
3143
|
}
|
|
@@ -3305,7 +3243,11 @@ class AppExecutor extends SysExecutor {
|
|
|
3305
3243
|
this.#pageKeys = [];
|
|
3306
3244
|
return this.#pageKeys;
|
|
3307
3245
|
}
|
|
3308
|
-
for await (const rel of glob.scan({
|
|
3246
|
+
for await (const rel of glob.scan({
|
|
3247
|
+
cwd: pageDir,
|
|
3248
|
+
absolute: false,
|
|
3249
|
+
onlyFiles: true
|
|
3250
|
+
})) {
|
|
3309
3251
|
const segments = rel.split(path7.sep);
|
|
3310
3252
|
if (segments.some((s) => s === "node_modules"))
|
|
3311
3253
|
continue;
|
|
@@ -3315,7 +3257,10 @@ class AppExecutor extends SysExecutor {
|
|
|
3315
3257
|
if (!isRouteSourceFile(posix))
|
|
3316
3258
|
continue;
|
|
3317
3259
|
const key = `./${posix}`;
|
|
3318
|
-
validateSubRoutePageKey(key, akanConfig2.basePaths, {
|
|
3260
|
+
validateSubRoutePageKey(key, akanConfig2.basePaths, {
|
|
3261
|
+
appName: this.name,
|
|
3262
|
+
filePath: absPath
|
|
3263
|
+
});
|
|
3319
3264
|
const parsed = parseRouteModuleKey(key);
|
|
3320
3265
|
if (parsed.isInternalRootLayout) {
|
|
3321
3266
|
throw new Error(`[route-convention] __root_layout is reserved for Akan.js generated root layout: ${absPath}`);
|
|
@@ -3355,7 +3300,11 @@ class AppExecutor extends SysExecutor {
|
|
|
3355
3300
|
]);
|
|
3356
3301
|
}
|
|
3357
3302
|
async scanSync({ refresh = false, write = true } = {}) {
|
|
3358
|
-
const scanInfo = await this.scan({
|
|
3303
|
+
const scanInfo = await this.scan({
|
|
3304
|
+
refresh,
|
|
3305
|
+
write,
|
|
3306
|
+
writeLib: write
|
|
3307
|
+
});
|
|
3359
3308
|
if (write)
|
|
3360
3309
|
await this.syncAssets(scanInfo.getScanResult().libDeps);
|
|
3361
3310
|
return scanInfo;
|
|
@@ -3419,7 +3368,10 @@ class PkgExecutor extends Executor {
|
|
|
3419
3368
|
return scanInfo;
|
|
3420
3369
|
}
|
|
3421
3370
|
async#getDependencyVersion(rootPackageJson, dep) {
|
|
3422
|
-
const rootDeps = {
|
|
3371
|
+
const rootDeps = {
|
|
3372
|
+
...rootPackageJson.dependencies,
|
|
3373
|
+
...rootPackageJson.devDependencies
|
|
3374
|
+
};
|
|
3423
3375
|
const rootVersion = rootDeps[dep];
|
|
3424
3376
|
if (rootVersion)
|
|
3425
3377
|
return rootVersion;
|
|
@@ -3475,7 +3427,14 @@ class PkgExecutor extends Executor {
|
|
|
3475
3427
|
const distPkgJson = {
|
|
3476
3428
|
...pkgJson,
|
|
3477
3429
|
type: "module",
|
|
3478
|
-
exports: {
|
|
3430
|
+
exports: {
|
|
3431
|
+
...pkgJson.exports,
|
|
3432
|
+
".": {
|
|
3433
|
+
import: "./index.ts",
|
|
3434
|
+
types: "./index.ts",
|
|
3435
|
+
default: "./index.ts"
|
|
3436
|
+
}
|
|
3437
|
+
},
|
|
3479
3438
|
engines: { bun: ">=1.3.13" },
|
|
3480
3439
|
...dependencyMaps
|
|
3481
3440
|
};
|
|
@@ -7769,7 +7728,7 @@ class ApplicationBuildRunner {
|
|
|
7769
7728
|
import { cp, mkdir as mkdir8, rm as rm3 } from "fs/promises";
|
|
7770
7729
|
|
|
7771
7730
|
// pkgs/@akanjs/devkit/uploadRelease.ts
|
|
7772
|
-
import { HttpClient, Logger as Logger10 } from "akanjs/common";
|
|
7731
|
+
import { HttpClient as HttpClient2, Logger as Logger10 } from "akanjs/common";
|
|
7773
7732
|
var spinning = (message) => {
|
|
7774
7733
|
const spinner = new Spinner(message, { prefix: message, enableSpin: true }).start();
|
|
7775
7734
|
return spinner;
|
|
@@ -7784,7 +7743,7 @@ var uploadRelease = async (appName, {
|
|
|
7784
7743
|
}) => {
|
|
7785
7744
|
const logger = new Logger10("uploadRelease");
|
|
7786
7745
|
const basePath2 = local ? "http://localhost:8282/backend" : "https://cloud.akanjs.com/backend";
|
|
7787
|
-
const httpClient = new
|
|
7746
|
+
const httpClient = new HttpClient2(basePath2);
|
|
7788
7747
|
const buildPath = `${workspaceRoot}/releases/builds/${appName}-release.tar.gz`;
|
|
7789
7748
|
const appBuildPath = `${workspaceRoot}/releases/builds/${appName}-appBuild.zip`;
|
|
7790
7749
|
const sourcePath = `${workspaceRoot}/releases/sources/${appName}-source.tar.gz`;
|
|
@@ -9771,77 +9730,6 @@ import { Box as Box2, Newline, Text as Text2, useInput as useInput2 } from "ink"
|
|
|
9771
9730
|
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
9772
9731
|
import { jsxDEV as jsxDEV2, Fragment as Fragment2 } from "react/jsx-dev-runtime";
|
|
9773
9732
|
"use client";
|
|
9774
|
-
// pkgs/@akanjs/devkit/cloud/cloudApi.ts
|
|
9775
|
-
var import_dayjs = __toESM(require_dayjs_min(), 1);
|
|
9776
|
-
|
|
9777
|
-
class HttpClient2 {
|
|
9778
|
-
baseUrl;
|
|
9779
|
-
constructor(baseUrl) {
|
|
9780
|
-
this.baseUrl = baseUrl;
|
|
9781
|
-
}
|
|
9782
|
-
async get(url, { headers } = {}) {
|
|
9783
|
-
const response = await fetch(`${this.baseUrl}${url}`, {
|
|
9784
|
-
headers: { "Content-Type": "application/json", ...headers }
|
|
9785
|
-
});
|
|
9786
|
-
return response.json();
|
|
9787
|
-
}
|
|
9788
|
-
async post(url, data, { headers } = {}) {
|
|
9789
|
-
const isFormData = data instanceof FormData;
|
|
9790
|
-
const response = await fetch(`${this.baseUrl}${url}`, {
|
|
9791
|
-
method: "POST",
|
|
9792
|
-
body: isFormData ? data : JSON.stringify(data),
|
|
9793
|
-
headers: isFormData ? headers : { "Content-Type": "application/json", ...headers }
|
|
9794
|
-
});
|
|
9795
|
-
return response.json();
|
|
9796
|
-
}
|
|
9797
|
-
}
|
|
9798
|
-
|
|
9799
|
-
class CloudApi {
|
|
9800
|
-
api;
|
|
9801
|
-
#accessToken = null;
|
|
9802
|
-
constructor(host, { accessToken } = {}) {
|
|
9803
|
-
this.api = new HttpClient2(`${host}/api`);
|
|
9804
|
-
this.#accessToken = accessToken ?? null;
|
|
9805
|
-
}
|
|
9806
|
-
async uploadEnv(devProjectId, file) {
|
|
9807
|
-
const formData = new FormData;
|
|
9808
|
-
formData.append("devProjectId", devProjectId);
|
|
9809
|
-
formData.append("file", file);
|
|
9810
|
-
const response = await this.api.post(`/uploadEnv/${devProjectId}`, formData);
|
|
9811
|
-
return response.success;
|
|
9812
|
-
}
|
|
9813
|
-
async downloadEnv(devProjectId) {
|
|
9814
|
-
const response = await this.api.get(`/downloadEnv/${devProjectId}`);
|
|
9815
|
-
return response.success;
|
|
9816
|
-
}
|
|
9817
|
-
async getRemoteAuthToken(remoteId) {
|
|
9818
|
-
if (this.#needRefreshToken())
|
|
9819
|
-
return await this.refreshAuthToken();
|
|
9820
|
-
else if (this.#accessToken)
|
|
9821
|
-
return this.#accessToken;
|
|
9822
|
-
const accessToken = await this.api.get(`/getRemoteAuthToken/${remoteId}`);
|
|
9823
|
-
this.#accessToken = {
|
|
9824
|
-
jwt: accessToken.jwt,
|
|
9825
|
-
refreshToken: accessToken.refreshToken,
|
|
9826
|
-
expiresAt: accessToken.expiresAt ? import_dayjs.default(accessToken.expiresAt) : null
|
|
9827
|
-
};
|
|
9828
|
-
return this.#accessToken;
|
|
9829
|
-
}
|
|
9830
|
-
async refreshAuthToken() {
|
|
9831
|
-
const response = await this.api.post(`/refreshRemoteAuthToken`, {
|
|
9832
|
-
refreshToken: this.#accessToken?.refreshToken
|
|
9833
|
-
});
|
|
9834
|
-
this.#accessToken = {
|
|
9835
|
-
jwt: response.jwt,
|
|
9836
|
-
refreshToken: response.refreshToken,
|
|
9837
|
-
expiresAt: response.expiresAt ? import_dayjs.default(response.expiresAt) : null
|
|
9838
|
-
};
|
|
9839
|
-
return this.#accessToken;
|
|
9840
|
-
}
|
|
9841
|
-
#needRefreshToken() {
|
|
9842
|
-
return !!this.#accessToken?.expiresAt?.isBefore(import_dayjs.default().add(1, "hour"));
|
|
9843
|
-
}
|
|
9844
|
-
}
|
|
9845
9733
|
// pkgs/@akanjs/cli/application/application.command.ts
|
|
9846
9734
|
import { select as select6 } from "@inquirer/prompts";
|
|
9847
9735
|
|
|
@@ -10728,7 +10616,7 @@ class PackageScript extends script("package", [PackageRunner]) {
|
|
|
10728
10616
|
|
|
10729
10617
|
// pkgs/@akanjs/cli/cloud/cloud.runner.ts
|
|
10730
10618
|
import path38 from "path";
|
|
10731
|
-
import { confirm as confirm3 } from "@inquirer/prompts";
|
|
10619
|
+
import { confirm as confirm3, input as input5, select as select7 } from "@inquirer/prompts";
|
|
10732
10620
|
import { Logger as Logger15, sleep } from "akanjs/common";
|
|
10733
10621
|
import chalk7 from "chalk";
|
|
10734
10622
|
import * as QRcode from "qrcode";
|
|
@@ -10750,6 +10638,9 @@ async function getLatestPackageVersion(packageName, tag = "latest", registryUrl)
|
|
|
10750
10638
|
}
|
|
10751
10639
|
|
|
10752
10640
|
// pkgs/@akanjs/cli/cloud/cloud.runner.ts
|
|
10641
|
+
var addRemoteEnvServerValue = "__addRemoteEnvServer";
|
|
10642
|
+
var removeRemoteEnvServerValue = "__removeRemoteEnvServer";
|
|
10643
|
+
|
|
10753
10644
|
class CloudRunner extends runner("cloud") {
|
|
10754
10645
|
#akanFrameworkPackages = new Set([
|
|
10755
10646
|
"akanjs",
|
|
@@ -10774,12 +10665,129 @@ class CloudRunner extends runner("cloud") {
|
|
|
10774
10665
|
NPM_CONFIG_REGISTRY: getNpmRegistryUrl(registryUrl)
|
|
10775
10666
|
} : process.env;
|
|
10776
10667
|
}
|
|
10668
|
+
async#addRemoteEnvServer() {
|
|
10669
|
+
const name = (await input5({
|
|
10670
|
+
message: "Remote server name: ",
|
|
10671
|
+
validate: (value) => value.trim() ? true : "Remote server name is required"
|
|
10672
|
+
})).trim();
|
|
10673
|
+
const host = (await input5({
|
|
10674
|
+
message: "Remote server host: ",
|
|
10675
|
+
validate: (value) => value.trim() ? true : "Remote server host is required"
|
|
10676
|
+
})).trim();
|
|
10677
|
+
const username = (await input5({ message: "Remote server username (optional): " })).trim() || undefined;
|
|
10678
|
+
const portInput = (await input5({
|
|
10679
|
+
message: "Remote server SSH port (optional): ",
|
|
10680
|
+
validate: (value) => {
|
|
10681
|
+
const trimmed = value.trim();
|
|
10682
|
+
if (!trimmed)
|
|
10683
|
+
return true;
|
|
10684
|
+
const port = Number(trimmed);
|
|
10685
|
+
return Number.isInteger(port) && port > 0 ? true : "SSH port must be a positive integer";
|
|
10686
|
+
}
|
|
10687
|
+
})).trim();
|
|
10688
|
+
const config = {
|
|
10689
|
+
host,
|
|
10690
|
+
...username ? { username } : {},
|
|
10691
|
+
...portInput ? { port: Number(portInput) } : {}
|
|
10692
|
+
};
|
|
10693
|
+
await GlobalConfig.setRemoteEnvServer(name, config);
|
|
10694
|
+
return { name, config };
|
|
10695
|
+
}
|
|
10696
|
+
async#selectRemoteEnvServer() {
|
|
10697
|
+
const servers = await GlobalConfig.getRemoteEnvServers();
|
|
10698
|
+
const serverEntries = Object.entries(servers).sort(([nameA], [nameB]) => nameA.localeCompare(nameB));
|
|
10699
|
+
if (serverEntries.length === 0) {
|
|
10700
|
+
Logger15.info("No remote env servers configured. Add the first remote server for SCP mode.");
|
|
10701
|
+
return await this.#addRemoteEnvServer();
|
|
10702
|
+
}
|
|
10703
|
+
const selectedName = await select7({
|
|
10704
|
+
message: "Select the remote env server",
|
|
10705
|
+
choices: [
|
|
10706
|
+
...serverEntries.map(([name, config2]) => ({
|
|
10707
|
+
name: `${name} (${config2.username ? `${config2.username}@` : ""}${config2.host}${config2.port ? `:${config2.port}` : ""})`,
|
|
10708
|
+
value: name
|
|
10709
|
+
})),
|
|
10710
|
+
{ name: "Add new remote server", value: addRemoteEnvServerValue },
|
|
10711
|
+
{ name: "Remove remote server", value: removeRemoteEnvServerValue }
|
|
10712
|
+
]
|
|
10713
|
+
});
|
|
10714
|
+
if (selectedName === addRemoteEnvServerValue)
|
|
10715
|
+
return await this.#addRemoteEnvServer();
|
|
10716
|
+
if (selectedName === removeRemoteEnvServerValue) {
|
|
10717
|
+
await this.#removeRemoteEnvServer(serverEntries);
|
|
10718
|
+
return await this.#selectRemoteEnvServer();
|
|
10719
|
+
}
|
|
10720
|
+
const config = servers[selectedName];
|
|
10721
|
+
if (!config)
|
|
10722
|
+
throw new Error(`Remote env server is not found: ${selectedName}`);
|
|
10723
|
+
return { name: selectedName, config };
|
|
10724
|
+
}
|
|
10725
|
+
async#removeRemoteEnvServer(serverEntries) {
|
|
10726
|
+
const selectedName = await select7({
|
|
10727
|
+
message: "Select the remote env server to remove",
|
|
10728
|
+
choices: serverEntries.map(([name, config]) => ({
|
|
10729
|
+
name: `${name} (${config.username ? `${config.username}@` : ""}${config.host}${config.port ? `:${config.port}` : ""})`,
|
|
10730
|
+
value: name
|
|
10731
|
+
}))
|
|
10732
|
+
});
|
|
10733
|
+
const shouldRemove = await confirm3({
|
|
10734
|
+
message: `Remove remote env server "${selectedName}"?`,
|
|
10735
|
+
default: false
|
|
10736
|
+
});
|
|
10737
|
+
if (!shouldRemove)
|
|
10738
|
+
return;
|
|
10739
|
+
await GlobalConfig.removeRemoteEnvServer(selectedName);
|
|
10740
|
+
Logger15.info(`Removed remote env server "${selectedName}"`);
|
|
10741
|
+
}
|
|
10742
|
+
async#getRemoteEnvServerWithUsername() {
|
|
10743
|
+
const remoteServer = await this.#selectRemoteEnvServer();
|
|
10744
|
+
if (remoteServer.config.username)
|
|
10745
|
+
return remoteServer;
|
|
10746
|
+
const username = (await input5({
|
|
10747
|
+
message: `SSH username for ${remoteServer.config.host} (optional): `
|
|
10748
|
+
})).trim();
|
|
10749
|
+
return {
|
|
10750
|
+
...remoteServer,
|
|
10751
|
+
config: {
|
|
10752
|
+
...remoteServer.config,
|
|
10753
|
+
...username ? { username } : {}
|
|
10754
|
+
}
|
|
10755
|
+
};
|
|
10756
|
+
}
|
|
10757
|
+
#getRemoteEnvArchivePath() {
|
|
10758
|
+
return `${this.#getRemoteEnvArchiveDir()}/env.tar`;
|
|
10759
|
+
}
|
|
10760
|
+
#getRemoteEnvArchiveDir() {
|
|
10761
|
+
const { repoName } = WorkspaceExecutor.getBaseDevEnv();
|
|
10762
|
+
return `~/secrets/${repoName}`;
|
|
10763
|
+
}
|
|
10764
|
+
#getScpTarget(config, remotePath) {
|
|
10765
|
+
return `${config.username ? `${config.username}@` : ""}${config.host}:${remotePath}`;
|
|
10766
|
+
}
|
|
10767
|
+
#getSshTarget(config) {
|
|
10768
|
+
return `${config.username ? `${config.username}@` : ""}${config.host}`;
|
|
10769
|
+
}
|
|
10770
|
+
#getScpArgs(config, source, target) {
|
|
10771
|
+
return [
|
|
10772
|
+
...config.port ? ["-P", config.port.toString()] : [],
|
|
10773
|
+
source,
|
|
10774
|
+
target
|
|
10775
|
+
];
|
|
10776
|
+
}
|
|
10777
|
+
#getSshArgs(config, command3) {
|
|
10778
|
+
return [
|
|
10779
|
+
...config.port ? ["-p", config.port.toString()] : [],
|
|
10780
|
+
this.#getSshTarget(config),
|
|
10781
|
+
command3
|
|
10782
|
+
];
|
|
10783
|
+
}
|
|
10777
10784
|
async login() {
|
|
10778
|
-
const config = await getHostConfig();
|
|
10779
|
-
const
|
|
10780
|
-
|
|
10785
|
+
const config = await GlobalConfig.getHostConfig();
|
|
10786
|
+
const cloudApi2 = new CloudApi(config);
|
|
10787
|
+
const self = config.auth ? await cloudApi2.getRemoteSelf() : null;
|
|
10788
|
+
if (self) {
|
|
10781
10789
|
Logger15.rawLog(chalk7.green(`
|
|
10782
|
-
\u2713 Already logged in akan cloud as ${
|
|
10790
|
+
\u2713 Already logged in akan cloud as ${self.nickname}
|
|
10783
10791
|
`));
|
|
10784
10792
|
return true;
|
|
10785
10793
|
}
|
|
@@ -10807,14 +10815,15 @@ ${chalk7.green("\u27A4")} Authentication Required`));
|
|
|
10807
10815
|
Logger15.rawLog(chalk7.dim("Waiting for authentication..."));
|
|
10808
10816
|
const MAX_RETRY = 300;
|
|
10809
10817
|
for (let i = 0;i < MAX_RETRY; i++) {
|
|
10810
|
-
const
|
|
10811
|
-
const
|
|
10812
|
-
|
|
10813
|
-
|
|
10814
|
-
|
|
10818
|
+
const accessToken = await cloudApi2.getRemoteAuthToken(remoteId);
|
|
10819
|
+
const self2 = await cloudApi2.getRemoteSelf();
|
|
10820
|
+
if (accessToken && self2) {
|
|
10821
|
+
await GlobalConfig.setHostConfig(akanCloudHost, {
|
|
10822
|
+
auth: { accessToken, self: self2 }
|
|
10823
|
+
});
|
|
10815
10824
|
Logger15.rawLog(chalk7.green(`\r\u2713 Authentication successful!`));
|
|
10816
10825
|
Logger15.rawLog(chalk7.green.bold(`
|
|
10817
|
-
\u2728 Welcome aboard, ${
|
|
10826
|
+
\u2728 Welcome aboard, ${self2.nickname}!`));
|
|
10818
10827
|
Logger15.rawLog(chalk7.dim(`You're now ready to use Akan CLI!
|
|
10819
10828
|
`));
|
|
10820
10829
|
return true;
|
|
@@ -10824,9 +10833,9 @@ ${chalk7.green("\u27A4")} Authentication Required`));
|
|
|
10824
10833
|
throw new Error(chalk7.red("\u2716 Authentication timed out after 10 minutes. Please try again."));
|
|
10825
10834
|
}
|
|
10826
10835
|
async logout() {
|
|
10827
|
-
const config = await getHostConfig();
|
|
10828
|
-
if (config.auth) {
|
|
10829
|
-
setHostConfig(akanCloudHost, {});
|
|
10836
|
+
const config = await GlobalConfig.getHostConfig();
|
|
10837
|
+
if (config.auth?.self) {
|
|
10838
|
+
await GlobalConfig.setHostConfig(akanCloudHost, {});
|
|
10830
10839
|
Logger15.rawLog(chalk7.magenta.bold(`
|
|
10831
10840
|
\uD83D\uDC4B Goodbye, ${config.auth.self.nickname}!`));
|
|
10832
10841
|
Logger15.rawLog(chalk7.dim(`\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
@@ -10961,20 +10970,78 @@ ${chalk7.green("\u27A4")} Authentication Required`));
|
|
|
10961
10970
|
}
|
|
10962
10971
|
return normalized;
|
|
10963
10972
|
}
|
|
10964
|
-
async downloadEnv(workspace) {
|
|
10965
|
-
const
|
|
10966
|
-
|
|
10967
|
-
|
|
10968
|
-
|
|
10969
|
-
|
|
10970
|
-
|
|
10971
|
-
|
|
10973
|
+
async downloadEnv(cloudApi2, workspace, workspaceId) {
|
|
10974
|
+
const envArchivePath = "local/env.tar";
|
|
10975
|
+
await workspace.mkdir("local");
|
|
10976
|
+
await workspace.remove(envArchivePath);
|
|
10977
|
+
await cloudApi2.downloadEnv(workspaceId, path38.join(workspace.workspaceRoot, envArchivePath));
|
|
10978
|
+
await workspace.spawn("tar", ["-xf", envArchivePath], {
|
|
10979
|
+
cwd: workspace.workspaceRoot
|
|
10980
|
+
});
|
|
10981
|
+
await workspace.remove(envArchivePath);
|
|
10982
|
+
}
|
|
10983
|
+
async uploadEnv(cloudApi2, workspaceId, filePath) {
|
|
10984
|
+
const file = new File([Bun.file(filePath)], path38.basename(filePath));
|
|
10985
|
+
await cloudApi2.uploadEnv(workspaceId, file);
|
|
10986
|
+
}
|
|
10987
|
+
async downloadEnvByScp(workspace) {
|
|
10988
|
+
const envArchivePath = "local/env.tar";
|
|
10989
|
+
const remoteServer = await this.#getRemoteEnvServerWithUsername();
|
|
10990
|
+
const remoteArchivePath = this.#getRemoteEnvArchivePath();
|
|
10991
|
+
const remoteTarget = this.#getScpTarget(remoteServer.config, remoteArchivePath);
|
|
10992
|
+
await workspace.mkdir("local");
|
|
10993
|
+
await workspace.remove(envArchivePath);
|
|
10994
|
+
try {
|
|
10995
|
+
Logger15.info(`Downloading env archive from remote server "${remoteServer.name}"...`);
|
|
10996
|
+
await workspace.spawn("scp", this.#getScpArgs(remoteServer.config, remoteTarget, envArchivePath), {
|
|
10997
|
+
cwd: workspace.workspaceRoot,
|
|
10998
|
+
stdio: "inherit"
|
|
10999
|
+
});
|
|
11000
|
+
await workspace.spawn("tar", ["-xf", envArchivePath], {
|
|
11001
|
+
cwd: workspace.workspaceRoot
|
|
11002
|
+
});
|
|
11003
|
+
await workspace.remove(envArchivePath);
|
|
11004
|
+
} catch (error) {
|
|
11005
|
+
throw new Error(`Failed to download env archive from remote server "${remoteServer.name}"`, { cause: error });
|
|
11006
|
+
}
|
|
11007
|
+
}
|
|
11008
|
+
async uploadEnvByScp(workspace, filePath) {
|
|
11009
|
+
const remoteServer = await this.#getRemoteEnvServerWithUsername();
|
|
11010
|
+
const remoteArchiveDir = this.#getRemoteEnvArchiveDir();
|
|
11011
|
+
const remoteArchivePath = this.#getRemoteEnvArchivePath();
|
|
11012
|
+
const remoteTarget = this.#getScpTarget(remoteServer.config, remoteArchivePath);
|
|
11013
|
+
try {
|
|
11014
|
+
await workspace.spawn("ssh", this.#getSshArgs(remoteServer.config, `mkdir -p ${remoteArchiveDir}`), {
|
|
11015
|
+
cwd: workspace.workspaceRoot,
|
|
11016
|
+
stdio: "inherit"
|
|
11017
|
+
});
|
|
11018
|
+
Logger15.info(`Uploading env archive to remote server "${remoteServer.name}"...`);
|
|
11019
|
+
await workspace.spawn("scp", this.#getScpArgs(remoteServer.config, filePath, remoteTarget), {
|
|
11020
|
+
cwd: workspace.workspaceRoot,
|
|
11021
|
+
stdio: "inherit"
|
|
11022
|
+
});
|
|
11023
|
+
} catch (error) {
|
|
11024
|
+
throw new Error(`Failed to upload env archive to remote server "${remoteServer.name}"`, { cause: error });
|
|
11025
|
+
}
|
|
11026
|
+
}
|
|
11027
|
+
async gatherEnvFiles(workspace) {
|
|
11028
|
+
const envFilePattern = /^env\.(client|server)\.(?!(type|example)\.ts$).+\.ts$/;
|
|
11029
|
+
const [appNames, libNames] = await workspace.getExecs();
|
|
11030
|
+
const envDirs = [
|
|
11031
|
+
...appNames.map((appName) => `apps/${appName}/env`),
|
|
11032
|
+
...libNames.map((libName) => `libs/${libName}/env`)
|
|
11033
|
+
];
|
|
11034
|
+
const envFilePaths = (await Promise.all(envDirs.map(async (envDir) => (await workspace.readdir(envDir)).filter((fileName) => envFilePattern.test(fileName)).map((fileName) => `${envDir}/${fileName}`)))).flat().sort();
|
|
11035
|
+
await workspace.mkdir("local");
|
|
11036
|
+
await workspace.remove("local/env.tar");
|
|
11037
|
+
if (envFilePaths.length === 0)
|
|
11038
|
+
throw new Error("No environment files found to archive");
|
|
11039
|
+
await workspace.spawn("tar", ["-cf", "local/env.tar", ...envFilePaths], {
|
|
11040
|
+
cwd: workspace.workspaceRoot
|
|
10972
11041
|
});
|
|
10973
|
-
|
|
10974
|
-
|
|
10975
|
-
Logger15.info(`Environment variables: ${JSON.stringify(env.env, null, 2)}`);
|
|
11042
|
+
Logger15.info(`Archived ${envFilePaths.length} environment files to local/env.tar`);
|
|
11043
|
+
return { files: envFilePaths, path: "local/env.tar" };
|
|
10976
11044
|
}
|
|
10977
|
-
async uploadEnv(workspace) {}
|
|
10978
11045
|
}
|
|
10979
11046
|
|
|
10980
11047
|
// pkgs/@akanjs/cli/cloud/cloud.script.ts
|
|
@@ -11000,10 +11067,23 @@ class CloudScript extends script("cloud", [
|
|
|
11000
11067
|
await session.ask(question);
|
|
11001
11068
|
}
|
|
11002
11069
|
async downloadEnv(workspace) {
|
|
11003
|
-
|
|
11070
|
+
const workspaceId = workspace.getWorkspaceId({ allowEmpty: true });
|
|
11071
|
+
if (workspaceId) {
|
|
11072
|
+
const cloudApi2 = await CloudApi.fromHost();
|
|
11073
|
+
await this.cloudRunner.downloadEnv(cloudApi2, workspace, workspaceId);
|
|
11074
|
+
return;
|
|
11075
|
+
}
|
|
11076
|
+
await this.cloudRunner.downloadEnvByScp(workspace);
|
|
11004
11077
|
}
|
|
11005
11078
|
async uploadEnv(workspace) {
|
|
11006
|
-
|
|
11079
|
+
const workspaceId = workspace.getWorkspaceId({ allowEmpty: true });
|
|
11080
|
+
const { path: path39 } = await this.cloudRunner.gatherEnvFiles(workspace);
|
|
11081
|
+
if (workspaceId) {
|
|
11082
|
+
const cloudApi2 = await CloudApi.fromHost();
|
|
11083
|
+
await this.cloudRunner.uploadEnv(cloudApi2, workspaceId, path39);
|
|
11084
|
+
return;
|
|
11085
|
+
}
|
|
11086
|
+
await this.cloudRunner.uploadEnvByScp(workspace, path39);
|
|
11007
11087
|
}
|
|
11008
11088
|
async deployAkan(workspace, { test = true, registryUrl } = {}) {
|
|
11009
11089
|
const akanPkgs = await this.cloudRunner.getAkanPkgs(workspace);
|
|
@@ -11042,7 +11122,10 @@ class CloudCommand extends command("cloud", [CloudScript], ({ public: target })
|
|
|
11042
11122
|
resetLlm: target({ desc: "Reset LLM configuration to default" }).with(Workspace).exec(function(workspace) {
|
|
11043
11123
|
this.cloudScript.resetLlm(workspace);
|
|
11044
11124
|
}),
|
|
11045
|
-
ask: target({
|
|
11125
|
+
ask: target({
|
|
11126
|
+
devOnly: true,
|
|
11127
|
+
desc: "Ask AI assistant a question about your project"
|
|
11128
|
+
}).option("question", String, { ask: "question to ask" }).with(Workspace).exec(async function(question, workspace) {
|
|
11046
11129
|
await this.cloudScript.ask(question, workspace);
|
|
11047
11130
|
}),
|
|
11048
11131
|
deployAkan: target({
|
|
@@ -11077,10 +11160,14 @@ class CloudCommand extends command("cloud", [CloudScript], ({ public: target })
|
|
|
11077
11160
|
registryUrl: resolveRegistryUrl(registry)
|
|
11078
11161
|
});
|
|
11079
11162
|
}),
|
|
11080
|
-
downloadEnv: target({
|
|
11163
|
+
downloadEnv: target({
|
|
11164
|
+
desc: "Download environment variables from cloud or SCP server"
|
|
11165
|
+
}).with(Workspace).exec(async function(workspace) {
|
|
11081
11166
|
await this.cloudScript.downloadEnv(workspace);
|
|
11082
11167
|
}),
|
|
11083
|
-
uploadEnv: target({
|
|
11168
|
+
uploadEnv: target({
|
|
11169
|
+
desc: "Upload environment variables to cloud or SCP server"
|
|
11170
|
+
}).with(Workspace).exec(async function(workspace) {
|
|
11084
11171
|
await this.cloudScript.uploadEnv(workspace);
|
|
11085
11172
|
})
|
|
11086
11173
|
})) {
|
|
@@ -11554,7 +11641,7 @@ class LocalRegistryCommand extends command("local-registry", [LocalRegistryScrip
|
|
|
11554
11641
|
import { lowerlize } from "akanjs/common";
|
|
11555
11642
|
|
|
11556
11643
|
// pkgs/@akanjs/cli/module/module.script.ts
|
|
11557
|
-
import { input as
|
|
11644
|
+
import { input as input6 } from "@inquirer/prompts";
|
|
11558
11645
|
import { capitalize as capitalize6, randomPicks as randomPicks2 } from "akanjs/common";
|
|
11559
11646
|
|
|
11560
11647
|
// pkgs/@akanjs/cli/page/page.runner.ts
|
|
@@ -11981,8 +12068,8 @@ class ModuleScript extends script("module", [ModuleRunner, PageScript]) {
|
|
|
11981
12068
|
const { constant, dictionary } = await this.moduleRunner.createModuleTemplate(executor);
|
|
11982
12069
|
if (page && sys3.type === "app")
|
|
11983
12070
|
await this.pageScript.createCrudPage(executor, { app: sys3, basePath: null, single: false });
|
|
11984
|
-
const modelDesc = description ?? await
|
|
11985
|
-
const modelSchemaDesign = schemaDescription ?? await
|
|
12071
|
+
const modelDesc = description ?? await input6({ message: "description of module" });
|
|
12072
|
+
const modelSchemaDesign = schemaDescription ?? await input6({ message: "schema description of module" });
|
|
11986
12073
|
const config = await sys3.getConfig();
|
|
11987
12074
|
const moduleRequest = new ModuleRequest({ sysType: sys3.type, sysName: sys3.name, modelName: name, config });
|
|
11988
12075
|
const constantRequestPrompt = await moduleRequest.requestModelConstant({
|
|
@@ -12153,7 +12240,7 @@ class PageCommand extends command("page", [PageScript], ({ public: target }) =>
|
|
|
12153
12240
|
import { lowerlize as lowerlize2 } from "akanjs/common";
|
|
12154
12241
|
|
|
12155
12242
|
// pkgs/@akanjs/cli/scalar/scalar.prompt.ts
|
|
12156
|
-
import { input as
|
|
12243
|
+
import { input as input7 } from "@inquirer/prompts";
|
|
12157
12244
|
class ScalarPrompt extends Prompter {
|
|
12158
12245
|
sys;
|
|
12159
12246
|
name;
|
|
@@ -12163,13 +12250,13 @@ class ScalarPrompt extends Prompter {
|
|
|
12163
12250
|
this.name = name;
|
|
12164
12251
|
}
|
|
12165
12252
|
async requestUpdateConstant() {
|
|
12166
|
-
const request = await
|
|
12253
|
+
const request = await input7({ message: `What do you want to change?` });
|
|
12167
12254
|
return { request, validate: undefined };
|
|
12168
12255
|
}
|
|
12169
12256
|
async requestCreateConstant() {
|
|
12170
12257
|
const constantFiles = await this.sys.getConstantFilesWithLibs();
|
|
12171
|
-
const description = await
|
|
12172
|
-
const schemaDescription = await
|
|
12258
|
+
const description = await input7({ message: "description of scalar" });
|
|
12259
|
+
const schemaDescription = await input7({ message: "schema description of scalar" });
|
|
12173
12260
|
await this.sys.applyTemplate({
|
|
12174
12261
|
basePath: "./lib/__scalar",
|
|
12175
12262
|
template: "__scalar",
|