go to post Rubens Silva · Nov 13, 2019 Ahh I see, and what does it assume if there's no value defined there? I just zwrite'd it to check if there was any. Does it also modifies what the default Apache sets in the Content-Type? Checking for the following lines in %CSP.Routine: If charset="" { Set charset=##class(%SYS.NLS.Table).GetCSPTable() If charset="" Set charset=$get(^%SYS("CSP","DefaultFileCharset")) } If charset'="" { If ##class(%Net.Charset).TranslateTableExists(charset) Set i%TranslateTable=##class(%Net.Charset).GetTranslateTable(charset) } seems to mean that the RAW TranslateTable is used when none is located. Which charset does RAW defaults to? EDIT: I checked your answer because you already gave me a lead. Also, looks like ISO-8859-1 is indeed RAW. w ##class(%Net.Charset).GetTranslateTable("iso-8859-1") RAW
go to post Rubens Silva · Nov 12, 2019 You need to generate a SSL configuration and provide to your request object by using the SSLConfiguration property, after this you must also inform to your request that you want to use a secure connection by enabling the property Https. Here's how we send a push using OneSignal: set client = ##class(%Net.HttpRequest).%New() set client.Server = "onesignal.com" // You'll need to generate the configuration to be used below, you can decide its name. set client.SSLConfiguration = "OneSignal SSL Config" set client.Https = 1 set client.Authorization = $$$FormatText("Basic %1", $get(^App.Envs("ONESIGNAL_KEY"))) set client.ContentCharset = "utf-8" set client.ContentType = "application/json" set client.ContentEncoding = "utf-8" set client.NoDefaultContentCharset = 0 set body = { "app_id": ($get(^App.Envs("ONESIGNAL_APPID"))), "data": (data), "contents": { "en": (message), "pt": (message) }, "filters": (filters) } set json = body.%ToJSON() do client.EntityBody.Write(json) set sc = client.Post("/api/v1/notifications") return sc You can generate that SSL configuration using the portal, you can also something like this: ClassMethod CreateSSLConfigurationIfNoneExists(name As %String) { new $namespace set $namespace = "%SYS" do ##class(Security.SSLConfigs).Get(name, .p) if $data(p) quit set p("CipherList")="ALL:!aNULL:!eNULL:!EXP:!SSLv2" set p("CAFile")="" set p("CAPath")="" set p("CRLFile")="" set p("CertificateFile")="" set p("CipherList")="ALL:!aNULL:!eNULL:!EXP:!SSLv2" set p("Description")="" set p("Enabled")=1 set p("PrivateKeyFile")="" set p("PrivateKeyPassword")="" set p("PrivateKeyType")=2 set p("Protocols")=24 set p("SNIName")="" set p("Type")=0 set p("VerifyDepth")=9 set p("VerifyPeer")=0 do ##class(Security.SSLConfigs).Create(name, .p) }
go to post Rubens Silva · Nov 12, 2019 Yes, that makes sense, however this would increase drastically the difficulty to write/remember the classe name, that's... unless the keyword Import is used. This way the library user could avoid writing the full package name everytime but... I don't see many using that kind of feature as I noticed that most of the Caché developers prefer to write the full class name whenever they need to call it. So we would need that to become a part of our development habit. The only exception is any class that belongs to the %LIbrary package. At least from my experience, I never write down %Library.ThePackageIWant, only %ThePackageIWant. Anyway, the user who downloaded the module would do something like this when using it: Import org.rfns.Frontier Class MyAPI.Router Extends Router { /// And every other call to any classes from Frontier would omit `org.rfns.Frontier`. } Also, I took that naming convention from Java, just to increase the available suggestion.
go to post Rubens Silva · Nov 12, 2019 I think that the developer should have the freedom to name their classes and packages.However the name registered in the ZPM should follow a pattern indeed. I'd suggest the lower case with slashes: like-this.This is the same pattern I use to name my repositories by the way.
go to post Rubens Silva · Sep 30, 2019 Unless its not documented, I think he meant features like mutations and subscriptions.Specially mutations, anything else have a workaround.
go to post Rubens Silva · Sep 19, 2019 "Method of my class" though...@Vandrei de Lima write ##class(Your.Class).YourMethod(arg1, arg2, arg3) // How many args you have.
go to post Rubens Silva · Sep 16, 2019 Hello @Evgeny Shvarov certainly, we are even shifting our development to use the extension I'm making to handle the current Caché projects this week. So I'll be publishing it to the marketplace after our dev team gives the ok on its usability. Meanwhile I can publish it to OpenExchange someday on this week as well, I just need to make sure everything will be working as intended.
go to post Rubens Silva · Sep 9, 2019 Yes, because everything you put between parenthesis is evaluated/casted back to COS language, and since there's no NULL in COS, you get an empty string as value and string as its type.The only way is to have a custom serializer that reads the "null", "false" and "true" and interpret them as it seems fit. This is how I did by the way.
go to post Rubens Silva · Sep 9, 2019 Yes, I'm not having problems with your extension connected to the server, instead I actually think is the best way since most of the data depends on the server already. The problem is that the save event is also being called on my extension, which makes the code to be sent two times to the Caché instance.
go to post Rubens Silva · Sep 9, 2019 Outstanding! @Dmitry Maslennikov I bought you some coffe to celebrate your doings, keep the good work!Now one question, do you think you could add an option to disable the auto-save? I'm thinking on using my extension to complement yours regarding the support for projects. It's not release yet but I plan on doing it very soon.
go to post Rubens Silva · Sep 9, 2019 Sadly, I'm not planning to participate this GlobalSummit due to travel wages and passport issuing time. But we can keep the discussions going by message for now if you want. Also regarding the option you mentioned, this also disables your Atelier IntelliSense integration, could you think of a way to separate the IntelliSense from that option? I tested it and only the local IntelliSense remains.
go to post Rubens Silva · Sep 9, 2019 For now, I think this is more of type Question than Article. You're right, I updated the type to fit the criteria. I also created an issue there. Thanks for the heads up.
go to post Rubens Silva · Sep 6, 2019 Yes, I mentioned the usage of DIrectoryExists to cover this issue. Looks like the most efficient way to check if the file is a directory or not is using the Attributes method and checking the bitflags.
go to post Rubens Silva · Aug 30, 2019 set ts = $zdt($zts, 3) // there's no timezone on it set date = $piece(ts, " ", 1) set time = $piece(ts, " ", 2) return $$$FormatText("%1T%2Z", date, time) // So we force it to use Z. If you use $now(), you'll either need take out the timezone offset or change the Z to -hh:00 / +mm:00 which represents the timezone. So I'd recommend you to use $ztimestamp instead. You can also use the %UTC class's NowUTC() if you are using a recent Caché version, let's say... 2017 onwards. But you still need to edit the value to include the T and Z, since this method also doesn't put it. set ts = ##class(%UTC).NowUTC() // this includes milliseconds precision. set date = $piece(ts, " ", 1) set time = $piece(ts, " ", 2) return $$$FormatText("%1T%2Z", date, time) // So we force it to use Z.
go to post Rubens Silva · Aug 29, 2019 If you don't want to hook Caché with another language using Caché Bindings, you should use PBKDF2 with SHA256. Otherwise you'll need some external implementation to use bcrypt. write $System.Encryption.PBKDF2("secret", 15000, $System.Encryption.GenCryptRand(64), 64, 256) Although IS should really implement bcrypt and Argon with native support.
go to post Rubens Silva · Aug 29, 2019 This brought me to another question. How does the ZPM handle two modules that use the same dependency but both have different versions while being used as peer dependencies? Example: Module A using dependency C requires its major 1. Module B also uses dependency C but requires the newer major 2. The requisite for this case is: You must have both because you're making a module D that uses both module A and B.
go to post Rubens Silva · Aug 29, 2019 Any reasons for it? Are you so lazy, that you can't write this simple XML by hand? Just kidding, not yet, I think best and fastest what I can do it, add Intellisense in vscode for such files, so you can help to do it easier. Any UI, at the moment, is just a waste of time, it is not so important. And anyway, is there any wizard from NPM? Haha, I'll overlook this first line. I meant something like a CLI wizard really, that asks you for steps, but maybe this can be something apart, you know Yeoman don't you? NPM does have the command npm init which asks you the basic information about your package and generates a package.json. It is already there, should work the same as semver in npm Nice! Does it follow the same format as the one from NPM? (symbolically speaking ^ and *) Not sure about contextual root. But if saying about UnitTests, yes actually there are many things which should be changed in the original %UnitTests engine. But in this case, it has some way to run tests without care about UnitTestRoot global. ZPM itself has own module.xml, and look there. You will find lines about UnitTests. with this definition, you run these commands, and it will run tests in different phases. Yeah, that's exactly what I meant about contextual root, my wording looked wrong because I intended for this feature to be used outside UnitTest, but now I see that there isn't much use for it outside of unit testing.
go to post Rubens Silva · Aug 29, 2019 Interesting... however I have some questions: 1 - Is there any plans to automatize the module.xml generation by using something like a Wizard? 2 - Is there any plans to support non-specific dependency versions like NPM does? 3 - Is it possible to run pre/post-install scripts as well? Kind of what installer classes do. 4 - Is also possible to use the module.xmlto provide a contextual root? this way it would be used to run UnitTests without the need of defining (or overwriting) the UnitTestRoot global. I already did it with Port, so it's not hard to implement as you basically have to overwrite the Root method: Class Port.UnitTest.Manager Extends %UnitTest.Manager { ClassMethod Root() As %String { // This provides us the capability to search for tests unrelated to ^UnitTestRoot. return ##class(%File).NormalizeFilename(##class(Port.Configuration).GetWorkspace()) } ClassMethod RunTestsFromWorkspace(projectName As %String, targetClass As %String = "", targetMethod As %String = "", targetSpec As %String = "") As %Status { set recursive = "recursive" set activeProject = $get(^||Port.Project) set ^||Port.Project = projectName if targetClass '= "" set target = ##class(Port.UnitTest.Util).GetClassTestSpec(targetClass) else set target = ##class(Port.Configuration).GetTestPath() if targetMethod '= "" { set target = target_":"_targetMethod set recursive = "norecursive" } set sc = ..RunTest(target_$case(targetSpec, "": "", : ":"_targetSpec), "/"_recursive_"/run/noload/nodelete") set ^||Port.Project = activeProject return sc } }
go to post Rubens Silva · Aug 26, 2019 Try sending the CreatedDate format like this, which is the format used by JSON serializers."2019-08-26T16:38:26.893Z"