Help us shape the future of Go! Take the 2026 Go Developer Survey

apppkg

package
v0.21.0 Latest Latest
Warning

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

Go to latest
Published: Oct 29, 2026 License: AGPL-3.0 Imports: 7 Imported by: 0

Documentation

Overview

Package apppkg is the application package (ADR-0437, ADR-0467): the directory or archive an application and its shop move between installations in, as `atlas export` writes it from a terminal and the Console downloads it.

atlas.json, *.bpmn, *.form.json, *.dmn  the application's source (ADR-0134)
konstanten.json                         its constants, as `atlas export` writes them
katalog.json                            the catalogues, as one catalogue document
fragen.json                             one question per group and person they name
antworten.json                          the answers, as the exporting server names them

What turns a catalogue export into a package another installation can take is here, once, for both: every group and person a catalogue names becomes a {{question}} answered by name, because ids are minted per server and names are not; a process a product is bound to travels once; and what cannot travel is named. The import half is here too: the answers are found in the target's directory, by id or by name, and put in place of the questions.

It works on data, not on the server's types: a field it does not know — written by a newer server — travels as it came.

Index

Constants

View Source
const (
	ProblemUnanswered = "unanswered"
	ProblemUnknown    = "unknown"
	ProblemAmbiguous  = "ambiguous"
)

Why an answer does not answer its question.

View Source
const (
	CatalogueFile = "katalog.json"
	QuestionsFile = "fragen.json"
	AnswersFile   = "antworten.json"
	ConstantsFile = "konstanten.json"
)

The files of a package, beside the source tree.

View Source
const (
	KindGroup   = "group"
	KindUser    = "user"
	KindAccount = "account"
)

Question kinds an answer is looked up for in the directory. Any other kind is taken as written.

Variables

View Source
var Placeholder = regexp.MustCompile(`\{\{([a-z0-9-]+)\}\}`)

Placeholder is a value a catalogue document leaves to the installation it is imported into: an audience group, an approver.

Functions

func Asked

func Asked(document []byte) []string

Asked names the questions a document leaves, each once, in the order it asks them.

func Decode

func Decode(raw []byte, into any) error

Decode reads a JSON document as data, numbers kept as written: a document goes back out as it came in, a rank or a price included.

func EncodeJSON

func EncodeJSON(v any) ([]byte, error)

EncodeJSON writes a package file: indented for a diff, newline-terminated, and without escaping < and > — a BPMN model in katalog.json stays readable XML.

func Fill

func Fill(doc []byte, answers map[string]string) ([]byte, error)

Fill puts the answers in place of the questions. Each goes in escaped as a JSON string, so an answer cannot break the document it is put in.

func FindPrincipal

func FindPrincipal(dir []DirectoryEntry, kind, value string) (id string, candidates []string, why string)

FindPrincipal finds a principal of a kind by id, then by name: a group or a user by its id, an account by its username. A name two principals share is refused rather than guessed: it answers the ids it matches and why it took none. why is empty when it found exactly one.

Types

type Answers

type Answers struct {
	// Packaged are antworten.json's: the names the exporting server gives.
	Packaged map[string]string
	// Chosen are the person's, and win: an answers file or --set in a terminal, a
	// choice in the Console's dialog.
	Chosen map[string]string
	// Mappings are this server's table, read for a packaged answer before the
	// directory is.
	Mappings []Mapping
}

Answers are what an import answers a package's questions with.

type Application

type Application struct {
	Processes []string
	Forms     []string
}

Application is what of the application a package carries that a shop refers to: its processes and forms, by id.

type DirectoryEntry

type DirectoryEntry struct {
	Type string `json:"type"`
	ID   string `json:"id"`
	Name string `json:"name"`
}

DirectoryEntry is one principal of a server's directory, as GET /api/v1/principals lists it: a "user" or a "group" by id. An "account" is a user by username — what a fixed approver names, because the approval becomes a task assigned to that username (catalog/approverreport.go) — with its display name as its name; GET /api/v1/users/assignable lists them.

