codegentemplates

package
v0.0.0-...-2c61642 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 8, 2021 License: Apache-2.0 Imports: 0 Imported by: 2

Documentation

Index

Constants

View Source
const BackendCommandsDefinitions = `package {{.Module.Id}}

// WARNING: generated file

import (
	"errors"
	"fmt"
	"regexp"
	"strings"
	"github.com/function61/eventkit/command"
{{if .CommandsImports.Date}}	"github.com/function61/eventkit/guts"{{end}}
)

// handlers

type CommandHandlers interface { {{range .Module.Commands}}
	{{.AsGoStructName}}(*{{.AsGoStructName}}, *command.Ctx) error{{end}}
}

// invoker

func CommandInvoker(handlers CommandHandlers) command.Invoker {
	return &invoker{handlers}
}

type invoker struct {
	handlers CommandHandlers
}

func (i *invoker) Invoke(cmdGeneric command.Command, ctx *command.Ctx) error {
	switch cmd := cmdGeneric.(type) { {{range .Module.Commands}}
	case *{{.AsGoStructName}}:
		return i.handlers.{{.AsGoStructName}}(cmd, ctx){{end}}
	default:
		// should not ever happen, because this is asserted in httpcommand
		return fmt.Errorf("unknown command: " + cmdGeneric.Key())
	}
}

// structs

{{range .Module.Commands}}
type {{.AsGoStructName}} struct { {{range .Fields}}
	{{.Key}} {{.AsGoType $.Module}} ` + "`json:\"{{.Key}}\"`" + `{{end}}
}

func (x *{{.AsGoStructName}}) Validate() error {
	{{.MakeValidation $.Module}}

	return nil
}

func (x *{{.AsGoStructName}}) MiddlewareChain() string { return "{{.MiddlewareChain}}" }
func (x *{{.AsGoStructName}}) Key() string { return "{{.Command}}" }
{{end}}

// allocators

var Allocators = command.Allocators{
{{range .Module.Commands}}
	"{{.Command}}": func() command.Command { return &{{.AsGoStructName}}{} },{{end}}
}

// util functions

func regexpValidation(fieldName string, pattern string, content string) error {
	if !regexp.MustCompile(pattern).MatchString(content) {
		return fmt.Errorf("field %s does not match pattern %s", fieldName, pattern)
	}

	return nil
}

func noNewlinesValidation(fieldName string, content string) error {
	if strings.ContainsAny(content, "\r\n") {
		return errors.New("single-line field " + fieldName + " contains newlines")
	}

	return nil
}

func fieldEmptyValidationError(fieldName string) error {
	return errors.New("field " + fieldName + " cannot be empty")
}

func fieldLengthValidationError(fieldName string, maxLength int, got int) error {
	return fmt.Errorf("field %s exceeded maximum length %d (got %d)", fieldName, maxLength, got)
}
`
View Source
const BackendEventDefinitions = `` /* 1240-byte string literal not displayed */
View Source
const BackendRestEndpoints = `` /* 2608-byte string literal not displayed */
View Source
const BackendTypes = `` /* 1740-byte string literal not displayed */
View Source
const BackendUiRoutes = `` /* 225-byte string literal not displayed */
View Source
const DocsCommands = `` /* 406-byte string literal not displayed */
View Source
const DocsEvents = `` /* 408-byte string literal not displayed */
View Source
const DocsRestEndpoints = `` /* 897-byte string literal not displayed */
View Source
const DocsTypes = `{{if .Module.Types.StringConsts}}
Constants
---------

| const | value |
|-------|-------|
{{range .Module.Types.StringConsts}}| {{.Key}} | {{.Value}} |
{{end}}
{{end}}

{{range .Module.Types.Enums}}
enum {{.Name}}
---------

{{range .StringMembers}}
- {{.}}{{end}}
{{end}}

{{range .Module.Types.Types}}
{{.Name}}
---------

` + "```" + `
{{.AsTypeScriptCode}}
` + "```" + `
{{end}}
`
View Source
const FrontendCommandDefinitions = `` /* 1371-byte string literal not displayed */
View Source
const FrontendDatatypes = `` /* 666-byte string literal not displayed */
View Source
const FrontendRestEndpoints = `// tslint:disable
// WARNING: generated file

// WHY: wouldn't make sense complicating code generation to check
// if we need template string or not in path string

{{if .Module.Types.EndpointsProducesAndConsumesTypescriptTypes}}import { {{range .Module.Types.EndpointsProducesAndConsumesTypescriptTypes}}
	{{.}},{{end}}
} from '{{$.Opts.FrontendModulePrefix}}{{.Module.Path}}_types';{{end}}
import {
	getJson,
{{if .AnyEndpointHasConsumes}}	postJson,{{end}}
} from 'f61ui/httputil';

{{range .Module.Types.Endpoints}}
// {{.Path}}
export function {{.Name}}({{.TypescriptArgs}}) {
	return {{if .Consumes}}postJson<{{if .Consumes}}{{.Consumes.AsTypeScriptType}}{{else}}void{{end}}, {{if .Produces}}{{.Produces.AsTypeScriptType}}{{else}}void{{end}}>{{else}}getJson<{{if .Produces}}{{.Produces.AsTypeScriptType}}{{else}}void{{end}}>{{end}}(` + "`{{.TypescriptPath}}`" + `{{if .Consumes}}, body{{end}});
}
{{if not .Consumes}}
export function {{.Name}}Url({{.TypescriptArgs}}): string {
	return ` + "`{{.TypescriptPath}}`" + `;
}{{end}}
{{end}}
`
View Source
const FrontendUiRoutes = `// tslint:disable
// WARNING: generated file

import { parseQueryParams, queryParams, makeQueryParams } from 'f61ui/httputil';

export interface RouteHandlers { {{range .Module.UiRoutes}}
	{{.Id}}: ({{if .HasOpts}}opts: {{.TsOptsName}}{{end}}) => JSX.Element;{{end}}
	notFound: (url: string) => JSX.Element;
}

{{range .Module.UiRoutes}}
{{if .HasOpts}}export interface {{.TsOptsName}} { {{range .PathPlaceholders}}
	{{.}}: string;{{end}}{{range .QueryParams}}
	{{.Key}}{{if .Type.Nullable}}?{{end}}: {{if eq .Type.NameRaw "integer"}}number{{else}}string{{end}};{{end}}
}{{end}}

{{if .Title}}
export const {{.Id}}Title = '{{.Title}}';
{{end}}

// {{.Path}}
export function {{.Id}}URL({{if .HasOpts}}opts: {{.TsOptsName}}{{end}}): string {
	const query: queryParams = {};
{{range .QueryParams}}
{{if .Type.Nullable}}	if (opts.{{.Key}} !== undefined) {
	{{end}}	query.{{.Key}} = opts.{{.Key}}{{if eq .Type.NameRaw "integer"}}.toString(){{end}};{{if .Type.Nullable}}
	}{{end}}
{{end}}
 
	return makeQueryParams(` + "`{{.TsPath}}`" + `, query);
}

export function {{.Id}}Match(path: string, query: queryParams): {{if .HasOpts}}{{.TsOptsName}}{{else}}{}{{end}} | null {
	const matches = {{.PathReJavaScript}}.exec(path);
	if (matches == null) {
		return null;
	}

{{range .QueryParams}}{{if eq .Type.NameRaw "string"}}
	const {{.Key}}Par = query.{{.Key}};{{else}}
	let {{.Key}}Par: number | undefined;
	if (query.{{.Key}} !== undefined) {
		// parseInt() accepts garbage after the number, and "+" accepts empty string
		if (query.{{.Key}} === '') {
			throw new Error("Invalid URL param: '{{.Key}}'; expecting integer, got empty string")
		}
		const parsed = +query.{{.Key}};
		if (isNaN(parsed)) {
			throw new Error("Invalid URL param: '{{.Key}}'; expecting integer")
		}
		{{.Key}}Par = parsed;
	}{{end}}{{if not .Type.Nullable}}
	if ({{.Key}}Par === undefined) {
		throw new Error("Required URL param '{{.Key}}' missing");
	} {{end}}
{{end}}

	assertNoUnrecognizedKeys(Object.keys(query), [{{range .QueryParams}}'{{.Key}}', {{end}}]);

	return { {{range $idx, $key := .PathPlaceholders}}
		{{$key}}: matches[{{add $idx 1}}],{{end}}{{range .QueryParams}}
		{{.Key}}: {{.Key}}Par,{{end}}
	};
}

// ---------------
{{end}}

export function handle(url: string, handlers: RouteHandlers): JSX.Element {
	const qpos = url.indexOf('?');

	// "/search?query=foo" => "/search"
	const path = qpos === -1 ? url : url.substr(0, qpos);
	const queryPars = parseQueryParams(qpos === -1 ? '' : url.substr(qpos + 1));
{{range .Module.UiRoutes}}
	const {{.Id}}Opts = {{.Id}}Match(path, queryPars);
	if ({{.Id}}Opts) {
		return handlers.{{.Id}}({{if .HasOpts}}{{.Id}}Opts{{end}});
	}
{{end}}

	return handlers.notFound(path);
}

// for when you need to check if url can be routed to this route collection
export function hasRouteFor(url: string): boolean {
	const qpos = url.indexOf('?');

	// "/search?query=foo" => "/search"
	const path = qpos === -1 ? url : url.substr(0, qpos);
	const queryPars = parseQueryParams(qpos === -1 ? '' : url.substr(qpos + 1));
{{range .Module.UiRoutes}}
	if ({{.Id}}Match(path, queryPars)) {
		return true
	} {{end}}

	return false;
}

function assertNoUnrecognizedKeys(gotKeys: string[], allowedKeys: string[]) {
	const unrecognizedKeys = gotKeys.filter(key => allowedKeys.indexOf(key) === -1);
	if (unrecognizedKeys.length > 0) {
		throw new Error("Unrecognized keys in URL params: "+unrecognizedKeys.join(', '));
	}
}

`
View Source
const FrontendVersion = `` /* 164-byte string literal not displayed */

Variables

This section is empty.

Functions

This section is empty.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL