/
weylin
/
WtDev
Обзор
Документация
Войти
/
weylin
/
WtDev
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
dev
src/backend/wtdev.js
789 строк
19 KB
Weylin
Увеличен номер версии бэка
27 янв 2026, 19:54
27 янв 2026, 19:54
c0fb334
Код
Авторство
О чём код?
/*#wtdevsync{ "type": "elem", "elem": "custom_web_template", "code": "wtdev", "encloseInAspTags": true }#*/ /* eslint-disable eqeqeq */ BACKEND_VERSION = "b0026"; DOC_FORMS_WITH_CODE = [ "custom_web_template", "remote_action", "remote_collection", "server_agent", ]; SRC_RESOURCE_CODE_SUFFIX = "srcfile"; Server.Execute("include/access_init.html"); function GetBackendInfo() { return { ok: true, backendVersion: BACKEND_VERSION, }; } function UploadFiles(oFiles) { var result = { ok: true, updatedXmlElems: [], updatedFilesCnt: 0, }; var docTpl; var resultContent, mode, curContent, rePattern; for (oFile in oFiles) { if (oFile.type == "file") { resultContent = undefined; mode = oFile.GetOptProperty("mode"); if (mode == "replaceBlock") { //curContent = LoadUrlData(oFile.url); curContent = DecodeCharset(LoadUrlData(oFile.url), "windows-1251"); rePattern = "(\\/\\*BlockStart:" + oFile.block + "\\*\\/[\\r\\n]*)([\\s\\S]*?)([\\r\\n]*\\/\\*BlockEnd:" + oFile.block + "\\*\\/)"; //alert("block: "+oFile.block+" = "+RegExpTest(rePattern, curContent)); if (regExpTest(rePattern, curContent)) { resultContent = regExpReplace( rePattern, curContent, "$1" + oFile.content + "$3" ); } } else { resultContent = oFile.content; } //alert("EncodeJson(oFile): "+EncodeJson(oFile)); if (oFile.HasProperty("application")) { //alert("EncodeJson(oFile.application): "+EncodeJson(oFile.application)); if (tools_web.is_true(oFile.application.GetOptProperty("dropCache"))) { dropApplicationCache(oFile.application.name); } } if (resultContent != undefined) { PutUrlData(oFile.url, EncodeCharset(resultContent, "windows-1251")); DropFormsCache(oFile.url); result.updatedFilesCnt++; } } else if (oFile.type == "elem") { if (oFile.elem == "custom_web_template") { docTpl = tools.get_doc_by_key( "custom_web_template", "code", oFile.code ); if (docTpl != null) { //docTpl.TopElem.html = oFile.content; docTpl.TopElem.exec_code.code_text = oFile.content; docTpl.Save(); result.updatedXmlElems.push(makeWtXmlElemFromDoc(docTpl)); result.updatedFilesCnt++; } } else if (oFile.elem == "remote_collection") { docTpl = tools.get_doc_by_key("remote_collection", "code", oFile.code); if (docTpl != null) { //docTpl.TopElem.html = oFile.content; docTpl.TopElem.exec_code.code_text = oFile.content; docTpl.Save(); result.updatedXmlElems.push(makeWtXmlElemFromDoc(docTpl)); result.updatedFilesCnt++; } } else if (oFile.elem == "remote_action") { docTpl = tools.get_doc_by_key("remote_action", "code", oFile.code); if (docTpl != null) { //docTpl.TopElem.html = oFile.content; docTpl.TopElem.exec_code.code_text = oFile.content; docTpl.Save(); result.updatedXmlElems.push(makeWtXmlElemFromDoc(docTpl)); result.updatedFilesCnt++; } } else if (oFile.elem == "server_agent") { docTpl = tools.get_doc_by_key("server_agent", "code", oFile.code); if (docTpl != null) { //docTpl.TopElem.html = oFile.content; docTpl.TopElem.exec_code.code_text = oFile.content; docTpl.Save(); result.updatedXmlElems.push(makeWtXmlElemFromDoc(docTpl)); result.updatedFilesCnt++; } } } } return result; } function DownloadXmlElems(elemIDs) { var elems = []; var docElem; for (elemID in elemIDs) { docElem = tools.open_doc(elemID); if (docElem == undefined) { continue; } elems.push(makeWtXmlElemFromDoc(docElem)); } //alert("elems: " + EncodeJson(elems)); return { ok: true, elems: elems, }; } function DownloadXmlElemsByPackageScheme(packageSchemeName) { var fldPackage = package_objects.GetOptChildByKey(packageSchemeName, "name"); if (fldPackage == undefined) { return { ok: false, message: "Не найден пакет с указанным именем" }; } var elemIDs = ArrayExtract(fldPackage.objects, "id"); return DownloadXmlElems(elemIDs); } function prepareXmlElemTopElem(docElem) { var teElemCloned = docElem.TopElem.Clone(); if (docElem.Form.TopElem.Name == "resource") { if (!StrEnds(docElem.TopElem.code, SRC_RESOURCE_CODE_SUFFIX)) { teElemCloned.set_data(); } else { teElemCloned.file_url.Clear(); } if (teElemCloned.ChildExists("size")) { teElemCloned.size.Clear(); } if ( teElemCloned.ChildExists("last_data") && teElemCloned.last_data.ChildExists("size") ) { teElemCloned.last_data.size.Clear(); } } if (teElemCloned.ChildExists("cache_vars")) { teElemCloned.cache_vars.Clear(); } if ( ArrayOptFind(DOC_FORMS_WITH_CODE, "This == docElem.Form.TopElem.Name") != undefined ) { if (teElemCloned.ChildExists("html")) { teElemCloned.html.Clear(); } if (teElemCloned.ChildExists("exec_code")) { teElemCloned.exec_code.Clear(); } if (teElemCloned.ChildExists("run_code")) { teElemCloned.run_code.Clear(); } if (teElemCloned.ChildExists("script")) { teElemCloned.script.Clear(); } if (teElemCloned.ChildExists("last_run_date")) { teElemCloned.last_run_date.Clear(); } } teElemCloned.doc_info.modification.Clear(); return teElemCloned; } function makeWtXmlElemFromDoc(docElem) { var teElemCloned = prepareXmlElemTopElem(docElem); return { id: docElem.DocID + "", name: tools.get_disp_name_value(teElemCloned), form: docElem.Form.TopElem.Name + "", xml: teElemCloned.Xml, }; } function makeComparableTopElem(docElem) { var teElemCloned = prepareXmlElemTopElem(docElem); if (docElem.Form.TopElem.Name == "resource") { teElemCloned.file_url = regExpReplace( "(x-local://wt_data/attachments).+/(.*)", teElemCloned.file_url, "$1/something/$2" ); } return teElemCloned; } function makeComparableElemXml(docElem) { return makeComparableTopElem(docElem).Xml; } function isElemChanged(newXmlElem) { var docElem_Stored = tools.open_doc(newXmlElem.id); if (docElem_Stored == undefined) { return true; } docElem_New = OpenNewDoc(getFormPathForCatalog(xmlElem.form)); docElem_New.TopElem.LoadData(newXmlElem.xml); var teElem_Stored = makeComparableTopElem(docElem_Stored); var teElem_New = makeComparableTopElem(docElem_New); return teElem_Stored.Xml != teElem_New.Xml; } function UploadXmlElems(xmlElems, options) { options = setDefaultOptions(options, { updateAll: false, }); var docElem; var resourceFileType; var uploadedXmlsCount = 0; var updatedElemIds = []; alert("ArrayCount(xmlElems): " + ArrayCount(xmlElems)); for (xmlElem in xmlElems) { if (!options.updateAll && !isElemChanged(xmlElem)) { continue; } docElem = OpenNewDoc(getFormPathForCatalog(xmlElem.form)); docElem.TopElem.LoadData(xmlElem.xml); docElem.Save(UrlFromDocID(Int(xmlElem.id))); uploadedXmlsCount++; if (xmlElem.form == "resource" && docElem.TopElem.ChildExists("data")) { try { resourceFileType = docElem.TopElem.type; docElem.TopElem.put_str( Base64Decode(docElem.TopElem.data), docElem.TopElem.file_name ); docElem.TopElem.type = resourceFileType; docElem.TopElem.data.Clear(); docElem.Save(); } catch (e) { alert("error in UploadXmlElems resource loading: " + e); } } else if (xmlElem.form == "notification") { docElem.TopElem.notification_systems.Clear(); docElem.Save(); } updatedElemIds.push(docElem.DocID + ""); } //alert("updatedElemIds: " + EncodeJson(updatedElemIds)); return { ok: true, uploadXmlsCount: uploadedXmlsCount, updatedElemIds: updatedElemIds, }; } function getFormPathForCatalog(catalog) { var formPath = "x-local://wtv/wtv_" + catalog + ".xmd"; if (!FilePathExists(UrlToFilePath(formPath))) { formPath = "x-local://qti/qti_" + catalog + ".xmd"; } if (!FilePathExists(UrlToFilePath(formPath))) { formPath = "x-local://udt/udt_" + catalog + ".xmd"; } alert("formPath: " + formPath); return formPath; } function findPackageElemIDs(packageElems) { var elemIDs = []; var xElem, xElems; for (packageElem in packageElems) { if (packageElem.HasProperty("id")) { elemIDs.push(OptInt(packageElem.id)); } else if (packageElem.HasProperty("catalog")) { if (packageElem.HasProperty("code")) { xElem = getElemByKey(packageElem.catalog, { code: packageElem.code }); if (xElem != undefined) { elemIDs.push(OptInt(xElem.id)); } } else if (packageElem.HasProperty("byXQueryWhere")) { xElems = ArraySelectAll( XQuery( "for $elem in " + packageElem.catalog + "s where " + packageElem.byXQueryWhere + " return $elem" ) ); //alert("byXQueryWhere ArrayCount(xElems): " + ArrayCount(xElems)); elemIDs = ArrayExtract(xElems, "id"); } } } return elemIDs; } function CreatePackage(elemIDs, options) { options = setDefaultOptions(options, { skipMissingElems: false, excludedElems: [], }); var docPackages = tools.new_doc_by_name("package_objects"); var fldPackage = docPackages.TopElem.AddChild(); var docElem; var addedElemsCount = 0; elemIDs = ArrayExtract(elemIDs, "OptInt(This)"); var excludedElemIDs = findPackageElemIDs(options.excludedElems); elemIDs = arraySubtract(elemIDs, excludedElemIDs); for (elemID in elemIDs) { docElem = tools.open_doc(elemID); if (docElem == undefined) { if (options.skipMissingElems) { continue; } else { return { ok: false, message: "На стенде отсутствует один или несколько запрошенных элементов", }; } } tools.add_object_to_package(null, elemID, undefined, fldPackage, { apply_to_all: true, }); addedElemsCount++; } var sTempUrl = "x-local://trash/temp/bbb" + tools.random_string(10) + ".zip"; tools.create_list_package(sTempUrl, fldPackage); var result = { ok: true, elemsCount: addedElemsCount, dataB64: Base64Encode(LoadUrlData(sTempUrl)), }; //alert("CreatePackage result: " + EncodeJson(result)); DeleteFile(sTempUrl); return result; } function InstallPackage(dataB64) { var tempFileUrl = "x-local://trash/temp/bbb" + tools.random_string(10) + ".zip"; var tempFilePath = UrlToFilePath(tempFileUrl); var fileData = Base64Decode(dataB64); alert("dataB64 length: " + StrLen(dataB64)); alert("fileData length: " + StrLen(fileData)); alert("tempFileUrl: " + tempFileUrl); alert("tempFilePath: " + tempFilePath); PutFileData(tempFilePath, fileData); tools.process_package(tempFileUrl); if (FileExists(tempFilePath)) { DeleteFile(tempFilePath); } return { ok: true }; } function GetXmlElemStamps(elemIDs) { var docElem; var stamps = []; var elemXml; var elemHash; for (elemID in elemIDs) { docElem = tools.open_doc(elemID); if (docElem != undefined) { elemXml = makeComparableElemXml(docElem); elemHash = Md5Hex(elemXml); } else { //elemHash = Md5Hex("not found"); // TODO upload на фронте отсутствющих на бэке continue; } stamps.push({ id: OptInt(elemID) + "", hash: StrLowerCase(elemHash), }); } return { ok: true, stamps: stamps, }; } function getFileResourceID(resourceCode, fileName) { var xResource = ArrayOptFirstElem( XQuery( " \ for $elem in resources \ where\ $elem/code = " + XQueryLiteral(resourceCode) + " \ and $elem/name = " + XQueryLiteral(fileName) + " \ return $elem \ " ) ); return xResource != undefined ? xResource.id : undefined; } function saveFileDataAsResource(fileData, resourceCode, fileName, resourceID) { var docResource; if (resourceID != undefined) { docResource = tools.open_doc(resourceID); } else { docResource = tools.new_doc_by_name("resource"); docResource.BindToDb(DefaultDb); docResource.TopElem.code = resourceCode; } docResource.TopElem.put_str(fileData, fileName); //docResource.TopElem.put_data(FilePathToUrl(filePath)); docResource.Save(); return docResource; } function obtainFileResourceDoc(resourceCode, filename) { var xResource = ArrayOptFirstElem( XQuery( " \ for $elem in resources \ where\ $elem/code = " + XQueryLiteral(resourceCode) + " \ and $elem/name = " + XQueryLiteral(filename) + " \ return $elem \ " ) ); var docResource; if (xResource != undefined) { docResource = tools.open_doc(xResource.id); } else { docResource = tools.new_doc_by_name("resource"); docResource.BindToDb(DefaultDb); docResource.TopElem.code = resourceCode; } return docResource; } function SaveFilesAsResources(preparedResources) { alert("SaveFilesAsResources..."); alert("ArrayCount(preparedResources): " + ArrayCount(preparedResources)); //alert("EncodeJson(preparedResources): " + EncodeJson(preparedResources)); var docResource; var savedResources = []; var updatedXmlElems = []; var fileMustBeUpdated; for (preparedResource in preparedResources) { docResource = obtainFileResourceDoc( preparedResource.code, preparedResource.name ); teResource_Comparable = makeComparableTopElem(docResource); fileMustBeUpdated = docResource.TopElem.file_url == "" || Base64Encode(LoadUrlData(docResource.TopElem.file_url)) != preparedResource.data; if (!fileMustBeUpdated) { continue; } docResource.TopElem.put_str( Base64Decode(preparedResource.data), preparedResource.name ); //docResource.TopElem.put_data(FilePathToUrl(filePath)); docResource.Save(); savedResources.push({ //path: folderElemPath, name: preparedResource.name, link: "/download_file.html?file_id=" + docResource.DocID, }); updatedXmlElems.push(makeWtXmlElemFromDoc(docResource)); } alert("packedElems: " + EncodeJson(savedResources)); return { ok: true, savedResources: savedResources, updatedXmlElems: updatedXmlElems, }; } function RunTests(oTests, oFiles) { var testResults = []; var oFile, result; for (oTest in oTests) { oFile = ArrayOptFind(oFiles, "This.url == oTest.url"); if (oFile == undefined) { continue; } result = runTest(oFile, oTest.id); testResults.push({ id: oTest.id, url: oTest.url, passed: result.passed, errored: result.errored, message: result.message, duration: result.duration, output: result.output, }); } return { ok: true, testResults: testResults, }; } function changeAlertsToTestAlerts(codeStr) { return regExpReplace("(^|\\W+)alert(\\s*\\()", codeStr, "$1testAlert$2"); } function dropEnclosingAspTags(codeStr) { codeStr = regExpReplace("^\\s*\\<\\%", codeStr, ""); codeStr = regExpReplace("^\\s*\\%\\>", codeStr, ""); return codeStr; } function testFailed(message) { throw new Error("***" + message); } function runTest(codeFile, funcName) { var TEST_MESSAGES = []; function testAlert(message) { TEST_MESSAGES.push(message); alert(message); } var result = { passed: false, errored: false, message: "", duration: 0, output: "", }; var startTicks = GetCurTicks(); var TEST_MODE = true; try { var codeParts = []; var docTpl; if (codeFile.HasProperty("includedWebTemplates")) { for (webTemplateCode in codeFile.includedWebTemplates) { docTpl = tools.get_doc_by_key( "custom_web_template", "code", webTemplateCode ); if (docTpl == null) { throw new Error( 'Web template with code "' + webTemplateCode + '" not found' ); } codeParts.push( dropEnclosingAspTags(docTpl.TopElem.exec_code.code_text) ); } } codeParts.push(changeAlertsToTestAlerts(codeFile.content)); codeParts.push(funcName + "();"); var codeStr = codeParts.join("\n\n\n"); if (codeFile.GetOptProperty("outerAlertsToConsole")) { codeStr = changeAlertsToTestAlerts(codeStr); } eval(codeStr); result.passed = true; } catch (e) { if (StrBegins(e.message, "***")) { result.passed = false; result.message = StrReplaceOne(e.message, "***", ""); } else { result.errored = true; result.message = "Error: " + e; testAlert(e); } } var endTicks = GetCurTicks(); result.duration = endTicks - startTicks; result.output = TEST_MESSAGES.join("\r\n") + (TEST_MESSAGES.length > 0 ? "\r\n" : ""); return result; } try { alert("wtupload..."); //alert(Request.Body); data = DecodeJson(Request.Body); alert("data.action: " + data.action); if (data.requiredBackendVersion != BACKEND_VERSION) { Response.Write(EncodeJson({ ok: false, isBackendVersionWrong: true })); } else if (data.action == "UploadFiles") { result = UploadFiles(data.files); Response.Write(EncodeJson(result)); // } else if (data.action == "DownloadXmlElems") { result = DownloadXmlElems(data.elemIds); Response.Write(EncodeJson(result)); // } else if (data.action == "DownloadXmlElemsByPackageScheme") { result = DownloadXmlElemsByPackageScheme(data.packageSchemeName); Response.Write(EncodeJson(result)); // } else if (data.action == "UploadXmlElems") { result = UploadXmlElems(data.xmlElems, data.GetOptProperty("options")); Response.Write(EncodeJson(result)); // } else if (data.action == "CreatePackage") { result = CreatePackage(data.elemIDs, { skipMissingElems: data.skipMissingElems, excludedElems: data.excludedElems, }); Response.Write(EncodeJson(result)); // } else if (data.action == "InstallPackage") { result = InstallPackage(data.dataB64); Response.Write(EncodeJson(result)); // } else if (data.action == "GetXmlElemStamps") { result = GetXmlElemStamps(data.elemIds); Response.Write(EncodeJson(result)); // } else if (data.action == "UploadFilesToResources") { result = SaveFilesAsResources(data.uploads); Response.Write(EncodeJson(result)); // } else if (data.action == "GetBackendInfo") { result = GetBackendInfo(); Response.Write(EncodeJson(result)); // } else if (data.action == "RunTests") { result = RunTests(data.tests, data.files); Response.Write(EncodeJson(result)); // } else { Response.Write(EncodeJson({ ok: false, message: "No such api method" })); } alert("wtupload done."); } catch (e) { Response.Write(EncodeJson({ ok: false, message: "error in wtupload: " + e })); alert("error in wtupload: " + e); }