Another useful comment: while generating swagger spec ask GPT to provide meaningful OperationId for every endpoint, otherwise the generated impl class will come with generated names for implementation methods like that:

Also this could be a typical copy-paste for a REST API app created in a module.xml in a <module> section:

<CSPApplicationUrl="/travel/api"PasswordAuthEnabled="0"UnauthenticatedEnabled="1"DispatchClass="shvarov.travel.disp"MatchRoles=":{$dbrole}"Recurse="1"UseCookies="2"CookiePath="/travel/api"
       />

where /travel/api is the app name, and shvarov.travel.disp - a generated class vs the swagger spec file and shvarov.travel.spec class.

Hi @Luis Petkovicz!

Consider to try csvgen also?

it will be:

USER>zpm "install csvgen"

to install the package, and here is the usage:

USER>do ##class(community.csvgen).Generate("/folder/filename.csv")

to generate class and import the data into it from an arbitrary csv.

 

Just've published the shvarov-persistent package once installed by
USER>zpm "install shvarov-persistent"

will add shvarov.persistent.base class which can be used as an ancestor after %Persistent, like:

Class yourclass Extends (%Persistent, shvarov.persistent.base)

, which will add two properties:

Property CreatedAt As%TimeStamp [ InitialExpression = {$ZDT($H, 3)} ];Property LastUpdate As%TimeStamp [ SqlComputeCode = {set {*}=$ZDATETIME($HOROLOG,3)}, SqlComputed, SqlComputeOnChange = (%%INSERT, %%UPDATE) ];

@Ben Spead it's great you mentioned %OnAddToSaveSet() triggers - how do you manage cases when records were changed by CREATE/UPDATE SQL query? These triggers not fire in this case, right?

also I always add the same _spec GET endpoint to let swagger have a working specification in docker - the default one doesn't work in docker as IRIS default spec one overrides the host variable to one, that doesn't work.

ClassMethod GetSpec() As%DynamicObject
{

set specname=$p(..%ClassName(1),".impl")

Set spec = {}.%FromJSON(##class(%Dictionary.CompiledXData).%OpenId(specname_".spec||OpenAPI").Data)

Set url = $Select(%request.Secure:"https",1:"http") _ "://"_$Get(%request.CgiEnvs("SERVER_NAME")) _ ":" _ $Get(%request.CgiEnvs("SERVER_PORT")) _ %request.ApplicationSet spec.servers = [{"url" : (url)}]

Quit spec

}

And 3 parameters for the spec class that help: HandleCorsRequest - it is most likely CORS will be needed, applicaton/json to support JSON content and ExposeServerExceptions for debug reasons:

Class shvarov.person.spec Extends%REST.Spec [ ProcedureBlock ]

{

Parameter HandleCorsRequest = 1;Parameter CONTENTTYPE = "application/json";Parameter ExposeServerExceptions = 1;
...

The simplest way to programmatically create a database in IRIS is:

do$SYSTEM.SQL.Execute("CREATE DATABASE MYDB")

A yet another workaround for non-obvious caveat of using %JSON.Adapter  and JSON transport around persistent data is a necessity to add an ID related property to your persistent class, like PersonId in this case:

Property PersonId As%Integer [ Calculated, SqlComputeCode = { set {*}={%%ID}}, SqlComputed ];

This will allow to export ID of a record in DB automatically.

Same when you do updates with records, you need to remove this PersonId JSON from an update request, .e.g like this:

set personDynObj= {}.%FromJSON(person.Read())

do personDynObj.%Remove("PersonId") // Remove PersonId if it exists, as it is calculatedset sc = personObj.%JSONImport(personDynObj)

set sc = personObj.%Save()

Thank you, @Enrico Parisi ! But are you sure about 1.?

I've just created a class:

Class dc.sample.ObjectScript
{

property Name As%String;property name as%String;

}

}

And have a compilation error:

ERROR! In class 'dc.sample.ObjectScript' Property 'Name' from 'dc.sample.ObjectScript' and 'name' from 'dc.sample.ObjectScript' have the same name but differ in case.

How do you mean "use case"? You just shouldn't bother about the case of property names in IRIS while sending a JSON from your frontend to the IRIS REST-API. Like you don't care while sending it vs any SQL engine backend.

Exactly. And as I mentioned above, you cannot compile such a class with properties that differ only in case. What are the benefits of properties being case sensitive? Don't see any.

Right. So, what is the reason, or if you may, what are the benefits of properties to be case sensitive?

Thank you, Kai! Do you have any examples where the case-sensitive principle can be used, e.g., with C++ or C# and InterSystems ObjectScript class properties? 

I agree. I changed it to "not read-only" as I wasn't to manage unit-tests without it :) 

Don't know how to mark an object "modified" - otherwise, %Save() doesn't trigger the calculated property to update.

But I agree - read only is much better.

@Justin Millette, there are more settings to enable in the system to allow delegated access, e.g. a system-wide setting, mentioned in this great @Pravin Barton's article , also there is another one from @Yuri Marx 
 

Also, I don't recommend using the WebApplication tag as it is not working properly yet; there is at least one important bug not solved: for example , CSPApplication works quite well. 

Also, I see %all - I hope this is for development/demo usage only, as it is quite a generous role to use.

Exciting initiative!

I think this line in Update is "orphaned":

set myobj = ##class(%Library.DynamicObject).%FromJSON(%request.Content)