abra-flexi 0.5.7 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +298 -95
- package/dist/index.d.cts +40 -8
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +40 -8
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +298 -95
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -186,6 +186,7 @@ var AFEntity = class AFEntity {
|
|
|
186
186
|
}
|
|
187
187
|
constructor(stitkyCache) {
|
|
188
188
|
this._orig = {};
|
|
189
|
+
this._isNew = true;
|
|
189
190
|
this._stitkyCache = stitkyCache;
|
|
190
191
|
}
|
|
191
192
|
getPropertyTypeAnnotation(key) {
|
|
@@ -201,7 +202,7 @@ var AFEntity = class AFEntity {
|
|
|
201
202
|
return !this.hasChanged();
|
|
202
203
|
}
|
|
203
204
|
get isNew() {
|
|
204
|
-
return
|
|
205
|
+
return this._isNew;
|
|
205
206
|
}
|
|
206
207
|
getCotr() {
|
|
207
208
|
return this.constructor;
|
|
@@ -66578,6 +66579,29 @@ function extractEvidence(inUrl) {
|
|
|
66578
66579
|
return split[3];
|
|
66579
66580
|
}
|
|
66580
66581
|
|
|
66582
|
+
//#endregion
|
|
66583
|
+
//#region src/abra/AFNestedEntityResolver.ts
|
|
66584
|
+
function resolveNestedEntityPathPrefix(entityPath, options) {
|
|
66585
|
+
switch (entityPath) {
|
|
66586
|
+
case "individualni-cenik": {
|
|
66587
|
+
const sel = serializeParentSelector(options.adresarId, "adresarId", entityPath);
|
|
66588
|
+
if (sel === void 0) return "";
|
|
66589
|
+
return `adresar/${sel}/`;
|
|
66590
|
+
}
|
|
66591
|
+
default: return "";
|
|
66592
|
+
}
|
|
66593
|
+
}
|
|
66594
|
+
function serializeParentSelector(value, optionName, entityPath) {
|
|
66595
|
+
if (value === void 0 || value === null) return void 0;
|
|
66596
|
+
if (value instanceof AFFilter) {
|
|
66597
|
+
const piece = value.toUrlComponent();
|
|
66598
|
+
if (!piece.length) throw new AFError(AFErrorCode.MISSING_ID, `'${optionName}' for ${entityPath} resolved to empty URL component.`);
|
|
66599
|
+
return piece;
|
|
66600
|
+
}
|
|
66601
|
+
if (typeof value === "string" && !value.length) throw new AFError(AFErrorCode.MISSING_ID, `'${optionName}' for ${entityPath} must be a non-empty id.`);
|
|
66602
|
+
return String(value);
|
|
66603
|
+
}
|
|
66604
|
+
|
|
66581
66605
|
//#endregion
|
|
66582
66606
|
//#region src/abra/AFStitkyCache.ts
|
|
66583
66607
|
const DEBOUNCE_MS = 5 * 1e3;
|
|
@@ -66596,51 +66620,61 @@ var AFStitkyCache = class {
|
|
|
66596
66620
|
if (this._strategy === StitkyCacheStrategy.None) return;
|
|
66597
66621
|
const now = /* @__PURE__ */ new Date();
|
|
66598
66622
|
if (this._lastUpdate && now.getTime() - this._lastUpdate.getTime() < DEBOUNCE_MS) return;
|
|
66599
|
-
|
|
66600
|
-
|
|
66601
|
-
|
|
66602
|
-
|
|
66603
|
-
|
|
66604
|
-
|
|
66605
|
-
|
|
66606
|
-
|
|
66607
|
-
|
|
66608
|
-
|
|
66609
|
-
this.
|
|
66610
|
-
|
|
66611
|
-
|
|
66612
|
-
|
|
66613
|
-
|
|
66614
|
-
|
|
66615
|
-
|
|
66616
|
-
|
|
66617
|
-
|
|
66618
|
-
|
|
66619
|
-
|
|
66620
|
-
|
|
66621
|
-
|
|
66622
|
-
|
|
66623
|
-
|
|
66624
|
-
|
|
66625
|
-
|
|
66626
|
-
|
|
66627
|
-
|
|
66628
|
-
|
|
66629
|
-
|
|
66630
|
-
|
|
66631
|
-
|
|
66632
|
-
|
|
66633
|
-
|
|
66634
|
-
|
|
66635
|
-
|
|
66636
|
-
|
|
66637
|
-
|
|
66638
|
-
|
|
66639
|
-
|
|
66640
|
-
|
|
66623
|
+
if (this._inflight) return this._inflight;
|
|
66624
|
+
this._inflight = (async () => {
|
|
66625
|
+
try {
|
|
66626
|
+
const sinceTs = this._lastUpdate ? formatAbraTimestamp(this._lastUpdate) : void 0;
|
|
66627
|
+
const skupOpts = {
|
|
66628
|
+
limit: NO_LIMIT,
|
|
66629
|
+
detail: AFQueryDetail.FULL,
|
|
66630
|
+
noUpdateStitkyCache: true
|
|
66631
|
+
};
|
|
66632
|
+
if (sinceTs) skupOpts.filter = Filter(`lastUpdate > :date`, { date: sinceTs });
|
|
66633
|
+
const skUpdate = await this._client.query(AFSkupinaStitku, skupOpts);
|
|
66634
|
+
for (const sk of skUpdate) {
|
|
66635
|
+
let found = this._stitekSkupiny.find((ss) => ss.id === sk.id);
|
|
66636
|
+
if (!found) {
|
|
66637
|
+
this._stitekSkupiny.push(sk);
|
|
66638
|
+
continue;
|
|
66639
|
+
}
|
|
66640
|
+
Object.assign(found, sk);
|
|
66641
|
+
}
|
|
66642
|
+
const stitOpts = {
|
|
66643
|
+
limit: NO_LIMIT,
|
|
66644
|
+
detail: [
|
|
66645
|
+
"id",
|
|
66646
|
+
"kod",
|
|
66647
|
+
"lastUpdate",
|
|
66648
|
+
"nazev",
|
|
66649
|
+
"nazevA",
|
|
66650
|
+
"nazevB",
|
|
66651
|
+
"nazevC",
|
|
66652
|
+
"nazevD",
|
|
66653
|
+
"poznam",
|
|
66654
|
+
"popis",
|
|
66655
|
+
"platiOd",
|
|
66656
|
+
"platiDo",
|
|
66657
|
+
"skupVybKlic"
|
|
66658
|
+
],
|
|
66659
|
+
noUpdateStitkyCache: true
|
|
66660
|
+
};
|
|
66661
|
+
if (sinceTs) stitOpts.filter = Filter(`lastUpdate > :date`, { date: sinceTs });
|
|
66662
|
+
const stUpdate = await this._client.query(AFStitek, stitOpts);
|
|
66663
|
+
for (const st of stUpdate) {
|
|
66664
|
+
st.skupVybKlic = this._stitekSkupiny.find((ss) => ss.kod === st.skupVybKlic?.kod);
|
|
66665
|
+
const found = this._stitky.find((s) => s.id === st.id);
|
|
66666
|
+
if (!found) {
|
|
66667
|
+
this._stitky.push(st);
|
|
66668
|
+
continue;
|
|
66669
|
+
}
|
|
66670
|
+
Object.assign(found, st);
|
|
66671
|
+
}
|
|
66672
|
+
this._lastUpdate = now;
|
|
66673
|
+
} finally {
|
|
66674
|
+
this._inflight = void 0;
|
|
66641
66675
|
}
|
|
66642
|
-
|
|
66643
|
-
|
|
66676
|
+
})();
|
|
66677
|
+
return this._inflight;
|
|
66644
66678
|
}
|
|
66645
66679
|
stitkyWithString(keys, groupFilter) {
|
|
66646
66680
|
if (!keys) return void 0;
|
|
@@ -66660,15 +66694,27 @@ var AFStitkyCache = class {
|
|
|
66660
66694
|
return list;
|
|
66661
66695
|
}
|
|
66662
66696
|
};
|
|
66697
|
+
function formatAbraTimestamp(d) {
|
|
66698
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
66699
|
+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
|
|
66700
|
+
}
|
|
66663
66701
|
|
|
66664
66702
|
//#endregion
|
|
66665
66703
|
//#region src/abra/AFApiClient.ts
|
|
66666
66704
|
const ABRA_API_FORMAT = "json";
|
|
66705
|
+
const LOG_LEVEL_RANK = {
|
|
66706
|
+
none: 0,
|
|
66707
|
+
error: 1,
|
|
66708
|
+
warn: 2,
|
|
66709
|
+
info: 3,
|
|
66710
|
+
debug: 4
|
|
66711
|
+
};
|
|
66667
66712
|
var AFApiClient = class {
|
|
66668
66713
|
constructor(config) {
|
|
66669
66714
|
this._url = config.url;
|
|
66670
66715
|
this._company = config.company;
|
|
66671
66716
|
this._fetch = config.fetch || fetch;
|
|
66717
|
+
this._logger = makeFilteringLogger(config.logger ?? console, config.logLevel ?? (config.logger ? "debug" : "none"));
|
|
66672
66718
|
this._stitkyCache = new AFStitkyCache(this, config.stitkyCacheStrategy);
|
|
66673
66719
|
}
|
|
66674
66720
|
get url() {
|
|
@@ -66680,14 +66726,14 @@ var AFApiClient = class {
|
|
|
66680
66726
|
get stitkyCacheStrategy() {
|
|
66681
66727
|
return this._stitkyCache.strategy;
|
|
66682
66728
|
}
|
|
66683
|
-
|
|
66684
|
-
if (!this.company || !this.company.length) throw new AFError(AFErrorCode.MISSING_ABRA_COMPANY, `Can't query AFApiClient without providing company path component first.`);
|
|
66729
|
+
_buildQueryUrl(entityPath, format, options) {
|
|
66685
66730
|
const detail = options.detail || AFQueryDetail.SUMMARY;
|
|
66686
66731
|
let furl = options.filter?.toUrlComponent();
|
|
66687
66732
|
if (furl && !furl.length) furl = void 0;
|
|
66688
|
-
|
|
66733
|
+
const pathPrefix = resolveNestedEntityPathPrefix(entityPath, options);
|
|
66734
|
+
let url = this._url + "/c/" + this.company + "/" + pathPrefix + entityPath;
|
|
66689
66735
|
url += furl ? "/" + furl : "";
|
|
66690
|
-
url += "." +
|
|
66736
|
+
url += "." + format;
|
|
66691
66737
|
url = addParamToUrl(url, "detail", composeDetail(detail));
|
|
66692
66738
|
url = addParamToUrl(url, "includes", composeIncludes(detail, entityPath));
|
|
66693
66739
|
url = addParamToUrl(url, "relations", composeRelations(detail));
|
|
@@ -66706,20 +66752,61 @@ var AFApiClient = class {
|
|
|
66706
66752
|
url = addParamToUrl(url, "pocetMesicu", options.pocetMesicu);
|
|
66707
66753
|
url = addParamToUrl(url, "date", options.date);
|
|
66708
66754
|
url = addParamToUrl(url, "currency", options.currency);
|
|
66709
|
-
|
|
66755
|
+
return url;
|
|
66756
|
+
}
|
|
66757
|
+
async queryRaw(entityPath, options = {}) {
|
|
66758
|
+
if (!this.company || !this.company.length) throw new AFError(AFErrorCode.MISSING_ABRA_COMPANY, `Can't query AFApiClient without providing company path component first.`);
|
|
66759
|
+
const url = this._buildQueryUrl(entityPath, ABRA_API_FORMAT, options);
|
|
66760
|
+
this._logger.debug(url);
|
|
66710
66761
|
try {
|
|
66711
66762
|
const raw$1 = await this._fetch(url, { signal: options.abortController?.signal });
|
|
66712
|
-
|
|
66713
|
-
|
|
66763
|
+
const json = await raw$1.json().catch(() => null);
|
|
66764
|
+
if (raw$1.status >= 400 && raw$1.status < 600) {
|
|
66765
|
+
const details = this._extractAbraErrors(json);
|
|
66766
|
+
throw new AFError(AFErrorCode.ABRA_FLEXI_ERROR, `${raw$1.status} ${raw$1.statusText}${details ? ` — ${details}` : ""}`);
|
|
66767
|
+
}
|
|
66768
|
+
return json?.winstrom?.[entityPath];
|
|
66769
|
+
} catch (e) {
|
|
66770
|
+
if (!(e instanceof AFError)) {
|
|
66771
|
+
this._logger.error(e);
|
|
66772
|
+
e = new AFError(AFErrorCode.UNKNOWN, e.toString());
|
|
66773
|
+
}
|
|
66774
|
+
throw e;
|
|
66775
|
+
}
|
|
66776
|
+
}
|
|
66777
|
+
async queryFileRaw(entityPath, format, options = {}) {
|
|
66778
|
+
if (!this.company || !this.company.length) throw new AFError(AFErrorCode.MISSING_ABRA_COMPANY, `Can't query AFApiClient without providing company path component first.`);
|
|
66779
|
+
let url = this._buildQueryUrl(entityPath, format, options);
|
|
66780
|
+
url = addParamToUrl(url, "report-name", options.reportName);
|
|
66781
|
+
url = addParamToUrl(url, "report-lang", options.reportLang);
|
|
66782
|
+
this._logger.debug(url);
|
|
66783
|
+
try {
|
|
66784
|
+
const raw$1 = await this._fetch(url, { signal: options.abortController?.signal });
|
|
66785
|
+
if (raw$1.status >= 400 && raw$1.status < 600) {
|
|
66786
|
+
let details = "";
|
|
66787
|
+
if ((raw$1.headers.get("content-type") || "").includes("application/json")) {
|
|
66788
|
+
const json = await raw$1.json().catch(() => null);
|
|
66789
|
+
details = this._extractAbraErrors(json);
|
|
66790
|
+
}
|
|
66791
|
+
throw new AFError(AFErrorCode.ABRA_FLEXI_ERROR, `${raw$1.status} ${raw$1.statusText}${details ? ` — ${details}` : ""}`);
|
|
66792
|
+
}
|
|
66793
|
+
return {
|
|
66794
|
+
blob: await raw$1.blob(),
|
|
66795
|
+
contentType: raw$1.headers.get("content-type") || "application/octet-stream",
|
|
66796
|
+
filename: parseContentDispositionFilename(raw$1.headers.get("content-disposition"))
|
|
66797
|
+
};
|
|
66714
66798
|
} catch (e) {
|
|
66715
66799
|
if (!(e instanceof AFError)) {
|
|
66716
|
-
|
|
66800
|
+
this._logger.error(e);
|
|
66717
66801
|
e = new AFError(AFErrorCode.UNKNOWN, e.toString());
|
|
66718
66802
|
}
|
|
66719
66803
|
throw e;
|
|
66720
66804
|
}
|
|
66721
66805
|
}
|
|
66722
|
-
async
|
|
66806
|
+
async queryFile(entity, format, options = {}) {
|
|
66807
|
+
return this.queryFileRaw(entity.EntityPath, format, options);
|
|
66808
|
+
}
|
|
66809
|
+
async query(entity, options = {}) {
|
|
66723
66810
|
const res = this.queryRaw(entity.EntityPath, options);
|
|
66724
66811
|
try {
|
|
66725
66812
|
const rawData = await res;
|
|
@@ -66728,7 +66815,7 @@ var AFApiClient = class {
|
|
|
66728
66815
|
return data;
|
|
66729
66816
|
} catch (e) {
|
|
66730
66817
|
if (!(e instanceof AFError)) {
|
|
66731
|
-
|
|
66818
|
+
this._logger.error(e);
|
|
66732
66819
|
e = new AFError(AFErrorCode.UNKNOWN, e.toString());
|
|
66733
66820
|
}
|
|
66734
66821
|
throw e;
|
|
@@ -66775,7 +66862,7 @@ var AFApiClient = class {
|
|
|
66775
66862
|
out.push(res);
|
|
66776
66863
|
} catch (e) {
|
|
66777
66864
|
if (!(e instanceof AFError)) {
|
|
66778
|
-
|
|
66865
|
+
this._logger.error(e);
|
|
66779
66866
|
e = new AFError(AFErrorCode.UNKNOWN, e.toString());
|
|
66780
66867
|
}
|
|
66781
66868
|
throw e;
|
|
@@ -66786,7 +66873,7 @@ var AFApiClient = class {
|
|
|
66786
66873
|
if (!options.noUpdateStitkyCache) await this._stitkyCache.fetchTick();
|
|
66787
66874
|
return out;
|
|
66788
66875
|
}
|
|
66789
|
-
async populate(entities, options) {
|
|
66876
|
+
async populate(entities, options = {}) {
|
|
66790
66877
|
const fetchBy = [];
|
|
66791
66878
|
for (const en of entities) {
|
|
66792
66879
|
if (typeof en.id !== "undefined" && en.id !== null) {
|
|
@@ -66825,18 +66912,19 @@ var AFApiClient = class {
|
|
|
66825
66912
|
if (!en) continue;
|
|
66826
66913
|
const oKeys = Object.keys(enQ);
|
|
66827
66914
|
for (const okey of oKeys) this._decodeProperty(en, okey, enQ);
|
|
66915
|
+
en._isNew = false;
|
|
66828
66916
|
}
|
|
66829
66917
|
if (!options.noUpdateStitkyCache) await this._stitkyCache.fetchTick();
|
|
66830
66918
|
} catch (e) {
|
|
66831
66919
|
if (!(e instanceof AFError)) {
|
|
66832
|
-
|
|
66920
|
+
this._logger.error(e);
|
|
66833
66921
|
e = new AFError(AFErrorCode.UNKNOWN, e.toString());
|
|
66834
66922
|
}
|
|
66835
66923
|
throw e;
|
|
66836
66924
|
}
|
|
66837
66925
|
return entities;
|
|
66838
66926
|
}
|
|
66839
|
-
async populateOne(entity, options) {
|
|
66927
|
+
async populateOne(entity, options = {}) {
|
|
66840
66928
|
const res = await this.populate([entity], options);
|
|
66841
66929
|
if (!res || !res.length) throw new AFError(AFErrorCode.OBJECT_NOT_FOUND, `${entity} object not found. Kod / ID: ${entity.kod} / ${entity.id}`);
|
|
66842
66930
|
return res[0];
|
|
@@ -66849,14 +66937,15 @@ var AFApiClient = class {
|
|
|
66849
66937
|
const ent = new entity(this._stitkyCache);
|
|
66850
66938
|
if (id.id) ent.id = id.id;
|
|
66851
66939
|
if (id.kod) ent.kod = id.kod;
|
|
66940
|
+
ent._isNew = false;
|
|
66852
66941
|
return ent;
|
|
66853
66942
|
}
|
|
66854
66943
|
async saveRaw(entityPath, data, options) {
|
|
66855
66944
|
if (!this.company || !this.company.length) throw new AFError(AFErrorCode.MISSING_ABRA_COMPANY, `Can't query AFApiClient without providing company path component first.`);
|
|
66856
66945
|
if (!options) options = {};
|
|
66857
66946
|
let url = this._url + "/c/" + this.company + "/" + entityPath + ".json";
|
|
66858
|
-
|
|
66859
|
-
|
|
66947
|
+
this._logger.debug(url);
|
|
66948
|
+
this._logger.debug(data);
|
|
66860
66949
|
if (options.removeStitky) data["stitky@removeAll"] = "true";
|
|
66861
66950
|
try {
|
|
66862
66951
|
const raw$1 = await this._fetch(url, {
|
|
@@ -66865,98 +66954,189 @@ var AFApiClient = class {
|
|
|
66865
66954
|
headers: { "Content-Type": "application/json" },
|
|
66866
66955
|
body: JSON.stringify({ winstrom: [{ [entityPath]: data }] })
|
|
66867
66956
|
});
|
|
66957
|
+
const json = await raw$1.json().catch(() => null);
|
|
66958
|
+
this._logger.debug(json);
|
|
66868
66959
|
if (raw$1.status >= 400 && raw$1.status < 600) {
|
|
66869
|
-
|
|
66870
|
-
throw new AFError(AFErrorCode.ABRA_FLEXI_ERROR, `${raw$1.status} ${raw$1.statusText}`);
|
|
66960
|
+
const details = this._extractAbraErrors(json);
|
|
66961
|
+
throw new AFError(AFErrorCode.ABRA_FLEXI_ERROR, `${raw$1.status} ${raw$1.statusText}${details ? ` — ${details}` : ""}`);
|
|
66962
|
+
}
|
|
66963
|
+
const jres = json?.winstrom;
|
|
66964
|
+
if (jres && jres["success"] === "false") {
|
|
66965
|
+
const details = this._extractAbraErrors(json);
|
|
66966
|
+
throw new AFError(AFErrorCode.ABRA_FLEXI_ERROR, `Save of ${entityPath} failed${details ? ` — ${details}` : ""}`);
|
|
66871
66967
|
}
|
|
66872
|
-
|
|
66873
|
-
console.log(JSON.stringify(json));
|
|
66874
|
-
if (json.winstrom["success"] === "true") {}
|
|
66968
|
+
return Array.isArray(jres?.results) ? jres.results : [];
|
|
66875
66969
|
} catch (e) {
|
|
66876
66970
|
if (!(e instanceof AFError)) {
|
|
66877
|
-
|
|
66971
|
+
this._logger.error(e);
|
|
66878
66972
|
e = new AFError(AFErrorCode.UNKNOWN, e.toString());
|
|
66879
66973
|
}
|
|
66880
66974
|
throw e;
|
|
66881
66975
|
}
|
|
66882
66976
|
}
|
|
66883
66977
|
async save(entity, options) {
|
|
66978
|
+
if (entity.isNew) {
|
|
66979
|
+
const uvs = entity["uzivatelske-vazby"];
|
|
66980
|
+
if (Array.isArray(uvs) && uvs.length > 0) throw new AFError(AFErrorCode.FORBIDDEN_OPERATION, `Creating ${entity.constructor.EntityName} with 'uzivatelske-vazby' is not supported by the API. Workaround: save the entity first without user relations, then add them in a second update (save) request.`);
|
|
66981
|
+
}
|
|
66884
66982
|
const obj = this._encodeEntity(entity);
|
|
66885
66983
|
const res = this.saveRaw(entity.constructor.EntityPath, obj, options);
|
|
66886
66984
|
try {
|
|
66887
|
-
await res;
|
|
66985
|
+
const results = await res;
|
|
66986
|
+
this._applySaveResultToEntity(entity, results);
|
|
66987
|
+
entity._isNew = false;
|
|
66888
66988
|
return entity;
|
|
66889
66989
|
} catch (e) {
|
|
66890
66990
|
if (!(e instanceof AFError)) {
|
|
66891
|
-
|
|
66991
|
+
this._logger.error(e);
|
|
66892
66992
|
e = new AFError(AFErrorCode.UNKNOWN, e.toString());
|
|
66893
66993
|
}
|
|
66894
66994
|
throw e;
|
|
66895
66995
|
}
|
|
66896
66996
|
}
|
|
66897
|
-
async deleteRaw(entityPath, id, options) {
|
|
66997
|
+
async deleteRaw(entityPath, id, options = {}) {
|
|
66898
66998
|
if (!this.company || !this.company.length) throw new AFError(AFErrorCode.MISSING_ABRA_COMPANY, `Can't query AFApiClient without providing company path component first.`);
|
|
66899
66999
|
if (!id && typeof id !== "number" || id === "") throw new AFError(AFErrorCode.MISSING_ID, `Can't delete entity without knowing it's id.`);
|
|
66900
|
-
let url
|
|
66901
|
-
|
|
66902
|
-
|
|
66903
|
-
|
|
67000
|
+
let url;
|
|
67001
|
+
let fetchOptions;
|
|
67002
|
+
if (options.asUserRelation) {
|
|
67003
|
+
url = this._url + "/c/" + this.company + "/" + entityPath + ".json";
|
|
67004
|
+
fetchOptions = {
|
|
67005
|
+
signal: options.abortController?.signal,
|
|
67006
|
+
method: "PUT",
|
|
67007
|
+
body: JSON.stringify({ winstrom: [{
|
|
67008
|
+
[entityPath]: { id },
|
|
67009
|
+
[entityPath + "@action"]: "delete"
|
|
67010
|
+
}] })
|
|
67011
|
+
};
|
|
67012
|
+
} else {
|
|
67013
|
+
url = this._url + "/c/" + this.company + "/" + entityPath + "/" + id + ".json";
|
|
67014
|
+
fetchOptions = {
|
|
66904
67015
|
signal: options.abortController?.signal,
|
|
66905
67016
|
method: "DELETE"
|
|
66906
|
-
}
|
|
66907
|
-
|
|
66908
|
-
|
|
66909
|
-
|
|
66910
|
-
|
|
67017
|
+
};
|
|
67018
|
+
}
|
|
67019
|
+
this._logger.debug(url);
|
|
67020
|
+
try {
|
|
67021
|
+
const raw$1 = await this._fetch(url, fetchOptions);
|
|
67022
|
+
const json = await raw$1.json().catch(() => null);
|
|
67023
|
+
this._logger.debug(json);
|
|
67024
|
+
if (raw$1.status >= 400 && raw$1.status < 600) {
|
|
67025
|
+
const details = this._extractAbraErrors(json);
|
|
67026
|
+
throw new AFError(AFErrorCode.ABRA_FLEXI_ERROR, `${raw$1.status} ${raw$1.statusText}${details ? ` — ${details}` : ""}`);
|
|
67027
|
+
}
|
|
67028
|
+
const jres = json?.winstrom;
|
|
67029
|
+
if (jres && jres["success"] === "false") {
|
|
67030
|
+
const details = this._extractAbraErrors(json);
|
|
67031
|
+
throw new AFError(AFErrorCode.ABRA_FLEXI_ERROR, `Delete of ${entityPath} failed${details ? ` — ${details}` : ""}`);
|
|
67032
|
+
}
|
|
66911
67033
|
} catch (e) {
|
|
66912
67034
|
if (!(e instanceof AFError)) {
|
|
66913
|
-
|
|
67035
|
+
this._logger.error(e);
|
|
66914
67036
|
e = new AFError(AFErrorCode.UNKNOWN, e.toString());
|
|
66915
67037
|
}
|
|
66916
67038
|
throw e;
|
|
66917
67039
|
}
|
|
66918
67040
|
}
|
|
66919
|
-
async delete(entity, options) {
|
|
67041
|
+
async delete(entity, options = {}) {
|
|
66920
67042
|
if (entity.isNew) return true;
|
|
66921
|
-
const
|
|
67043
|
+
const entityPath = entity.constructor.EntityPath;
|
|
67044
|
+
const res = this.deleteRaw(entityPath, entity.id, {
|
|
67045
|
+
...options,
|
|
67046
|
+
asUserRelation: entity instanceof AFUzivatelskaVazba
|
|
67047
|
+
});
|
|
66922
67048
|
try {
|
|
66923
67049
|
await res;
|
|
66924
67050
|
return true;
|
|
66925
67051
|
} catch (e) {
|
|
66926
67052
|
if (!(e instanceof AFError)) {
|
|
66927
|
-
|
|
67053
|
+
this._logger.error(e);
|
|
66928
67054
|
e = new AFError(AFErrorCode.UNKNOWN, e.toString());
|
|
66929
67055
|
}
|
|
66930
67056
|
throw e;
|
|
66931
67057
|
}
|
|
66932
67058
|
}
|
|
66933
|
-
async
|
|
67059
|
+
async callEntityActionRaw(entityPath, id, actionName, options = {}) {
|
|
66934
67060
|
if (!this.company || !this.company.length) throw new AFError(AFErrorCode.MISSING_ABRA_COMPANY, `Can't query AFApiClient without providing company path component first.`);
|
|
66935
|
-
|
|
66936
|
-
if (!
|
|
66937
|
-
const
|
|
66938
|
-
|
|
67061
|
+
if (id === void 0 || id === null || id === "") throw new AFError(AFErrorCode.MISSING_ID, `Can't call action '${actionName}' on ${entityPath} without id.`);
|
|
67062
|
+
if (!actionName || !actionName.length) throw new AFError(AFErrorCode.UNKNOWN, `Action name must be a non-empty string.`);
|
|
67063
|
+
const url = this._url + "/c/" + this.company + "/" + entityPath + ".json";
|
|
67064
|
+
this._logger.debug(url);
|
|
66939
67065
|
try {
|
|
66940
67066
|
const raw$1 = await this._fetch(url, {
|
|
66941
67067
|
signal: options.abortController?.signal,
|
|
66942
67068
|
method: "PUT",
|
|
67069
|
+
headers: { "Content-Type": "application/json" },
|
|
66943
67070
|
body: JSON.stringify({ winstrom: [{
|
|
66944
67071
|
[entityPath]: { id },
|
|
66945
|
-
[entityPath + "@action"]:
|
|
67072
|
+
[entityPath + "@action"]: actionName
|
|
66946
67073
|
}] })
|
|
66947
67074
|
});
|
|
66948
|
-
|
|
66949
|
-
|
|
66950
|
-
|
|
66951
|
-
|
|
67075
|
+
const json = await raw$1.json().catch(() => null);
|
|
67076
|
+
this._logger.debug(json);
|
|
67077
|
+
if (raw$1.status >= 400 && raw$1.status < 600) {
|
|
67078
|
+
const details = this._extractAbraErrors(json);
|
|
67079
|
+
throw new AFError(AFErrorCode.ABRA_FLEXI_ERROR, `${raw$1.status} ${raw$1.statusText}${details ? ` — ${details}` : ""}`);
|
|
67080
|
+
}
|
|
67081
|
+
const jres = json?.winstrom;
|
|
67082
|
+
if (jres && jres["success"] === "false") {
|
|
67083
|
+
const details = this._extractAbraErrors(json);
|
|
67084
|
+
throw new AFError(AFErrorCode.ABRA_FLEXI_ERROR, `Action '${actionName}' on ${entityPath} failed${details ? ` — ${details}` : ""}`);
|
|
67085
|
+
}
|
|
67086
|
+
return true;
|
|
66952
67087
|
} catch (e) {
|
|
66953
67088
|
if (!(e instanceof AFError)) {
|
|
66954
|
-
|
|
67089
|
+
this._logger.error(e);
|
|
66955
67090
|
e = new AFError(AFErrorCode.UNKNOWN, e.toString());
|
|
66956
67091
|
}
|
|
66957
67092
|
throw e;
|
|
66958
67093
|
}
|
|
66959
67094
|
}
|
|
67095
|
+
async callEntityAction(entity, actionName, options = {}) {
|
|
67096
|
+
if (entity.isNew) throw new AFError(AFErrorCode.RELATED_INSTANCE_NOT_SAVED, `Can't call action '${actionName}' on an unsaved ${entity.constructor.EntityName}. Save it first.`);
|
|
67097
|
+
if (entity.id === void 0 || entity.id === null) throw new AFError(AFErrorCode.MISSING_ID, `Can't call action '${actionName}' on ${entity.constructor.EntityName} without id.`);
|
|
67098
|
+
const entityPath = entity.constructor.EntityPath;
|
|
67099
|
+
return this.callEntityActionRaw(entityPath, entity.id, actionName, options);
|
|
67100
|
+
}
|
|
67101
|
+
_applySaveResultToEntity(entity, results) {
|
|
67102
|
+
if (!Array.isArray(results) || !results.length) return;
|
|
67103
|
+
const entityPath = entity.constructor.EntityPath;
|
|
67104
|
+
let r = results.find((res) => res && typeof res.ref === "string" && res.ref.includes(`/${entityPath}/`));
|
|
67105
|
+
if (!r) {
|
|
67106
|
+
const refless = results.filter((res) => res && typeof res.ref !== "string");
|
|
67107
|
+
if (refless.length === 1 && results.length === 1) r = refless[0];
|
|
67108
|
+
}
|
|
67109
|
+
if (!r || r.id === void 0 || r.id === null) return;
|
|
67110
|
+
const newId = typeof r.id === "number" ? r.id : Number(r.id);
|
|
67111
|
+
if (Number.isFinite(newId)) {
|
|
67112
|
+
entity.id = newId;
|
|
67113
|
+
entity._orig.id = newId;
|
|
67114
|
+
}
|
|
67115
|
+
}
|
|
67116
|
+
_extractAbraErrors(json) {
|
|
67117
|
+
if (!json) return "";
|
|
67118
|
+
const winstrom = json.winstrom;
|
|
67119
|
+
if (!winstrom) return "";
|
|
67120
|
+
const messages = [];
|
|
67121
|
+
if (typeof winstrom.message === "string" && winstrom.message.length) messages.push(winstrom.message);
|
|
67122
|
+
const results = winstrom.results;
|
|
67123
|
+
if (Array.isArray(results)) for (const r of results) {
|
|
67124
|
+
if (!r || !Array.isArray(r.errors)) continue;
|
|
67125
|
+
for (const err of r.errors) {
|
|
67126
|
+
if (!err) continue;
|
|
67127
|
+
if (typeof err === "string") {
|
|
67128
|
+
messages.push(err);
|
|
67129
|
+
continue;
|
|
67130
|
+
}
|
|
67131
|
+
const parts = [];
|
|
67132
|
+
if (err.code) parts.push(`[${err.code}]`);
|
|
67133
|
+
if (err.for) parts.push(`(${err.for})`);
|
|
67134
|
+
if (err.message) parts.push(err.message);
|
|
67135
|
+
if (parts.length) messages.push(parts.join(" "));
|
|
67136
|
+
}
|
|
67137
|
+
}
|
|
67138
|
+
return messages.join("; ");
|
|
67139
|
+
}
|
|
66960
67140
|
_decodeEntityObj(entity, obj) {
|
|
66961
67141
|
if (!obj) return [];
|
|
66962
67142
|
if (typeof obj === "string") {
|
|
@@ -66968,6 +67148,7 @@ var AFApiClient = class {
|
|
|
66968
67148
|
const ent = new entity(this._stitkyCache);
|
|
66969
67149
|
const oKeys = Object.keys(o);
|
|
66970
67150
|
for (const okey of oKeys) this._decodeProperty(ent, okey, o);
|
|
67151
|
+
ent._isNew = false;
|
|
66971
67152
|
res.push(ent);
|
|
66972
67153
|
}
|
|
66973
67154
|
return res;
|
|
@@ -67024,7 +67205,7 @@ var AFApiClient = class {
|
|
|
67024
67205
|
return;
|
|
67025
67206
|
}
|
|
67026
67207
|
if (!(val instanceof AFEntity)) throw new AFError(AFErrorCode.UNKNOWN, `Key '${key}' on ${entity.constructor.EntityName}(id: ${entity.id}) referencing not AFEntity instance`);
|
|
67027
|
-
if (val.isNew) throw new AFError(AFErrorCode.RELATED_INSTANCE_NOT_SAVED, `Key '${key}' on ${entity.constructor.EntityName}(id: ${entity.id})
|
|
67208
|
+
if (val.isNew) throw new AFError(AFErrorCode.RELATED_INSTANCE_NOT_SAVED, `Key '${key}' on ${entity.constructor.EntityName}(id: ${entity.id}) references an unsaved instance. Save it first, or use createIdStub() to reference an existing entity by id/kod.`);
|
|
67028
67209
|
if (typeof val.id === "undefined") obj[key] = `code:${val.kod}`;
|
|
67029
67210
|
else obj[key] = val.id;
|
|
67030
67211
|
return;
|
|
@@ -67034,6 +67215,28 @@ var AFApiClient = class {
|
|
|
67034
67215
|
if (entity instanceof AFPriloha && key === "content") obj["content@encoding"] = "base64";
|
|
67035
67216
|
}
|
|
67036
67217
|
};
|
|
67218
|
+
function makeFilteringLogger(target, level) {
|
|
67219
|
+
const threshold = LOG_LEVEL_RANK[level];
|
|
67220
|
+
const make = (lvl) => {
|
|
67221
|
+
if (LOG_LEVEL_RANK[lvl] > threshold) return () => {};
|
|
67222
|
+
return (...args) => target[lvl](...args);
|
|
67223
|
+
};
|
|
67224
|
+
return {
|
|
67225
|
+
debug: make("debug"),
|
|
67226
|
+
info: make("info"),
|
|
67227
|
+
warn: make("warn"),
|
|
67228
|
+
error: make("error")
|
|
67229
|
+
};
|
|
67230
|
+
}
|
|
67231
|
+
function parseContentDispositionFilename(header) {
|
|
67232
|
+
if (!header) return void 0;
|
|
67233
|
+
const ext = /filename\*=(?:UTF-8'')?([^;]+)/i.exec(header);
|
|
67234
|
+
if (ext) try {
|
|
67235
|
+
return decodeURIComponent(ext[1].trim().replace(/^"|"$/g, ""));
|
|
67236
|
+
} catch {}
|
|
67237
|
+
const plain = /filename=("([^"]+)"|([^;]+))/i.exec(header);
|
|
67238
|
+
if (plain) return (plain[2] ?? plain[3] ?? "").trim();
|
|
67239
|
+
}
|
|
67037
67240
|
|
|
67038
67241
|
//#endregion
|
|
67039
67242
|
//#region src/abra/AFApiSession.ts
|