type Mapping

type Mapping struct {
	Kind   string `json:"kind"`
	Answer string `json:"answer"`
	// ID is the principal it means here: a group's or a user's id, an account's
	// username. Name is that principal's name here, for whoever reads the table.
	ID   string `json:"id"`
	Name string `json:"name,omitempty"`
}

Mapping is one entry of a target's table of names (ADR-0467, amended): what a package's answer of a kind — a group, a person or an account as the exporting server names it — means on this server. The table is the target's own, because only the target knows that INT's "Fachbereich Bau" is its "FB Bau"; it is filled from the choices people make when a name is not found, and read before the directory, so the same question is not asked twice.

type Part

type Part struct {
	ID       string
	Document map[string]any
	Released bool
}

Part is one catalogue as GET /api/v1/catalogs/{id}/document?processes=true answers it, decoded as data, and whether it has a release on the exporting server.

type Problem

type Problem struct {
	Name string `json:"name"`
	Kind string `json:"kind"`
	// Question is the question as fragen.json words it, in English when it can.
	Question string `json:"question"`
	Answer   string `json:"answer,omitempty"`
	// Reason is unanswered, unknown or ambiguous; Detail says it in a sentence.
	Reason string `json:"reason"`
	Detail string `json:"detail"`
	// Candidates are the ids of the principals an ambiguous name matches.
	Candidates []string `json:"candidates,omitempty"`
}

Problem is one question an import cannot answer from what it was given.

type Question

type Question struct {
	Kind  string            `json:"kind"`
	Label map[string]string `json:"label"`
	Hint  map[string]string `json:"hint"`
}

Question is one entry of fragen.json. Kind says where an answer must be found: "group" and "user" in the server's directory, anything else is taken as written.

func (Question) Text

func (q Question) Text(name string) string

Text is the question in English when it has English, else in whatever it has, else its name.

type Resolution

type Resolution struct {
	// Values are the answers by question, ready to fill: ids, usernames, text.
	Values map[string]string
	// Notes say how an answer was taken: a name found as an id, a remembered
	// answer, an answer nothing asks for.
	Notes    []string
	Problems []Problem
	// Learned are the choices worth remembering: a packaged answer the directory
	// did not answer by name as the person did. Recorded in the table once the import
	// went through, they answer the same question next time without asking.
	Learned []Mapping
	// Remembered names the questions the table answered.
	Remembered []string
}

Resolution is how the questions were answered.

func Resolve

func Resolve(document []byte, questions map[string]Question, given Answers, directory func() ([]DirectoryEntry, error)) (Resolution, error)

Resolve answers every question a catalogue document leaves. An answer to a group, person or account question must be one the server's directory has, given by its id (an account's username) or by its name: an audience group that does not exist reaches nobody, and the import would succeed without saying so. Names are accepted because ids are minted per server, so an answer that names "Alle Mitarbeitenden" serves the test installation and the production one alike.

For each question, in this order: the person's choice; for the packaged answer, the table's entry, while the principal it names still exists here; the packaged answer found in the directory. Every problem is reported at once; the directory is read only when a question needs it.

type Shop

type Shop struct {
	Document  []byte
	Questions map[string]Question
	Answers   map[string]string
	Publish   bool
	Products  int
	// Notes say what the import will do; Warnings what will not work on the
	// target as it does here.
	Notes    []string
	Warnings []string
}

Shop is katalog.json and what goes with it.

func BuildShop

func BuildShop(parts []Part, app Application, dir []DirectoryEntry, earlier map[string]Question) (Shop, error)

BuildShop makes the catalogues one document and that document a package's: the processes the application carries are left to it, the groups and people become questions, and what cannot travel is named. dir is the exporting server's directory; earlier are the questions an earlier export of the same package asked, whose wording is kept when the kind is the same.

Jump to

Keyboard shortcuts

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