123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670 |
- package tst
- import (
- "fmt"
- "strings"
- . "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/common" // . "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/gen"
- TS "git.eugeniocarvalho.dev/eugeniucarvalho/gg/generators/typescript"
- )
- var (
- FormatMap map[string]string
- // TemplatesMethods = map[string]func(p *Project, method *Method) (*G.Statement, error){
- // "post": GenCreateStmts,
- // "put": GenUpdateStmts,
- // "delete": GenDeleteStmts,
- // "get_one": GenGetStmtsOne,
- // "get_list": GenGetStmtsList,
- // }
- angularServiceOption = []TS.CodeInterface{}
- angularServiceOptionMap = map[string]string{}
- )
- func GenResources(p *Project) {
- var (
- // angularServiceStmtName string
- angularResourceName string
- ServiceStmt = "ServiceStmt"
- // angularServiceMethods []TS.CodeInterface
- angularServiceStmtMethods []TS.CodeInterface
- )
- // imports(module)
- // module.Line().Export().Class().Id(ServiceStmt).Block(
- // TS.Public().Id("Url").Call(TS.Raw("u: string, options:{}")).Op(":").String().Block(
- // TS.Raw(""),
- // ),
- // ).Line()
- module.Line().Raw(`
- export type HttpOptions = {
- headers?: HttpHeaders;
- params?: any;
- withCredentials?: boolean;
- id?: string;
- } & {
- [prop: string]: any;
- };
-
- export class ServiceStmt {
-
- // constructor(protected api: `).Id(ApiClassName(p)).Raw(`) {}
- constructor(protected api: ApiInterface) {
- }
-
- get authorized$(){
- // return this.api.Auth.Authorize()
- return this.api.Auth.grant
- ? of(true)
- : this.api.Auth.Authorize().pipe(map(() => true))
- }
- public Url(u: string, opts: {}): string {
-
- (u.match(/{(\w+)}/gm)||[]).map(argExpression => {
- const
- prop = argExpression.replace(/({|})/gm,''),
- value = opts[prop];
- if (!value) { throw Error(`).Raw("`Url params '${prop}' is required`").Raw(`);}
- u = u.replace(argExpression, value);
- });
- return u;
- }
-
- _event<T = any>(url, opt: HttpOptions): Observable<EventSourcePolyfill> {
- opt = this.api.options(opt);
- const _url = new URL(this.Url(url, opt)), { params = null } = opt;
- if (params) {
- params.map.forEach((values, prop) => values.map(value => _url.searchParams.append(prop, value)));
- }
- return new Observable(o => o.next(new EventSourcePolyfill(
- _url.toString(),
- { heartbeatTimeout: 86400000, headers: { Authorization: this.api.Auth.Token() } },
- ))).pipe(take(1));
- }
-
- _get<T = any>(url, opt: HttpOptions):Observable<T> {
- opt = this.api.options(opt);
- return this.api.http.get<any>(this.Url(url, opt), opt).pipe(take(1));
- }
-
- _put<T = any>(url, entity: any, opt: HttpOptions):Observable<T> {
- opt = this.api.options(opt);
- return this.api.http.put<any>(this.Url(url, opt), entity, opt).pipe(take(1));
- }
-
- _patch<T = any>(url, entity: any, opt: HttpOptions):Observable<T> {
- opt = this.api.options(opt);
- return this.api.http.patch<any>(this.Url(url, opt), entity, opt).pipe(take(1));
- }
-
- _post<T = any>(url, entity: any, opt: HttpOptions):Observable<T> {
- opt = this.api.options(opt);
- return this.api.http.post<any>(this.Url(url, opt), entity, opt).pipe(take(1));
- }
-
- _delete<T = any>(url, opt: HttpOptions) {
- opt = this.api.options(opt);
- return this.api.http.delete<any>(this.Url(url, opt), opt).pipe(take(1));
- }
- }`).Line()
- for _, resource := range p.Resources {
- FormatMap = map[string]string{}
- // angularServiceMethods = []TS.CodeInterface{}
- angularServiceStmtMethods = []TS.CodeInterface{}
- angularResourceName = strings.Title(resource.ID) + "Service"
- module.Comment(resource.Description).Line()
- // angularServiceMethods = append(angularServiceMethods, TS.Constructor(
- // TS.Protected().Id("api").Op(":").Id(ApiClassName(p)),
- // ).Block(
- // // TS.This().Dot("Url").Op("="),
- // ))
- // angularServiceStmtMethods = append(angularServiceStmtMethods, TS.Public().Id("Url").Op(":").String())
- // angularServiceStmtMethods = append(angularServiceStmtMethods, TS.Constructor(
- // TS.Protected().Id("api").Op(":").Id(ApiClassName(p)),
- // TS.Protected().Id("options").Op(":").Id("ServiceOptions"),
- // ).Block(
- // // TS.Raw("this.url").Op("=").Lit(p.UrlFromMethod()).Endl(),
- // TS.Raw("super();"),
- // TS.Raw("if (this.options == null)").Block(
- // // TS.Raw("this.options = new ServiceOptions();"),
- // TS.Raw("this.options = {};"),
- // ),
- // // TS.Super().Call(TS.Id("options")),
- // ))
- // angularServiceStmtName = angularResourceName + "Stmt"
- // angularServiceMethods = append(angularServiceMethods, TS.Id("Options").Params(
- // TS.Id("options?").Op(":").Id("ServiceOptions"),
- // ).Op(":").Id(angularServiceStmtName).Block(
- // TS.Return().New().Id(angularServiceStmtName).Call(
- // TS.Id("this.api"),
- // TS.Id("options"),
- // ),
- // ).Line())
- // angularServiceStmtMethods = append(angularServiceStmtMethods, TS.Line().Raw(`
- // options(opts?: HttpOptions): this {
- // opts && Object.assign(this.opts, opts)
- // return this;
- // }`).Line())
- for _, method := range resource.Methods {
- // if method.Template == "implement" {
- // continue
- // }
- GenAngularMethodStmt(
- p,
- resource,
- method,
- &angularServiceStmtMethods,
- angularResourceName,
- )
- // Vai ser usado no metodo de construcao da classe chamado em createAngularService
- for paramName, param := range method.Parameters {
- // fmt.Println("param >>>>>>>>>", resource.ID, method.ID, paramName)
- if _, find := angularServiceOptionMap[paramName]; find {
- continue
- }
- angularServiceOptionMap[paramName] = param.Location
- angularServiceOption = append(angularServiceOption,
- TS.Comment(param.Description).Id(paramName+"?").Op(":").Id(TS.ConvType(param.Type)).Endl(),
- )
- }
- }
- module.Line().Export().Class().Id(
- angularResourceName,
- // ).Extends().Id(fmt.Sprintf("%s<%s>",ServiceStmt, resource.Entity )).Block(
- ).Extends().Id(fmt.Sprintf("%s", ServiceStmt)).Block(
- angularServiceStmtMethods...,
- ).Line()
- // module.Line().Export().Class().Id(
- // angularResourceName,
- // ).Block(
- // angularServiceMethods...,
- // ).Line()
- }
- // Cria o arquivo de servido da api
- createAngularService(p, module)
- // Fim do laco de recurso
- // Salva o arquivo do modulo
- }
- func ApiClassName(p *Project) string {
- return p.Name + "Api"
- }
- func createAngularService(p *Project, module *TS.File) error {
- // var (
- // service = Ts.NewFile("api.service.ts")
- // )
- // Define a class que representa uma resposta da api
- // "Class gerencia todos os serviços da api.",
- module.Export().Interface().Id("ServiceResponse<T = any>").Block(
- TS.Raw("resultSizeEstimate: number;"),
- TS.Raw("nextPageToken: string;"),
- TS.Raw("entity?:T;"),
- TS.Raw("itens?:T[];"),
- )
- // Define todos os parametros atribuiveis as opcoes de uma requisicao da api
- module.Line().Export().Interface().Id("ServiceOptions").BlockFun(func(g *TS.Group) {
- g.Stmts = angularServiceOption
- })
- //
- createClientClass(p, module)
- //
- createAuthClass(p, module)
- module.Line().Comment("Objeto acessivel pelo usuario para realizar requisicoes à api.").Raw(`
- @Injectable({ providedIn: 'root' })
- // @Injectable()
- export class `).Raw(ApiClassName(p)).Raw(` {
- public Client: Client;
- // public BASE_URL = environment.BASE_URL;
- public Auth: Auth;
- // public queryParams: any = {};
- public poolReady = [];
- public httpOptions = {
- headers: new HttpHeaders({
- 'Content-Type': 'application/json',
- 'Accept': 'application/json'
- }),
- withCredentials: true,
- };
- constructor(
- public http: HttpClient,
- // public route: ActivatedRoute,
- // public router: Router,
- // @Inject(ApiOptionsParams) public apiOptions: `).Raw(ApiClassName(p) + "Options").Raw(`,
- public apiOptions: `).Raw(ApiClassName(p) + "Options").Raw(`,
- ) {
- console.log('apiOptions `).Raw(ApiClassName(p)).Raw(`',apiOptions);
- // this.route.queryParams.subscribe(params => { this.queryParams = params; });
- this.Client = new Client(this);
- if (Boolean(window[oauthWindowProp])) {
- this.Auth = window[oauthWindowProp];
- } else {
- this.Auth = window[oauthWindowProp] = new Auth(this);
- }
- }
- onready(fn: () => void) {
- this.Auth.onAuthorize$.pipe(filter(grant => Boolean(grant))).subscribe(fn);
- // if (this.Auth.grant) {
- // fn();
- // } else {
- // this.poolReady.push(fn);
- // }
- }
- // options(opts?: HttpOptions): HttpOptions {
- // console.log({ ...this.httpOptions.headers });
- // opts = Object.assign(
- // {
- // headers: new HttpHeaders({
- // ...this.httpOptions.headers,
- // }),
- // params: {},
- // },
- // opts
- // );
-
- // // const headers = {
- // // Authorization: this.Auth.Token(),
- // // };
-
- // opts.headers.set("Authorization", this.Auth.Token());
-
- // //this.copyHeader(this.httpOptions.headers, headers);
- // //this.copyHeader(opts.headers, headers);
-
- // const params = opts.params;
- // // Converte a query para base64
- // if (params.q) {
- // params.q = window.btoa(unescape(encodeURIComponent(params.q)));
- // }
-
- // // delete opts.headers;
- // // delete opts.params;
-
- // // const options = Object.assign(
- // // {
- // // headers: new HttpHeaders(headers),
- // // params: new HttpParams({ fromObject: params }),
- // // },
- // // opts
- // // );
-
- // // const options = Object.assign({
- // // headers: new HttpHeaders(hopts),
- // // params: {}
- // // }, opts);
-
- // // // Converte a query para base64
- // // if (options.params.q) {
- // // options.params.q = window.btoa(unescape(encodeURIComponent(options.params.q)));
- // // }
-
- // return opts;
- // }
-
- options(opts?: HttpOptions): HttpOptions {
- opts = Object.assign({
- headers: new HttpHeaders(),
- params: {},
- }, opts);
-
-
- const headers = {
- 'Authorization': this.Auth.Token()
- };
-
- this.copyHeader(this.httpOptions.headers, headers);
- this.copyHeader(opts.headers, headers);
-
- const params = opts.params;
- // Converte a query para base64
- if (params.q) {
- params.q = window.btoa(unescape(encodeURIComponent(params.q)));
- }
-
- delete opts.headers;
- delete opts.params;
-
- const options = Object.assign({
- headers: new HttpHeaders(headers),
- params: new HttpParams({ fromObject: params }),
- }, opts);
-
-
- // const options = Object.assign({
- // headers: new HttpHeaders(hopts),
- // params: {}
- // }, opts);
-
- // // Converte a query para base64
- // if (options.params.q) {
- // options.params.q = window.btoa(unescape(encodeURIComponent(options.params.q)));
- // }
-
- return options;
- }
-
- copyHeader(headers, hopts) {
- if (!headers) { return; }
- headers.keys().map(key => { hopts[key] = headers.get(key); });
- }
- }`)
- // .Injetable("{providedIn: 'root'}").Export().Class().Id(ApiClassName(p)).Block(
- // TS.Public().Id("Client").Op(":").Id("Client").Endl(),
- // TS.Public().Id("baseURL").Op("=").Lit(p.BaseURL).Endl(),
- // TS.Public().Id("Auth").Op(":").Id("Auth").Endl(),
- // TS.Public().Id("httpOptions").Id("=").Block(
- // TS.Id("headers").Op(":").Raw("new HttpHeaders").Call(TS.Block(
- // TS.Raw("'Content-Type': 'application/json',"),
- // TS.Raw("'Accept': 'application/json'"),
- // )),
- // ).Endl(),
- // // TS.Public().Id("http").Op(":").Id("HttpClient").Endl(),
- // TS.Constructor(
- // TS.Public().Id("http").Op(":").Id("HttpClient"),
- // ).Block(
- // TS.This().Dot("Client").Op("=").New().Id("Client").Call(TS.This()).Endl(),
- // // TS.Id("this.http").Op("=").New().Id("Client").Call(TS.This()).Endl(),
- // ),
- // TS.Id("Options").Params(
- // TS.Id("opts").Op(":").Id("ServiceOptions"),
- // ).Op(":").Id("{headers: HttpHeaders,params: any}").Block(
- // TS.Return().Block(
- // TS.Raw("headers: this.httpOptions.headers,"),
- // // TS.Raw("params : opts.Params()"),
- // TS.Raw("params : opts"),
- // ),
- // ),
- // ).Line()
- module.Line().Raw(`
- export function ApiOptionsProvider(options) {
- console.log('ApiOptionsProvider', options);
- return options;
- }
- @NgModule({
- imports: [
- CommonModule,
- HttpClientModule,
- ]
- })
- `).Export().
- Class().
- Id(p.Name + "ApiModule").
- Block(
- TS.Raw(`
- static forRoot( options?: `).Raw(ApiClassName(p) + "Options").Raw(` ) : ModuleWithProviders {
- // static forRoot( options?:any ) : ModuleWithProviders {
- return({
- ngModule: `).Raw(p.Name + "ApiModule").Raw(`,
- providers: [
- {
- provide: ApiOptionsParams,
- useValue: options,
- },
- {
- provide: `).Raw(ApiClassName(p) + "Options").Raw(`,
- useFactory: ApiOptionsProvider,
- deps:[ApiOptionsParams]
- }
- ]
- });
- }
- `),
- ).
- Line()
- return nil
- }
- // createClientClass cria a classe de cliente que guarda a referencia para todos os servicos da api
- func createClientClass(p *Project, file *TS.File) {
- var (
- angularResourceName string
- angularClientStmts = []TS.CodeInterface{}
- angularClientConstructor = []TS.CodeInterface{}
- )
- for _, resource := range p.Resources {
- angularResourceName = strings.Title(resource.ID) + "Service"
- angularClientStmts = append(
- angularClientStmts,
- TS.Public().Id(strings.Title(resource.ID)).Op(":").Id(angularResourceName).Endl(),
- )
- angularClientConstructor = append(
- angularClientConstructor,
- TS.This().Dot(strings.Title(resource.ID)).Op("=").New().Id(angularResourceName).Call(TS.Id("api")).Endl(),
- )
- }
- angularClientConstructor = append(
- angularClientConstructor,
- TS.Raw("this.Generic = new ServiceStmt").Call(TS.Id("api")).Endl(),
- )
- // angularClientStmts = append(
- // angularClientStmts,
- // TS.Raw(`public onready = new EventEmitter<any>();`),
- // )
- angularClientStmts = append(
- angularClientStmts,
- TS.Public().Id("Generic: ServiceStmt").Endl(),
- )
- angularClientStmts = append(
- angularClientStmts,
- TS.Constructor(
- TS.Protected().Id("api").Op(":").Id("ApiInterface"),
- ).Block(angularClientConstructor...),
- )
- file.Line().Comment(
- "Class gerencia todos os serviços da api.",
- ).Export().Class().Id("Client").Block(angularClientStmts...)
- }
- func GenAngularMethodStmt(p *Project, r *Resource, method *Method, methods *[]TS.CodeInterface, angularResourceName string) {
- var (
- typ string
- params = []TS.CodeInterface{}
- paramsHttp = []TS.CodeInterface{}
- // id = method.ID
- // ret = TS.Id("Observable")
- param = "entity"
- returnTemplate *TS.Group
- template string
- templateValue interface{}
- defined bool
- )
- if templateValue, defined = method.Custom["ts.template.method"]; defined {
- template = templateValue.(string)
- } else {
- template = method.HttpMethod
- }
- template = strings.ToLower(template)
- entityType := method.Entity
- if entityType == "" {
- entityType = "any"
- }
- switch template {
- case "post":
- typ = "post"
- params = append(params, TS.Id(param).Op(":").Id(entityType))
- // ret.TypeAliase(method.Entity)
- case "filter":
- typ = "get"
- // ret.TypeAliase(method.Entity)
- param = ""
- // params = append(params, TS.Id(param).Op(":").String())
- case "get":
- typ = "get"
- // ret.TypeAliase(method.Entity)
- param = ""
- case "put":
- typ = "put"
- // ret.TypeAliase(method.Entity)
- params = append(params, TS.Id(param).Op(":").Id(entityType).Op("|").String())
- case "delete":
- typ = "delete"
- // ret.TypeAliase(method.Entity)
- // params = append(params, TS.Id(param).Op(":").Id(method.Entity).Op("|").String())
- case "patch":
- typ = "patch"
- params = append(params, TS.Id(param).Op(":").Id(entityType).Op("|").String())
- // ret.TypeAliase(method.Entity)
- // params = append(params, TS.Id(param).Op(":").Id(method.Entity).Op("|").String())
- case "sse":
- typ = "event"
- default:
- panic(fmt.Sprintf("Method '%s' template not defined!", template))
- }
- path := method.Path
- for _, parameter := range method.Parameters {
- alias := getCustom(parameter.Custom, "ts.api.alias")
- if aliasString, ok := alias.(string); ok {
- path = strings.ReplaceAll(
- path,
- fmt.Sprintf("{%s}", parameter.ID),
- fmt.Sprintf("{%s}", aliasString),
- )
- }
- }
- // paramsHttp = append(paramsHttp, TS.Raw("this.Url(url, opt.params)"))
- paramsHttp = append(paramsHttp, TS.Raw(fmt.Sprintf("`${this.api.apiOptions.BASE_URL}%s`", path)))
- switch typ {
- case "post", "put", "patch":
- paramsHttp = append(paramsHttp, TS.Id("entity"))
- }
- params = append(params, TS.Id("opt?: HttpOptions"))
- paramsHttp = append(paramsHttp, TS.Id("opt"))
- response := strings.Replace(method.Response, "*", "", -1)
- if response == "" {
- response = method.Entity
- }
- if response == "" {
- response = "any"
- }
- if getCustom(method.Custom, "client.authorization.required", true).(bool) {
- returnTemplate = TS.Line().Raw(
- fmt.Sprintf(`return this.authorized$.pipe(
- switchMap(() => this._%s<%s>`,
- typ,
- response,
- ),
- ).Call(paramsHttp...).
- Raw(")\n)").
- Endl()
- } else {
- returnTemplate = TS.Line().Raw(
- fmt.Sprintf(
- "return this._%s<%s>",
- typ,
- response,
- ),
- ).Call(paramsHttp...).
- Endl()
- }
- // *methods = append(*methods, TS.Id(method.ID).Params(params...).Op(":").Id("Observable<ServiceResponse>").Block(
- *methods = append(*methods, TS.Id(method.ID).Params(params...).Block(
- returnTemplate,
- ).Line())
- // TS.Raw("let opt = this.api.Options(this.options)").Endl(),
- // TS.Raw("let url = ").Lit(p.GetUrlFromMethod(method)).Endl(),
- // TS.Raw("let url = ").Raw(fmt.Sprintf("`${this.api.BASE_URL}%s`", method.Path)).Endl(),
- // TS.Line().Raw(fmt.Sprintf("return this._%s", typ )).Call(paramsHttp...).Endl(),
- }
- // func GenAngularMethod(p *Project, r *Resource, method *Method, methods *[]TS.CodeInterface, angularResourceName string) {
- // params := []TS.CodeInterface{}
- // param := "entity"
- // methodId := method.ID
- // callOptionsParam := ""
- // switch strings.ToLower(method.HttpMethod) {
- // case "post":
- // params = append(params, TS.Id(param).Op(":").Id(method.Entity))
- // case "filter":
- // // methodId = "get"
- // param = ""
- // case "get":
- // param = ""
- // // params = append(params, TS.Id(param).Op(":").String())
- // case "get_list":
- // param = ""
- // // params = append(params, TS.Id(param).Op(":").Id(method.Entity).Op("|").String())
- // case "patch":
- // param = ""
- // params = append(params, TS.Id(param).Op(":").Id(method.Entity))
- // // params = append(params, TS.Id(param).Op(":").Id(method.Entity).Op("|").String())
- // case "put":
- // params = append(params, TS.Id(param).Op(":").Id(method.Entity))
- // callOptionsParam = "{id: entity.id}"
- // case "delete":
- // // params = append(params, TS.Id(param).Op(":").Id(method.Entity).Op("|").String())
- // params = append(params, TS.Id(param).Op(":").Id(method.Entity))
- // callOptionsParam = "{id: entity.id}"
- // param = ""
- // default:
- // panic(fmt.Sprintf("O método http '%s' para o recurso %s não foi definido!", method.HttpMethod, method.ID))
- // }
- // // *methods = append(*methods, TS.Id(method.ID).Params(params...).Op(":").Id("Observable<ServiceResponse>").Block(
- // *methods = append(*methods, TS.Id(method.ID).Params(params...).Op(":").Id("Observable<ServiceResponse>").Block(
- // TS.Return().This().Dot("options").Call(TS.Raw(callOptionsParam)).Dot(methodId).Call(TS.Id(param)).Endl(),
- // ).Line())
- // }
|