Major integrations and fixes: - Added BACKBEAT SDK integration for P2P operation timing - Implemented beat-aware status tracking for distributed operations - Added Docker secrets support for secure license management - Resolved KACHING license validation via HTTPS/TLS - Updated docker-compose configuration for clean stack deployment - Disabled rollback policies to prevent deployment failures - Added license credential storage (CHORUS-DEV-MULTI-001) Technical improvements: - BACKBEAT P2P operation tracking with phase management - Enhanced configuration system with file-based secrets - Improved error handling for license validation - Clean separation of KACHING and CHORUS deployment stacks 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
221 lines
7.4 KiB
Go
221 lines
7.4 KiB
Go
package schema
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/ipld/go-ipld-prime/datamodel"
|
|
)
|
|
|
|
// Everything in this file is __a temporary hack__ and will be __removed__.
|
|
//
|
|
// These methods will only hang around until more of the "ast" packages are finished;
|
|
// thereafter, building schema.Type and schema.TypeSystem values will only be
|
|
// possible through first constructing a schema AST, and *then* using Reify(),
|
|
// which will validate things correctly, cycle-check, cross-link, etc.
|
|
//
|
|
// (Meanwhile, we're using these methods in the codegen prototypes.)
|
|
|
|
// These methods use Type objects as parameters when pointing to other things,
|
|
// but this is... turning out consistently problematic.
|
|
// Even when we're doing this hacky direct-call doesn't-need-to-be-serializable temp stuff,
|
|
// as written, this doesn't actually let us express cyclic things viably!
|
|
// The same initialization questions are also going to come up again when we try to make
|
|
// concrete values in the output of codegen.
|
|
// Maybe it's actually just a bad idea to have our reified Type types use Type pointers at all.
|
|
// (I will never get tired of the tongue twisters, evidently.)
|
|
// I'm not actually using that much, and it's always avoidable (it's trivial to replace with a map lookup bouncing through a 'ts' variable somewhere).
|
|
// And having the AST gen'd types be... just... the thing... sounds nice. It could save a lot of work.
|
|
// (It would mean the golang types don't tell you whether the values have been checked for global properties or not, but, eh.)
|
|
// (It's not really compatible with "Prototype and Type are the same thing for codegen'd stuff", either (or, we need more interfaces, and to *really* lean into them), but maybe that's okay.)
|
|
|
|
func SpawnTypeSystem(types ...Type) (*TypeSystem, []error) {
|
|
ts := TypeSystem{}
|
|
ts.Init()
|
|
for _, typ := range types {
|
|
ts.Accumulate(typ)
|
|
}
|
|
if errs := ts.ValidateGraph(); errs != nil {
|
|
return nil, errs
|
|
}
|
|
return &ts, nil
|
|
}
|
|
func MustTypeSystem(types ...Type) *TypeSystem {
|
|
if ts, err := SpawnTypeSystem(types...); err != nil {
|
|
panic(err)
|
|
} else {
|
|
return ts
|
|
}
|
|
}
|
|
|
|
func SpawnString(name TypeName) *TypeString {
|
|
return &TypeString{typeBase{name, nil}}
|
|
}
|
|
|
|
func SpawnBool(name TypeName) *TypeBool {
|
|
return &TypeBool{typeBase{name, nil}}
|
|
}
|
|
|
|
func SpawnInt(name TypeName) *TypeInt {
|
|
return &TypeInt{typeBase{name, nil}}
|
|
}
|
|
|
|
func SpawnFloat(name TypeName) *TypeFloat {
|
|
return &TypeFloat{typeBase{name, nil}}
|
|
}
|
|
|
|
func SpawnBytes(name TypeName) *TypeBytes {
|
|
return &TypeBytes{typeBase{name, nil}}
|
|
}
|
|
|
|
func SpawnLink(name TypeName) *TypeLink {
|
|
return &TypeLink{typeBase{name, nil}, "", false}
|
|
}
|
|
|
|
func SpawnLinkReference(name TypeName, pointsTo TypeName) *TypeLink {
|
|
return &TypeLink{typeBase{name, nil}, pointsTo, true}
|
|
}
|
|
|
|
func SpawnList(name TypeName, valueType TypeName, nullable bool) *TypeList {
|
|
return &TypeList{typeBase{name, nil}, false, valueType, nullable}
|
|
}
|
|
|
|
func SpawnMap(name TypeName, keyType TypeName, valueType TypeName, nullable bool) *TypeMap {
|
|
return &TypeMap{typeBase{name, nil}, false, keyType, valueType, nullable}
|
|
}
|
|
|
|
func SpawnAny(name TypeName) *TypeAny {
|
|
return &TypeAny{typeBase{name, nil}}
|
|
}
|
|
|
|
func SpawnStruct(name TypeName, fields []StructField, repr StructRepresentation) *TypeStruct {
|
|
v := &TypeStruct{
|
|
typeBase{name, nil},
|
|
fields,
|
|
make(map[string]StructField, len(fields)),
|
|
repr,
|
|
}
|
|
for i := range fields {
|
|
fields[i].parent = v
|
|
v.fieldsMap[fields[i].name] = fields[i]
|
|
}
|
|
switch repr.(type) {
|
|
case StructRepresentation_Stringjoin:
|
|
for _, f := range fields {
|
|
if f.IsMaybe() {
|
|
panic("neither nullable nor optional is supported on struct stringjoin representation")
|
|
}
|
|
}
|
|
case nil:
|
|
v.representation = SpawnStructRepresentationMap(nil)
|
|
}
|
|
return v
|
|
}
|
|
func SpawnStructField(name string, typ TypeName, optional bool, nullable bool) StructField {
|
|
return StructField{nil /*populated later*/, name, typ, optional, nullable}
|
|
}
|
|
func SpawnStructRepresentationMap(renames map[string]string) StructRepresentation_Map {
|
|
return StructRepresentation_Map{renames, nil}
|
|
}
|
|
func SpawnStructRepresentationMap2(renames map[string]string, implicits map[string]ImplicitValue) StructRepresentation_Map {
|
|
return StructRepresentation_Map{renames, implicits}
|
|
}
|
|
func SpawnStructRepresentationTuple() StructRepresentation_Tuple {
|
|
return StructRepresentation_Tuple{}
|
|
}
|
|
func SpawnStructRepresentationStringjoin(delim string) StructRepresentation_Stringjoin {
|
|
return StructRepresentation_Stringjoin{delim}
|
|
}
|
|
|
|
func SpawnUnion(name TypeName, members []TypeName, repr UnionRepresentation) *TypeUnion {
|
|
return &TypeUnion{typeBase{name, nil}, members, repr}
|
|
}
|
|
func SpawnUnionRepresentationKeyed(table map[string]TypeName) UnionRepresentation_Keyed {
|
|
return UnionRepresentation_Keyed{table}
|
|
}
|
|
func SpawnUnionRepresentationKinded(table map[datamodel.Kind]TypeName) UnionRepresentation_Kinded {
|
|
return UnionRepresentation_Kinded{table}
|
|
}
|
|
func SpawnUnionRepresentationStringprefix(delim string, table map[string]TypeName) UnionRepresentation_Stringprefix {
|
|
return UnionRepresentation_Stringprefix{delim, table}
|
|
}
|
|
|
|
func SpawnEnum(name TypeName, members []string, repr EnumRepresentation) *TypeEnum {
|
|
return &TypeEnum{typeBase{name, nil}, members, repr}
|
|
}
|
|
|
|
// The methods relating to TypeSystem are also mutation-heavy and placeholdery.
|
|
|
|
func (ts *TypeSystem) Init() {
|
|
ts.namedTypes = make(map[TypeName]Type)
|
|
}
|
|
func (ts *TypeSystem) Accumulate(typ Type) {
|
|
typ._Type(ts)
|
|
name := typ.Name()
|
|
if _, ok := ts.namedTypes[name]; ok {
|
|
panic(fmt.Sprintf("duplicate type name: %s", name))
|
|
}
|
|
ts.namedTypes[name] = typ
|
|
ts.names = append(ts.names, name)
|
|
}
|
|
func (ts TypeSystem) GetTypes() map[TypeName]Type {
|
|
return ts.namedTypes
|
|
}
|
|
func (ts TypeSystem) TypeByName(n string) Type {
|
|
return ts.namedTypes[n]
|
|
}
|
|
func (ts TypeSystem) Names() []TypeName {
|
|
return ts.names
|
|
}
|
|
|
|
// ValidateGraph checks that all type names referenced are defined.
|
|
//
|
|
// It does not do any other validations of individual type's sensibleness
|
|
// (that should've happened when they were created
|
|
// (although also note many of those validates are NYI,
|
|
// and are roadmapped for after we research self-hosting)).
|
|
func (ts TypeSystem) ValidateGraph() []error {
|
|
var ee []error
|
|
for tn, t := range ts.namedTypes {
|
|
switch t2 := t.(type) {
|
|
case *TypeBool,
|
|
*TypeInt,
|
|
*TypeFloat,
|
|
*TypeString,
|
|
*TypeBytes,
|
|
*TypeEnum:
|
|
continue // nothing to check: these are leaf nodes and refer to no other types.
|
|
case *TypeLink:
|
|
if !t2.hasReferencedType {
|
|
continue
|
|
}
|
|
if _, ok := ts.namedTypes[t2.referencedType]; !ok {
|
|
ee = append(ee, fmt.Errorf("type %s refers to missing type %s (as link reference type)", tn, t2.referencedType))
|
|
}
|
|
case *TypeStruct:
|
|
for _, f := range t2.fields {
|
|
if _, ok := ts.namedTypes[f.typ]; !ok {
|
|
ee = append(ee, fmt.Errorf("type %s refers to missing type %s (in field %q)", tn, f.typ, f.name))
|
|
}
|
|
}
|
|
case *TypeMap:
|
|
if _, ok := ts.namedTypes[t2.keyType]; !ok {
|
|
ee = append(ee, fmt.Errorf("type %s refers to missing type %s (as key type)", tn, t2.keyType))
|
|
}
|
|
if _, ok := ts.namedTypes[t2.valueType]; !ok {
|
|
ee = append(ee, fmt.Errorf("type %s refers to missing type %s (as value type)", tn, t2.valueType))
|
|
}
|
|
case *TypeList:
|
|
if _, ok := ts.namedTypes[t2.valueType]; !ok {
|
|
ee = append(ee, fmt.Errorf("type %s refers to missing type %s (as value type)", tn, t2.valueType))
|
|
}
|
|
case *TypeUnion:
|
|
for _, mn := range t2.members {
|
|
if _, ok := ts.namedTypes[mn]; !ok {
|
|
ee = append(ee, fmt.Errorf("type %s refers to missing type %s (as a member)", tn, mn))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ee
|
|
}
|