@lotics/app-sdk 0.124.8 → 0.124.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-YONY7UPS.js → chunk-BNJZBF6D.js} +3 -3
- package/dist/index.js +147 -91
- package/dist/router.d.ts +1 -1
- package/dist/router.js +1 -1
- package/docs/ai.md +1 -1
- package/docs/data_fetching.md +2 -2
- package/docs/members_and_options.md +2 -2
- package/docs/mutations.md +7 -7
- package/docs/recipes.md +1 -5
- package/docs/runtime.md +1 -1
- package/docs/workflows.md +12 -12
- package/package.json +14 -12
|
@@ -193,7 +193,7 @@ function searchWords(value) {
|
|
|
193
193
|
return (typeof value === "string" ? [value] : value).map((word) => word.trim()).filter((word) => foldSearchText(word).trim() !== "");
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
-
//
|
|
196
|
+
// ../shared/node_modules/nanoid/index.browser.js
|
|
197
197
|
var random = (bytes) => crypto.getRandomValues(new Uint8Array(bytes));
|
|
198
198
|
var customRandom = (alphabet, defaultSize, getRandom) => {
|
|
199
199
|
let safeByteCutoff = 256 - 256 % alphabet.length;
|
|
@@ -204,7 +204,7 @@ var customRandom = (alphabet, defaultSize, getRandom) => {
|
|
|
204
204
|
let id = "";
|
|
205
205
|
while (true) {
|
|
206
206
|
let bytes = getRandom(size);
|
|
207
|
-
let j = size;
|
|
207
|
+
let j = size |= 0;
|
|
208
208
|
while (j--) {
|
|
209
209
|
id += alphabet[bytes[j] & mask];
|
|
210
210
|
if (id.length >= size) return id;
|
|
@@ -212,10 +212,10 @@ var customRandom = (alphabet, defaultSize, getRandom) => {
|
|
|
212
212
|
}
|
|
213
213
|
};
|
|
214
214
|
}
|
|
215
|
-
let step = Math.ceil(1.6 * 256 * defaultSize / safeByteCutoff);
|
|
216
215
|
return (size = defaultSize) => {
|
|
217
216
|
if (!size) return "";
|
|
218
217
|
let id = "";
|
|
218
|
+
let step = Math.ceil(1.6 * 256 * size / safeByteCutoff);
|
|
219
219
|
while (true) {
|
|
220
220
|
let bytes = getRandom(step);
|
|
221
221
|
let j = step;
|
package/dist/index.js
CHANGED
|
@@ -49,7 +49,7 @@ import {
|
|
|
49
49
|
subtractDecimal,
|
|
50
50
|
sumDecimal,
|
|
51
51
|
urlParam
|
|
52
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-BNJZBF6D.js";
|
|
53
53
|
|
|
54
54
|
// src/mount.tsx
|
|
55
55
|
import { createRoot } from "react-dom/client";
|
|
@@ -2724,36 +2724,64 @@ function isUsableLocale(locale) {
|
|
|
2724
2724
|
}
|
|
2725
2725
|
}
|
|
2726
2726
|
|
|
2727
|
+
// ../../node_modules/@noble/hashes/_u64.js
|
|
2728
|
+
var fromNumH = (n) => n / 2 ** 32 | 0;
|
|
2729
|
+
var fromNumL = (n) => n >>> 0;
|
|
2730
|
+
function setU64FromNum(view, byteOffset, n, isLE) {
|
|
2731
|
+
const h = fromNumH(n);
|
|
2732
|
+
const l = fromNumL(n);
|
|
2733
|
+
view.setUint32(byteOffset, isLE ? l : h, isLE);
|
|
2734
|
+
view.setUint32(byteOffset + 4, isLE ? h : l, isLE);
|
|
2735
|
+
}
|
|
2736
|
+
|
|
2727
2737
|
// ../../node_modules/@noble/hashes/utils.js
|
|
2728
2738
|
function isBytes(a) {
|
|
2729
2739
|
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array" && "BYTES_PER_ELEMENT" in a && a.BYTES_PER_ELEMENT === 1;
|
|
2730
2740
|
}
|
|
2741
|
+
var atitle = (title) => title ? `"${title}" ` : "";
|
|
2742
|
+
function anumber(n, title = "") {
|
|
2743
|
+
if (typeof n !== "number")
|
|
2744
|
+
throw new TypeError(atitle(title) + "expected number, got " + typeof n);
|
|
2745
|
+
if (!Number.isSafeInteger(n) || n < 0)
|
|
2746
|
+
throw new RangeError(atitle(title) + "expected integer >= 0, got " + n);
|
|
2747
|
+
return n;
|
|
2748
|
+
}
|
|
2731
2749
|
function abytes(value, length2, title = "") {
|
|
2750
|
+
if (isBytes(value) && (length2 === void 0 || value.length === length2))
|
|
2751
|
+
return value;
|
|
2752
|
+
if (length2 !== void 0)
|
|
2753
|
+
anumber(length2, "length");
|
|
2732
2754
|
const bytes = isBytes(value);
|
|
2733
|
-
const
|
|
2734
|
-
const
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
throw new
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2755
|
+
const ofLen = length2 !== void 0 ? ` of length ${length2}` : "";
|
|
2756
|
+
const got = bytes ? `length=${value.length}` : `type=${typeof value}`;
|
|
2757
|
+
const message2 = atitle(title) + "expected Uint8Array" + ofLen + ", got " + got;
|
|
2758
|
+
if (!bytes)
|
|
2759
|
+
throw new TypeError(message2);
|
|
2760
|
+
throw new RangeError(message2);
|
|
2761
|
+
}
|
|
2762
|
+
var aobject = (value, label) => {
|
|
2763
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
2764
|
+
throw new TypeError((label === "object" ? "" : `"${label}" `) + "expected object, got type=" + typeof value);
|
|
2765
|
+
};
|
|
2766
|
+
var aopts = (value, label) => {
|
|
2767
|
+
aobject(value, label);
|
|
2768
|
+
const proto = Object.getPrototypeOf(value);
|
|
2769
|
+
if (proto !== Object.prototype && proto !== null)
|
|
2770
|
+
throw new TypeError(`"${label}" expected plain object`);
|
|
2771
|
+
if (Object.hasOwn(value, "__proto__"))
|
|
2772
|
+
throw new TypeError(`"${label}.__proto__" is not allowed`);
|
|
2773
|
+
};
|
|
2746
2774
|
function aexists(instance, checkFinished = true) {
|
|
2747
2775
|
if (instance.destroyed)
|
|
2748
|
-
throw new Error("
|
|
2776
|
+
throw new Error("hash was destroyed");
|
|
2749
2777
|
if (checkFinished && instance.finished)
|
|
2750
|
-
throw new Error("
|
|
2778
|
+
throw new Error("digest() was already called");
|
|
2751
2779
|
}
|
|
2752
2780
|
function aoutput(out, instance) {
|
|
2753
|
-
abytes(out, void 0, "
|
|
2781
|
+
abytes(out, void 0, "output");
|
|
2754
2782
|
const min3 = instance.outputLen;
|
|
2755
|
-
if (out.length
|
|
2756
|
-
throw new RangeError('"
|
|
2783
|
+
if (!(out.length >= min3)) {
|
|
2784
|
+
throw new RangeError('"output" expected length >= ' + min3);
|
|
2757
2785
|
}
|
|
2758
2786
|
}
|
|
2759
2787
|
function clean(...arrays) {
|
|
@@ -2782,15 +2810,8 @@ function bytesToHex(bytes) {
|
|
|
2782
2810
|
}
|
|
2783
2811
|
return hex;
|
|
2784
2812
|
}
|
|
2785
|
-
var asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 };
|
|
2786
2813
|
function asciiToBase16(ch) {
|
|
2787
|
-
|
|
2788
|
-
return ch - asciis._0;
|
|
2789
|
-
if (ch >= asciis.A && ch <= asciis.F)
|
|
2790
|
-
return ch - (asciis.A - 10);
|
|
2791
|
-
if (ch >= asciis.a && ch <= asciis.f)
|
|
2792
|
-
return ch - (asciis.a - 10);
|
|
2793
|
-
return;
|
|
2814
|
+
return ch >= 48 && ch <= 57 ? ch - 48 : ch >= 65 && ch <= 70 ? ch - (65 - 10) : ch >= 97 && ch <= 102 ? ch - (97 - 10) : void 0;
|
|
2794
2815
|
}
|
|
2795
2816
|
function hexToBytes(hex) {
|
|
2796
2817
|
if (typeof hex !== "string")
|
|
@@ -2823,7 +2844,12 @@ function hexToBytes(hex) {
|
|
|
2823
2844
|
function utf8ToBytes(str) {
|
|
2824
2845
|
if (typeof str !== "string")
|
|
2825
2846
|
throw new TypeError("string expected");
|
|
2826
|
-
|
|
2847
|
+
const encoded = new TextEncoder().encode(str);
|
|
2848
|
+
try {
|
|
2849
|
+
return new Uint8Array(encoded);
|
|
2850
|
+
} finally {
|
|
2851
|
+
clean(encoded);
|
|
2852
|
+
}
|
|
2827
2853
|
}
|
|
2828
2854
|
function concatBytes(...arrays) {
|
|
2829
2855
|
let sum2 = 0;
|
|
@@ -2840,7 +2866,17 @@ function concatBytes(...arrays) {
|
|
|
2840
2866
|
}
|
|
2841
2867
|
return res;
|
|
2842
2868
|
}
|
|
2869
|
+
function checkOpts(defaults, opts, title = "opts") {
|
|
2870
|
+
aopts(defaults, "defaults");
|
|
2871
|
+
if (opts !== void 0)
|
|
2872
|
+
aopts(opts, title);
|
|
2873
|
+
const merged = Object.assign(/* @__PURE__ */ Object.create(null), defaults, opts);
|
|
2874
|
+
return merged;
|
|
2875
|
+
}
|
|
2843
2876
|
function createHasher(hashCons, info = {}) {
|
|
2877
|
+
if (typeof hashCons !== "function")
|
|
2878
|
+
throw new TypeError('"hashCons" expected function, got type=' + typeof hashCons);
|
|
2879
|
+
info = checkOpts({}, info, "info");
|
|
2844
2880
|
const hashC = (msg, opts) => hashCons(opts).update(msg).digest();
|
|
2845
2881
|
const tmp = hashCons(void 0);
|
|
2846
2882
|
hashC.outputLen = tmp.outputLen;
|
|
@@ -2884,24 +2920,28 @@ var HashMD = class {
|
|
|
2884
2920
|
abytes(data);
|
|
2885
2921
|
const { view, buffer, blockLen } = this;
|
|
2886
2922
|
const len = data.length;
|
|
2923
|
+
let processed = false;
|
|
2887
2924
|
for (let pos = 0; pos < len; ) {
|
|
2888
2925
|
const take = Math.min(blockLen - this.pos, len - pos);
|
|
2889
2926
|
if (take === blockLen) {
|
|
2890
2927
|
const dataView = createView(data);
|
|
2891
2928
|
for (; blockLen <= len - pos; pos += blockLen)
|
|
2892
2929
|
this.process(dataView, pos);
|
|
2930
|
+
processed = true;
|
|
2893
2931
|
continue;
|
|
2894
2932
|
}
|
|
2895
|
-
buffer.set(data.subarray(pos, pos + take), this.pos);
|
|
2933
|
+
buffer.set(pos === 0 && take === len ? data : data.subarray(pos, pos + take), this.pos);
|
|
2896
2934
|
this.pos += take;
|
|
2897
2935
|
pos += take;
|
|
2898
2936
|
if (this.pos === blockLen) {
|
|
2899
2937
|
this.process(view, 0);
|
|
2900
2938
|
this.pos = 0;
|
|
2939
|
+
processed = true;
|
|
2901
2940
|
}
|
|
2902
2941
|
}
|
|
2903
2942
|
this.length += data.length;
|
|
2904
|
-
|
|
2943
|
+
if (processed)
|
|
2944
|
+
this.roundClean();
|
|
2905
2945
|
return this;
|
|
2906
2946
|
}
|
|
2907
2947
|
digestInto(out) {
|
|
@@ -2911,23 +2951,20 @@ var HashMD = class {
|
|
|
2911
2951
|
const { buffer, view, blockLen, isLE } = this;
|
|
2912
2952
|
let { pos } = this;
|
|
2913
2953
|
buffer[pos++] = 128;
|
|
2914
|
-
|
|
2954
|
+
buffer.fill(0, pos);
|
|
2915
2955
|
if (this.padOffset > blockLen - pos) {
|
|
2916
2956
|
this.process(view, 0);
|
|
2917
|
-
|
|
2957
|
+
buffer.fill(0);
|
|
2918
2958
|
}
|
|
2919
|
-
|
|
2920
|
-
buffer[i] = 0;
|
|
2921
|
-
view.setBigUint64(blockLen - 8, BigInt(this.length * 8), isLE);
|
|
2959
|
+
setU64FromNum(view, blockLen - 8, this.length * 8, isLE);
|
|
2922
2960
|
this.process(view, 0);
|
|
2923
|
-
|
|
2961
|
+
this.roundClean();
|
|
2962
|
+
const oview = out === buffer ? view : createView(out);
|
|
2924
2963
|
const len = this.outputLen;
|
|
2925
|
-
if (len % 4)
|
|
2926
|
-
throw new Error("_sha2: outputLen must be aligned to 32bit");
|
|
2927
2964
|
const outLen = len / 4;
|
|
2928
2965
|
const state = this.get();
|
|
2929
|
-
if (outLen > state.length)
|
|
2930
|
-
throw new Error("
|
|
2966
|
+
if (len % 4 || outLen > state.length)
|
|
2967
|
+
throw new Error("invalid outputLen");
|
|
2931
2968
|
for (let i = 0; i < outLen; i++)
|
|
2932
2969
|
oview.setUint32(4 * i, state[i], isLE);
|
|
2933
2970
|
}
|
|
@@ -2938,15 +2975,13 @@ var HashMD = class {
|
|
|
2938
2975
|
this.destroy();
|
|
2939
2976
|
return res;
|
|
2940
2977
|
}
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
to.set(...this.get());
|
|
2944
|
-
const { blockLen, buffer, length: length2, finished, destroyed, pos } = this;
|
|
2978
|
+
_cloneIntoMeta(to) {
|
|
2979
|
+
const { buffer, length: length2, finished, destroyed, pos } = this;
|
|
2945
2980
|
to.destroyed = destroyed;
|
|
2946
2981
|
to.finished = finished;
|
|
2947
2982
|
to.length = length2;
|
|
2948
2983
|
to.pos = pos;
|
|
2949
|
-
if (
|
|
2984
|
+
if (pos)
|
|
2950
2985
|
to.buffer.set(buffer);
|
|
2951
2986
|
return to;
|
|
2952
2987
|
}
|
|
@@ -2984,6 +3019,10 @@ var _SHA1 = class extends HashMD {
|
|
|
2984
3019
|
this.D = D | 0;
|
|
2985
3020
|
this.E = E | 0;
|
|
2986
3021
|
}
|
|
3022
|
+
_cloneInto(to) {
|
|
3023
|
+
(to ||= new this.constructor()).set(...this.get());
|
|
3024
|
+
return this._cloneIntoMeta(to);
|
|
3025
|
+
}
|
|
2987
3026
|
process(view, offset) {
|
|
2988
3027
|
for (let i = 0; i < 16; i++, offset += 4)
|
|
2989
3028
|
SHA1_W[i] = view.getUint32(offset, false);
|
|
@@ -5832,8 +5871,7 @@ var TZDateMini = class _TZDateMini extends Date {
|
|
|
5832
5871
|
this.setTime(+args[0]);
|
|
5833
5872
|
} else {
|
|
5834
5873
|
this.setTime(+new Date(...args));
|
|
5835
|
-
adjustToSystemTZ(this,
|
|
5836
|
-
syncToInternal(this);
|
|
5874
|
+
adjustToSystemTZ(this, args);
|
|
5837
5875
|
}
|
|
5838
5876
|
}
|
|
5839
5877
|
}
|
|
@@ -5851,7 +5889,7 @@ var TZDateMini = class _TZDateMini extends Date {
|
|
|
5851
5889
|
}
|
|
5852
5890
|
//#endregion
|
|
5853
5891
|
//#region time
|
|
5854
|
-
setTime(
|
|
5892
|
+
setTime(_time) {
|
|
5855
5893
|
Date.prototype.setTime.apply(this, arguments);
|
|
5856
5894
|
syncToInternal(this);
|
|
5857
5895
|
return +this;
|
|
@@ -5887,49 +5925,79 @@ Object.getOwnPropertyNames(Date.prototype).forEach((method) => {
|
|
|
5887
5925
|
});
|
|
5888
5926
|
function syncToInternal(date2) {
|
|
5889
5927
|
date2.internal.setTime(+date2);
|
|
5890
|
-
date2.internal.setUTCSeconds(date2.internal.getUTCSeconds() -
|
|
5928
|
+
date2.internal.setUTCSeconds(date2.internal.getUTCSeconds() - // Round after converting minutes to seconds to avoid fractional offset
|
|
5929
|
+
// precision errors from historical offsets.
|
|
5930
|
+
Math.round(-tzOffset(date2.timeZone, date2) * 60));
|
|
5891
5931
|
}
|
|
5892
5932
|
function syncFromInternal(date2) {
|
|
5893
5933
|
Date.prototype.setFullYear.call(date2, date2.internal.getUTCFullYear(), date2.internal.getUTCMonth(), date2.internal.getUTCDate());
|
|
5894
5934
|
Date.prototype.setHours.call(date2, date2.internal.getUTCHours(), date2.internal.getUTCMinutes(), date2.internal.getUTCSeconds(), date2.internal.getUTCMilliseconds());
|
|
5895
5935
|
adjustToSystemTZ(date2);
|
|
5896
5936
|
}
|
|
5897
|
-
function adjustToSystemTZ(date2) {
|
|
5898
|
-
const
|
|
5899
|
-
const
|
|
5937
|
+
function adjustToSystemTZ(date2, constructorArgs) {
|
|
5938
|
+
const expectedInternalTime = Array.isArray(constructorArgs) ? constructorArgsToInternalTime(constructorArgs) : +date2.internal;
|
|
5939
|
+
const offsetWithSeconds = tzOffset(date2.timeZone, date2);
|
|
5940
|
+
const offset = offsetWithSeconds > 0 ? Math.floor(offsetWithSeconds) : Math.ceil(offsetWithSeconds);
|
|
5900
5941
|
const prevHour = /* @__PURE__ */ new Date(+date2);
|
|
5901
5942
|
prevHour.setUTCHours(prevHour.getUTCHours() - 1);
|
|
5902
5943
|
const systemOffset = -(/* @__PURE__ */ new Date(+date2)).getTimezoneOffset();
|
|
5903
5944
|
const prevHourSystemOffset = -(/* @__PURE__ */ new Date(+prevHour)).getTimezoneOffset();
|
|
5904
5945
|
const systemDSTChange = systemOffset - prevHourSystemOffset;
|
|
5905
|
-
|
|
5906
|
-
if (systemDSTChange &&
|
|
5907
|
-
|
|
5908
|
-
|
|
5946
|
+
let systemOffsetForDiff = systemOffset;
|
|
5947
|
+
if (systemDSTChange && systemOffset !== offset) {
|
|
5948
|
+
const systemHour = Date.prototype.getHours.apply(date2);
|
|
5949
|
+
const expectedHour = Array.isArray(constructorArgs) ? constructorArgs[3] || 0 : date2.internal.getUTCHours();
|
|
5950
|
+
if (systemHour !== expectedHour) {
|
|
5951
|
+
const testDate = /* @__PURE__ */ new Date(+date2);
|
|
5952
|
+
const testOffsetDiff = systemOffset - offset;
|
|
5953
|
+
if (testOffsetDiff) testDate.setUTCMinutes(testDate.getUTCMinutes() + testOffsetDiff);
|
|
5954
|
+
const testOffsetWithSeconds = tzOffset(date2.timeZone, testDate);
|
|
5955
|
+
const testOffset = testOffsetWithSeconds > 0 ? Math.floor(testOffsetWithSeconds) : Math.ceil(testOffsetWithSeconds);
|
|
5956
|
+
if (testOffset === offset) systemOffsetForDiff = prevHourSystemOffset;
|
|
5957
|
+
}
|
|
5958
|
+
}
|
|
5959
|
+
const offsetDiff = systemOffsetForDiff - offset;
|
|
5960
|
+
if (offsetDiff)
|
|
5961
|
+
Date.prototype.setUTCMinutes.call(date2, Date.prototype.getUTCMinutes.call(date2) + offsetDiff);
|
|
5909
5962
|
const systemDate = /* @__PURE__ */ new Date(+date2);
|
|
5910
5963
|
systemDate.setUTCSeconds(0);
|
|
5911
5964
|
const systemSecondsOffset = systemOffset > 0 ? systemDate.getSeconds() : (systemDate.getSeconds() - 60) % 60;
|
|
5912
5965
|
const secondsOffset = Math.round(-(tzOffset(date2.timeZone, date2) * 60)) % 60;
|
|
5913
|
-
if (secondsOffset || systemSecondsOffset)
|
|
5914
|
-
date2.internal.setUTCSeconds(date2.internal.getUTCSeconds() + secondsOffset);
|
|
5966
|
+
if (secondsOffset || systemSecondsOffset)
|
|
5915
5967
|
Date.prototype.setUTCSeconds.call(date2, Date.prototype.getUTCSeconds.call(date2) + secondsOffset + systemSecondsOffset);
|
|
5916
|
-
|
|
5917
|
-
const
|
|
5918
|
-
const postOffset = postBaseOffset > 0 ? Math.floor(postBaseOffset) : Math.ceil(postBaseOffset);
|
|
5968
|
+
const postOffsetWithSeconds = tzOffset(date2.timeZone, date2);
|
|
5969
|
+
const postOffset = postOffsetWithSeconds > 0 ? Math.floor(postOffsetWithSeconds) : Math.ceil(postOffsetWithSeconds);
|
|
5919
5970
|
const postSystemOffset = -(/* @__PURE__ */ new Date(+date2)).getTimezoneOffset();
|
|
5920
5971
|
const postOffsetDiff = postSystemOffset - postOffset;
|
|
5921
5972
|
const offsetChanged = postOffset !== offset;
|
|
5922
5973
|
const postDiff = postOffsetDiff - offsetDiff;
|
|
5923
|
-
|
|
5974
|
+
const targetDSTShift = postOffset - offset;
|
|
5975
|
+
const postOffsetCandidate = expectedInternalTime - postOffset * 60 * 1e3;
|
|
5976
|
+
const normalizedTargetDSTGap = targetDSTShift > 0 && targetInternalTime(date2) - expectedInternalTime === targetDSTShift * 60 * 1e3 && targetInternalTime(date2, postOffsetCandidate) !== expectedInternalTime;
|
|
5977
|
+
if (offsetChanged && postDiff && !normalizedTargetDSTGap) {
|
|
5924
5978
|
Date.prototype.setUTCMinutes.call(date2, Date.prototype.getUTCMinutes.call(date2) + postDiff);
|
|
5925
|
-
const
|
|
5926
|
-
const newOffset =
|
|
5979
|
+
const newOffsetWithSeconds = tzOffset(date2.timeZone, date2);
|
|
5980
|
+
const newOffset = newOffsetWithSeconds > 0 ? Math.floor(newOffsetWithSeconds) : Math.ceil(newOffsetWithSeconds);
|
|
5927
5981
|
const offsetChange = postOffset - newOffset;
|
|
5928
|
-
if (offsetChange) {
|
|
5929
|
-
date2.internal.setUTCMinutes(date2.internal.getUTCMinutes() + offsetChange);
|
|
5982
|
+
if (offsetChange && postDiff < 0) {
|
|
5930
5983
|
Date.prototype.setUTCMinutes.call(date2, Date.prototype.getUTCMinutes.call(date2) + offsetChange);
|
|
5931
5984
|
}
|
|
5932
5985
|
}
|
|
5986
|
+
syncToInternal(date2);
|
|
5987
|
+
const expectedTime = constructorArgs ? expectedInternalTime : expectedInternalTime + secondsOffset * 1e3;
|
|
5988
|
+
const drift = expectedTime - +date2.internal;
|
|
5989
|
+
if (drift && Math.abs(drift) < 30 * 60 * 1e3) {
|
|
5990
|
+
Date.prototype.setTime.call(date2, +date2 + drift);
|
|
5991
|
+
syncToInternal(date2);
|
|
5992
|
+
}
|
|
5993
|
+
}
|
|
5994
|
+
function constructorArgsToInternalTime(args) {
|
|
5995
|
+
return Date.UTC(args[0], args.length > 1 ? args[1] : 0, args.length > 2 ? args[2] : 1, ...args.slice(3));
|
|
5996
|
+
}
|
|
5997
|
+
function targetInternalTime(date2, time) {
|
|
5998
|
+
const internal = new Date(time ?? +date2);
|
|
5999
|
+
internal.setUTCSeconds(internal.getUTCSeconds() - Math.round(-tzOffset(date2.timeZone, internal) * 60));
|
|
6000
|
+
return +internal;
|
|
5933
6001
|
}
|
|
5934
6002
|
|
|
5935
6003
|
// ../../node_modules/@date-fns/tz/date/index.js
|
|
@@ -7613,7 +7681,11 @@ var TOOL_INPUT_SEMANTICS = {
|
|
|
7613
7681
|
// Each entry's {field, op, value} carries a field-key position, but the
|
|
7614
7682
|
// field is a sibling-dependent runtime value, not a single `table_from`
|
|
7615
7683
|
// kind — the tool's own resolveSurgicalKeys validates it at execute time.
|
|
7616
|
-
field_edits: { kind: "dynamic" }
|
|
7684
|
+
field_edits: { kind: "dynamic" },
|
|
7685
|
+
// The lock the call leaves, the deleted records it brings back, and the approval it files for a locked one: none holds a field key.
|
|
7686
|
+
locked: { kind: "scalar" },
|
|
7687
|
+
restore: { kind: "scalar" },
|
|
7688
|
+
request_change: { kind: "scalar" }
|
|
7617
7689
|
},
|
|
7618
7690
|
create_records: {
|
|
7619
7691
|
table_id: { kind: "table_ref", rows: "change" },
|
|
@@ -7674,21 +7746,11 @@ var TOOL_INPUT_SEMANTICS = {
|
|
|
7674
7746
|
as_member: { kind: "scalar" },
|
|
7675
7747
|
removal: { kind: "table_field_array" }
|
|
7676
7748
|
},
|
|
7677
|
-
restore_records: {
|
|
7678
|
-
table_id: { kind: "table_ref", rows: "change" },
|
|
7679
|
-
record_ids: { kind: "record_refs" },
|
|
7680
|
-
filters: { kind: "filter_tree", table_from: "table_id" }
|
|
7681
|
-
},
|
|
7682
7749
|
lock_records: {
|
|
7683
7750
|
table_id: { kind: "table_ref", rows: "change" },
|
|
7684
7751
|
record_ids: { kind: "record_refs" },
|
|
7685
7752
|
filters: { kind: "filter_tree", table_from: "table_id" }
|
|
7686
7753
|
},
|
|
7687
|
-
unlock_records: {
|
|
7688
|
-
table_id: { kind: "table_ref", rows: "change" },
|
|
7689
|
-
record_ids: { kind: "record_refs" },
|
|
7690
|
-
filters: { kind: "filter_tree", table_from: "table_id" }
|
|
7691
|
-
},
|
|
7692
7754
|
request_locked_record_change: {
|
|
7693
7755
|
table_id: { kind: "table_ref", rows: "none" },
|
|
7694
7756
|
record_id: { kind: "record_ref" },
|
|
@@ -7697,18 +7759,6 @@ var TOOL_INPUT_SEMANTICS = {
|
|
|
7697
7759
|
changes: { kind: "dynamic" },
|
|
7698
7760
|
reason: { kind: "text" }
|
|
7699
7761
|
},
|
|
7700
|
-
// The record names its own table; an entry's id is the trail's.
|
|
7701
|
-
undo_record_change: {
|
|
7702
|
-
record_id: { kind: "record_ref" },
|
|
7703
|
-
entry_id: { kind: "scalar" }
|
|
7704
|
-
},
|
|
7705
|
-
// `table_id` names the table whose rows the undo changes, moves to the trash and brings back; a run's id is the
|
|
7706
|
-
// trail's.
|
|
7707
|
-
undo_record_changes: {
|
|
7708
|
-
table_id: { kind: "table_ref", rows: "remove" },
|
|
7709
|
-
record_ids: { kind: "record_refs" },
|
|
7710
|
-
workflow_execution_id: { kind: "scalar" }
|
|
7711
|
-
},
|
|
7712
7762
|
// ─── Query surfaces ────────────────────────────────────────────────────
|
|
7713
7763
|
query_records: {
|
|
7714
7764
|
table_id: { kind: "table_ref", rows: "none" },
|
|
@@ -7724,6 +7774,10 @@ var TOOL_INPUT_SEMANTICS = {
|
|
|
7724
7774
|
archived_only: { kind: "scalar" },
|
|
7725
7775
|
include_timestamps: { kind: "scalar" },
|
|
7726
7776
|
as_member: { kind: "scalar" },
|
|
7777
|
+
comments: { kind: "scalar" },
|
|
7778
|
+
record_ids: { kind: "record_refs" },
|
|
7779
|
+
// Nested {field_key, operation} shapes and a group_by key: resolved at execute time, as the aggregate tool did.
|
|
7780
|
+
aggregate: { kind: "dynamic" },
|
|
7727
7781
|
// Each entry pairs its OWN table_id with its OWN filter tree, so the table a
|
|
7728
7782
|
// filter resolves against is per-element rather than a sibling kwarg — no
|
|
7729
7783
|
// top-level kind can say that. Opaque to the save-time walker, which is the
|
|
@@ -7775,7 +7829,8 @@ var TOOL_INPUT_SEMANTICS = {
|
|
|
7775
7829
|
// Keys on the record's own table, which `table_id` names when supplied and
|
|
7776
7830
|
// the record resolves otherwise — the same position it holds on a query.
|
|
7777
7831
|
field_keys: { kind: "field_key_refs", table_from: "table_id" },
|
|
7778
|
-
as_member: { kind: "scalar" }
|
|
7832
|
+
as_member: { kind: "scalar" },
|
|
7833
|
+
comments: { kind: "scalar" }
|
|
7779
7834
|
},
|
|
7780
7835
|
// ─── Buttons (table-scoped field with action) ─────────────────────────
|
|
7781
7836
|
press_button: {
|
|
@@ -9682,7 +9737,8 @@ async function tableOf(walk, input) {
|
|
|
9682
9737
|
async function predictUpdate(walk, input) {
|
|
9683
9738
|
const table = await tableOf(walk, input);
|
|
9684
9739
|
const ids = input.record_ids === void 0 ? null : asIds(await attempt(walk, input.record_ids));
|
|
9685
|
-
|
|
9740
|
+
const serverDecided = input.restore !== void 0 || input.locked !== void 0 || input.request_change !== void 0;
|
|
9741
|
+
if (table === null || ids === null || serverDecided || input.filters !== void 0 || input.rows !== void 0 || input.field_edits !== void 0) {
|
|
9686
9742
|
note(walk, { kind: "unknown", table_id: table });
|
|
9687
9743
|
return;
|
|
9688
9744
|
}
|
package/dist/router.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export interface NotFoundWords {
|
|
|
4
4
|
message: (path: string) => string;
|
|
5
5
|
firstScreen: string;
|
|
6
6
|
}
|
|
7
|
-
export declare function AppRouter({ routes, notFound, drawers }: {
|
|
7
|
+
export declare function AppRouter({ routes, notFound, drawers, }: {
|
|
8
8
|
routes: RouteObject[];
|
|
9
9
|
notFound?: NotFoundWords;
|
|
10
10
|
/** The query keys a drawer opens at, the one drawn lowest first: each open counts as a screen over the path's. */
|
package/dist/router.js
CHANGED
package/docs/ai.md
CHANGED
|
@@ -13,7 +13,7 @@ Don't run a structured extraction through `askAi` (the result is stranded in a c
|
|
|
13
13
|
|
|
14
14
|
## Declared agents — what `useAgentRun` runs
|
|
15
15
|
|
|
16
|
-
`useAgentRun` runs an agent already bound to the app; none can be added or
|
|
16
|
+
`useAgentRun` runs an agent already bound to the app; none can be added, changed or removed any more. A new job for an agent is a declared Query or Workflow node of the app, which an outside agent runs with `run_app_query` and `run_app_workflow`. `.lotics/app_agents.d.ts`, generated from the app's live bindings by `lotics app deploy` and `lotics app pull`, types `useAgentRun("<alias>")` by the agent's input and output shapes.
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
package/docs/data_fetching.md
CHANGED
|
@@ -11,8 +11,8 @@ alias** (bound with `set_app_queries`) and fills the template's declared `{{para
|
|
|
11
11
|
value holes; the server holds the canonical AST and runs it under the **app owner's** authority
|
|
12
12
|
([./security.md](./security.md)). The generated `.lotics/app_queries.d.ts` augments `AppQueries`,
|
|
13
13
|
so params are typed per the binding; an alias it does not carry is accepted as a plain string,
|
|
14
|
-
untyped. It is written from the app's live bindings by `lotics app
|
|
15
|
-
`lotics app
|
|
14
|
+
untyped. It is written from the app's live bindings by `lotics app deploy` and
|
|
15
|
+
`lotics app pull`. Every hook reads through the SDK's own cache, over the host RPC bridge.
|
|
16
16
|
|
|
17
17
|
## Choosing a read
|
|
18
18
|
|
|
@@ -194,10 +194,10 @@ three gates are observable as an `error` on the hook:
|
|
|
194
194
|
resolves to `{ members: [] }`.
|
|
195
195
|
|
|
196
196
|
Name the group by the `grp_…` id the workflow input's `group` declares — the binding below, set
|
|
197
|
-
with `
|
|
197
|
+
with `set_workflow`:
|
|
198
198
|
|
|
199
199
|
```jsonc
|
|
200
|
-
//
|
|
200
|
+
// the header of a set_workflow source — the declaration that unlocks useMembers
|
|
201
201
|
{
|
|
202
202
|
"alias": "assignOrder",
|
|
203
203
|
"inputs": {
|
package/docs/mutations.md
CHANGED
|
@@ -24,7 +24,7 @@ const result = await createOrder({ customer_id, quantity: 3 });
|
|
|
24
24
|
against the alias's declared input schema, and executes the workflow under the **app
|
|
25
25
|
owner's** authority (never the viewer's — see [security](./security.md) for attribution,
|
|
26
26
|
privilege gates, and public-app semantics).
|
|
27
|
-
- Binding is server-side and live: `
|
|
27
|
+
- Binding is server-side and live: `set_workflow` binds an alias as a new version of the app,
|
|
28
28
|
and a deploy never touches it. The declaration also types `useWorkflow` (below).
|
|
29
29
|
- Invoking an alias that is not bound resolves with `status: "error"` and a message naming
|
|
30
30
|
the missing binding.
|
|
@@ -41,7 +41,7 @@ render: one callable per alias, each run exactly as `useWorkflow`'s.
|
|
|
41
41
|
|
|
42
42
|
Typing comes from `.lotics/app_workflows.d.ts`, which augments the SDK's `AppWorkflows` and
|
|
43
43
|
`AppWorkflowResults` interfaces from the app's bound declarations. The declarations are generated from the app's live bindings into `.lotics/` by
|
|
44
|
-
`lotics app
|
|
44
|
+
`lotics app deploy` and `lotics app pull`. The result:
|
|
45
45
|
|
|
46
46
|
| Declaration | Call-site type |
|
|
47
47
|
|---|---|
|
|
@@ -170,7 +170,7 @@ envelope's grammar — `message` is required, `field_errors` never reaches the a
|
|
|
170
170
|
|
|
171
171
|
- **Typed for free — persisted at `set`.** The alias's `outputs` schema is derived at save
|
|
172
172
|
time from the inferred type of the body's `return({ data })`. When the binding declares
|
|
173
|
-
**no** `outputs`, `
|
|
173
|
+
**no** `outputs`, `set_workflow` stores the derived schema as the alias's `outputs`. An
|
|
174
174
|
**explicitly declared** `outputs` is authoritative and never overwritten;
|
|
175
175
|
declare one only to narrow beyond what's inferred. A shape the checker can't pin down degrades
|
|
176
176
|
to untyped `json`, never to a wrong schema.
|
|
@@ -214,7 +214,7 @@ if (r.status === "success" && r.data) {
|
|
|
214
214
|
An alias's declaration is `{ inputs?, outputs?, workflow_id? }` — `workflow_id` is the server's
|
|
215
215
|
half, stamped by the first bind, so an alias an author has only just written carries none.
|
|
216
216
|
`inputs` maps each input name to a typed declaration; it is authored beside the body and
|
|
217
|
-
travels with it (`
|
|
217
|
+
travels with it (`set_workflow` takes both), and the schema the body was verified against is
|
|
218
218
|
canonical. It drives three things at once: compile-time typing of the `useWorkflow` payload,
|
|
219
219
|
compile-time typing of `trigger.app_workflow.inputs.*` inside the body, and runtime payload
|
|
220
220
|
validation at the execute boundary.
|
|
@@ -283,7 +283,7 @@ When the alias declares `inputs`, the server validates the payload before the wo
|
|
|
283
283
|
added after authoring is accepted, a removed one rejected
|
|
284
284
|
(`select input "<path>" value "<v>" is not one of its current options (<label>=<value>, …)`) with no
|
|
285
285
|
redeploy. A `field` that doesn't exist or names a non-select field is rejected at bind time
|
|
286
|
-
(`
|
|
286
|
+
(`set_workflow`) with
|
|
287
287
|
`select input references field "<key>", which does not exist in this workspace` /
|
|
288
288
|
`… which is a <type> field, not a select`. Prefer `field` for any select backed by a real
|
|
289
289
|
field; keep `options` for a fixed enum the app owns. Populate pickers from `useFieldOptions`
|
|
@@ -460,7 +460,7 @@ return({ status: "success", message: "Updated." });
|
|
|
460
460
|
```
|
|
461
461
|
|
|
462
462
|
`update_records` has no bypass flag — a locked record's values change only through the
|
|
463
|
-
approval flow below (or the table's owner or an admin explicitly unlocking the record first; `
|
|
463
|
+
approval flow below (or the table's owner or an admin explicitly unlocking the record first; `update_records` with `locked: false` is
|
|
464
464
|
owner- or admin-gated — in an app's run, judged as the member who pressed, never the app's owner — so don't build an unlock→edit→relock workflow around the approval flow — the
|
|
465
465
|
lock exists to route changes through review).
|
|
466
466
|
|
|
@@ -553,7 +553,7 @@ What the steps cannot tell before they run is never guessed:
|
|
|
553
553
|
looks for a row to reuse draws nothing until the server says which it did. A `catch` block and a
|
|
554
554
|
`while` or counted `for` loop wait too.
|
|
555
555
|
- A pause (`wait`, `wait_for_event`, `wait_for_approval`): every write after it waits for the answer.
|
|
556
|
-
- A step that changes rows it cannot draw — `lock_records`, `
|
|
556
|
+
- A step that changes rows it cannot draw — `lock_records`, `update_records` with `restore` or `locked`, a pressed button, an
|
|
557
557
|
agent whose tools can change rows, a `create_records` matching on a field, a filtered update or
|
|
558
558
|
delete: every read over the tables it may touch (every read, where it names none) is `pending`
|
|
559
559
|
until the answer lands.
|
package/docs/recipes.md
CHANGED
|
@@ -121,11 +121,7 @@ Two **separate** layers; set both.
|
|
|
121
121
|
|
|
122
122
|
**Launcher chrome** — `lotics run set_app '{"app_id":"…","body":{"icon":"truck","color":"blue"}}'`.
|
|
123
123
|
`icon` is any Lucide name (the full library, validated at write time — a wrong name is rejected, not
|
|
124
|
-
silently boxed). Don't guess the kebab spelling:
|
|
125
|
-
|
|
126
|
-
```
|
|
127
|
-
lotics run search_app_icons '{"query":"shipping"}' → ["truck","ship","package",…]
|
|
128
|
-
```
|
|
124
|
+
silently boxed). Don't guess the kebab spelling: a wrong name is refused with the nearest Lucide names.
|
|
129
125
|
|
|
130
126
|
`color` is a named palette colour: `red orange amber yellow lime green emerald teal cyan sky
|
|
131
127
|
blue indigo violet purple fuchsia pink rose slate gray zinc neutral stone`. `null` in `body` clears
|
package/docs/runtime.md
CHANGED
|
@@ -18,7 +18,7 @@ mount(<App />);
|
|
|
18
18
|
`dist/mount.d.ts`) is called **once** from the app's entry file. It:
|
|
19
19
|
|
|
20
20
|
1. **Registers the mock fixture**, if `options.fixture` was passed (below).
|
|
21
|
-
2. **Finds or creates `#root`.** Uses the `<div id="root">` from the
|
|
21
|
+
2. **Finds or creates `#root`.** Uses the `<div id="root">` from the app's
|
|
22
22
|
`index.html`; if the bundler didn't ship one, it creates and appends it.
|
|
23
23
|
3. **Installs visible error handlers.** `window` `error` and
|
|
24
24
|
`unhandledrejection` listeners render a fixed red monospace banner (message +
|
package/docs/workflows.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Workflows — the body-authoring reference
|
|
2
2
|
|
|
3
|
-
The grammar of a **workflow body**: what `
|
|
3
|
+
The grammar of a **workflow body**: what `set_workflow` takes as a `source` bound to an app's alias, the
|
|
4
4
|
JS subset that is accepted, and the rules that decide whether a body saves.
|
|
5
5
|
[mutations](./mutations.md) owns the *call* side; this document owns everything between the
|
|
6
6
|
braces.
|
|
@@ -17,7 +17,7 @@ engine, no `eval`, no sandbox. Four consequences shape everything below:
|
|
|
17
17
|
- **A successful save may still return `warnings[]`** — advisory lint that does not block.
|
|
18
18
|
Read them; they are the failures that only show up in production.
|
|
19
19
|
- **One canonical form per concept.** Several JS spellings are accepted and *lowered* to one
|
|
20
|
-
stored form. The stored tree renders back to source when it is read (`
|
|
20
|
+
stored form. The stored tree renders back to source when it is read (`get_workflow`), so a
|
|
21
21
|
read body shows the canonical spelling, not the sugar you typed (see *Round-tripping* below).
|
|
22
22
|
- **Opaque keys, never display names.** Fields are `fld_*`, select options are `opt_*`, tables
|
|
23
23
|
are `tbl_*`, groups are `grp_*`. A display name is rejected at save with an error pointing at
|
|
@@ -31,10 +31,10 @@ if (order.data["fld_status"] == "opt_open") { … }
|
|
|
31
31
|
|
|
32
32
|
## Where a body lives
|
|
33
33
|
|
|
34
|
-
A body is the app's, stored on the server and bound to an alias: `
|
|
35
|
-
|
|
36
|
-
`return({ data })` derive it). The server verifies the body and the write lands live, as a new
|
|
37
|
-
version of the app; `
|
|
34
|
+
A body is the app's, stored on the server and bound to an alias: `set_workflow` takes a
|
|
35
|
+
`source` whose `on({ type: "app", app_id, alias, inputs?, outputs? })` header names the alias and its `inputs`
|
|
36
|
+
(leave `outputs` off to let the body's `return({ data })` derive it), then the body. The server verifies the body and the write lands live, as a new
|
|
37
|
+
version of the app; `get_workflow` reads it back, and an earlier body is restored by writing it again. Input declaration vocabulary and validation:
|
|
38
38
|
[mutations](./mutations.md#declaring-workflow-inputs).
|
|
39
39
|
|
|
40
40
|
An app workflow body carries **no trigger declaration** — the binding supplies the trigger
|
|
@@ -250,7 +250,7 @@ only the dialog. What it may name depends on who renders the refusal:
|
|
|
250
250
|
|
|
251
251
|
An app workflow whose alias declares no inputs leaves input-shaped keys unchecked, so a body can
|
|
252
252
|
be written before its declaration. A key outside its row is refused when the body is SAVED — by
|
|
253
|
-
`
|
|
253
|
+
`set_workflow`, by an agent binding one — and by a `dry_run` call before that. `return({ field_errors })` keys are not checked.
|
|
254
254
|
|
|
255
255
|
### `wait_for_approval` — the one wait worth binding
|
|
256
256
|
|
|
@@ -460,7 +460,7 @@ A single-expression helper, **top level only**, inlined at every call site.
|
|
|
460
460
|
value: `lineTotal({ qty: 1, price: 2 })` is rejected because inlining would splice a path onto
|
|
461
461
|
an object literal. Bind it first (`const l = { … };` then `lineTotal(l)`), or pass a row.
|
|
462
462
|
|
|
463
|
-
**A declared `function` does not survive a read.** Inlining erases it: `
|
|
463
|
+
**A declared `function` does not survive a read.** Inlining erases it: `get_workflow` returns
|
|
464
464
|
the body repeated at each call site and no `function` at all. Reach for one when the *saved* logic
|
|
465
465
|
is what matters, and expect to re-extract it if you edit the source read back.
|
|
466
466
|
|
|
@@ -834,7 +834,7 @@ genuinely recursive.
|
|
|
834
834
|
|
|
835
835
|
## The check loop
|
|
836
836
|
|
|
837
|
-
`
|
|
837
|
+
`set_workflow` with `dry_run: true` gives the verdict a save would, and writes nothing. The
|
|
838
838
|
server runs every check a save runs — the subset parse, the type pass against the alias's
|
|
839
839
|
declared inputs, tool and kwarg resolution, field, option, table and group resolution, `switch`
|
|
840
840
|
case validation, the literal `formatDate` probe, waits in loops, table reach, the `field_key` rule and the published-API guard. **Green means the save will take
|
|
@@ -849,8 +849,8 @@ fix-stating messages before you see them.
|
|
|
849
849
|
|
|
850
850
|
`check` and `set` prove parse, types, name resolution, structure, and lint — **none of them
|
|
851
851
|
evaluates an expression**. A body that saves clean can still take the wrong branch, hand a tool a filter it
|
|
852
|
-
rejects, or read a path that is null on real data. The rehearsal for that is `
|
|
853
|
-
`
|
|
852
|
+
rejects, or read a path that is null on real data. The rehearsal for that is `set_workflow` with
|
|
853
|
+
`dry_run: true` and a `record_id` (the row an Act would run on) or `preview_inputs` (the values of a
|
|
854
854
|
workflow that takes inputs and no row): the draft is walked by the engine an Act's preview uses, under the
|
|
855
855
|
app's authority, with the production expression evaluator. Reads are real; writes and service sends are
|
|
856
856
|
said, not made, and a document a step renders is made as a paper no listing shows. It answers `preview`
|
|
@@ -865,7 +865,7 @@ A workflow that files a recording ([mutations](./mutations.md#recording-into-a-w
|
|
|
865
865
|
declares the platform's `recording` input in exactly this shape, beside its own inputs:
|
|
866
866
|
|
|
867
867
|
```jsonc
|
|
868
|
-
//
|
|
868
|
+
// the header of a set_workflow source: on({ type: "app", app_id, alias: "log_visit", inputs: … })
|
|
869
869
|
"inputs": {
|
|
870
870
|
"site": { "type": "record_link", "table_id": "tbl_sites" },
|
|
871
871
|
"recording": { "type": "object", "fields": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lotics/app-sdk",
|
|
3
|
-
"version": "0.124.
|
|
3
|
+
"version": "0.124.10",
|
|
4
4
|
"description": "The SDK a Lotics custom-code app reads and writes through — typed hooks over the host bridge, cell readers, mount() and AppRouter",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
"build": "tsgo -p tsconfig.build.json && node scripts/build_sdk.mjs",
|
|
27
27
|
"lint": "oxlint",
|
|
28
28
|
"test": "vitest run",
|
|
29
|
-
"typecheck": "
|
|
29
|
+
"typecheck": "tsrs --noEmit",
|
|
30
30
|
"prepack": "npm run build"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"ai": "^7.0.
|
|
33
|
+
"ai": "^7.0.152"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"react": "^19.2.0",
|
|
@@ -39,17 +39,19 @@
|
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@lotics/shared": "*",
|
|
42
|
-
"@testing-library/react": "^16.3.
|
|
43
|
-
"@types/
|
|
44
|
-
"@types/react
|
|
42
|
+
"@testing-library/react": "^16.3.3",
|
|
43
|
+
"@types/node": "^24.19.2",
|
|
44
|
+
"@types/react": "^19.3.0",
|
|
45
|
+
"@types/react-dom": "~19.3.0",
|
|
46
|
+
"@typescript/native-preview": "^7.0.0-dev.20260707.2",
|
|
45
47
|
"@vitejs/plugin-react": "^6.1.2",
|
|
46
|
-
"esbuild": "^0.28.
|
|
47
|
-
"jsdom": "^30.1.
|
|
48
|
-
"react": "^19.
|
|
49
|
-
"react-dom": "^19.
|
|
50
|
-
"react-router": "^
|
|
48
|
+
"esbuild": "^0.28.2",
|
|
49
|
+
"jsdom": "^30.1.3",
|
|
50
|
+
"react": "^19.3.1",
|
|
51
|
+
"react-dom": "^19.3.1",
|
|
52
|
+
"react-router": "^8.5.0",
|
|
51
53
|
"typescript": "~6.0.3",
|
|
52
|
-
"vite": "^8.3.
|
|
54
|
+
"vite": "^8.3.5"
|
|
53
55
|
},
|
|
54
56
|
"engines": {
|
|
55
57
|
"node": ">=18"
|