Add factory creation ports and owner initialization contracts
This commit is contained in:
@@ -115,6 +115,8 @@ export const genericImplementationType = (
|
||||
}
|
||||
case "query":
|
||||
return queryPort(requirement);
|
||||
case "creation":
|
||||
throw new Error("Creation ports require the portable transaction context generator (LF-09)");
|
||||
case "constructor":
|
||||
return object([
|
||||
[
|
||||
|
||||
@@ -249,6 +249,8 @@ export const generateTypeScriptBindings = (
|
||||
},
|
||||
};
|
||||
}
|
||||
case "creation":
|
||||
throw new Error("Creation ports require the portable transaction context generator (LF-09)");
|
||||
case "constructor": {
|
||||
const input = requirement.inputType;
|
||||
if (!input)
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,279 +1,283 @@
|
||||
WORKSPACE=1
|
||||
EXECUTION=2
|
||||
SNAPSHOT=3
|
||||
TRANSACTION=4
|
||||
REMOTE=5
|
||||
TARGETS=6
|
||||
PORTABLE=7
|
||||
REPLICA=8
|
||||
LOCAL=9
|
||||
FROM=10
|
||||
RESULT_BYTES=11
|
||||
RPC_CALLS=12
|
||||
DEADLINE_MS=13
|
||||
QUERY=14
|
||||
REFLECTION=15
|
||||
SPECIALIZE=16
|
||||
ROOT=17
|
||||
DOCUMENT=18
|
||||
FRAGMENTS=19
|
||||
VIEW=20
|
||||
MAX=21
|
||||
ALLOW=22
|
||||
POLL=23
|
||||
QUERYABLE=24
|
||||
RPC=25
|
||||
QUERY_REASON=26
|
||||
TYPE=27
|
||||
OBJECT=28
|
||||
STORABLE=29
|
||||
IMPLEMENTS=30
|
||||
REF=31
|
||||
FRAGMENT=32
|
||||
IMPORT=33
|
||||
EXTERNAL=34
|
||||
ATOM=35
|
||||
INTERFACE=36
|
||||
INTERFACES=37
|
||||
PACKAGE=38
|
||||
VALUE=39
|
||||
RELATION=40
|
||||
OPERATION=41
|
||||
FUNCTION=42
|
||||
CONSTRUCTOR=43
|
||||
CONSTRUCTS=44
|
||||
INPUT=45
|
||||
CONFORM=46
|
||||
AS=47
|
||||
BIND=48
|
||||
STATIC=49
|
||||
TO=50
|
||||
PRIVATE=51
|
||||
SHARED=52
|
||||
STATE=53
|
||||
EDGE=54
|
||||
PROJECTION=55
|
||||
WITH=56
|
||||
USING=57
|
||||
VIA=58
|
||||
MATERIALIZE=59
|
||||
IF=60
|
||||
ABSENT=61
|
||||
ON=62
|
||||
POLICY=63
|
||||
DEFAULT=64
|
||||
SOURCE=65
|
||||
REPOSITORY=66
|
||||
COMMIT=67
|
||||
REVISION=68
|
||||
SEMANTIC_MAJOR=69
|
||||
ON_DELETE=70
|
||||
RETAIN_OTHER=71
|
||||
KEYED=72
|
||||
PUBLIC_TRAVERSAL=73
|
||||
ID=74
|
||||
DOC=75
|
||||
MODE=76
|
||||
EMITS=77
|
||||
RECEIVER=78
|
||||
REQUIRES=79
|
||||
ANY=80
|
||||
GET=81
|
||||
SET=82
|
||||
WATCH=83
|
||||
START=84
|
||||
STOP=85
|
||||
READ=86
|
||||
WRITE=87
|
||||
RESOLVE=88
|
||||
CONNECT=89
|
||||
DISCONNECT=90
|
||||
CALL=91
|
||||
WATCH_START=92
|
||||
WATCH_STOP=93
|
||||
SUBSCRIBE=94
|
||||
UNSUBSCRIBE=95
|
||||
OPTIMISTIC_REGISTER=96
|
||||
CRDT=97
|
||||
OPTIONAL_ONE=98
|
||||
EXACTLY_ONE=99
|
||||
MANY_UNIQUE=100
|
||||
MANY=101
|
||||
ORDERED=102
|
||||
UNIT=103
|
||||
WATCH_HANDLE=104
|
||||
MESSAGE=105
|
||||
ATOM_REF=106
|
||||
INTERFACE_REF=107
|
||||
OPTIONAL=108
|
||||
LIST=109
|
||||
RECORD=110
|
||||
BOOL=111
|
||||
BYTES=112
|
||||
DOUBLE=113
|
||||
INT32=114
|
||||
INT64=115
|
||||
STRING=116
|
||||
UINT32=117
|
||||
UINT64=118
|
||||
TRUE=119
|
||||
FALSE=120
|
||||
NULL=121
|
||||
ARROW=122
|
||||
COLON=123
|
||||
SEMI=124
|
||||
COMMA=125
|
||||
DOT=126
|
||||
LBRACE=127
|
||||
RBRACE=128
|
||||
LBRACK=129
|
||||
RBRACK=130
|
||||
LPAREN=131
|
||||
RPAREN=132
|
||||
LT=133
|
||||
GT=134
|
||||
AMP=135
|
||||
EQUAL=136
|
||||
INTEGER=137
|
||||
JSON_NUMBER=138
|
||||
IDENTIFIER=139
|
||||
STRING_LITERAL=140
|
||||
LINE_COMMENT=141
|
||||
BLOCK_COMMENT=142
|
||||
WS=143
|
||||
'workspace'=1
|
||||
'execution'=2
|
||||
'snapshot'=3
|
||||
'transaction'=4
|
||||
'remote'=5
|
||||
'targets'=6
|
||||
'portable'=7
|
||||
'replica'=8
|
||||
'local'=9
|
||||
'from'=10
|
||||
'result-bytes'=11
|
||||
'rpc-calls'=12
|
||||
'deadline-ms'=13
|
||||
'query'=14
|
||||
'reflection'=15
|
||||
'specialize'=16
|
||||
'root'=17
|
||||
'document'=18
|
||||
'fragments'=19
|
||||
'view'=20
|
||||
'max'=21
|
||||
'allow'=22
|
||||
'poll'=23
|
||||
'queryable'=24
|
||||
'rpc'=25
|
||||
'query-reason'=26
|
||||
'type'=27
|
||||
'object'=28
|
||||
'storable'=29
|
||||
'implements'=30
|
||||
'ref'=31
|
||||
'fragment'=32
|
||||
'import'=33
|
||||
'external'=34
|
||||
'atom'=35
|
||||
'interface'=36
|
||||
'interfaces'=37
|
||||
'package'=38
|
||||
'value'=39
|
||||
'relation'=40
|
||||
'operation'=41
|
||||
'function'=42
|
||||
'constructor'=43
|
||||
'constructs'=44
|
||||
'input'=45
|
||||
'conform'=46
|
||||
'as'=47
|
||||
'bind'=48
|
||||
'static'=49
|
||||
'to'=50
|
||||
'private'=51
|
||||
'shared'=52
|
||||
'state'=53
|
||||
'edge'=54
|
||||
'projection'=55
|
||||
'with'=56
|
||||
'using'=57
|
||||
'via'=58
|
||||
'materialize'=59
|
||||
'if'=60
|
||||
'absent'=61
|
||||
'on'=62
|
||||
'policy'=63
|
||||
'default'=64
|
||||
'source'=65
|
||||
'repository'=66
|
||||
'commit'=67
|
||||
'revision'=68
|
||||
'semantic-major'=69
|
||||
'on-delete'=70
|
||||
'retain-other'=71
|
||||
'keyed'=72
|
||||
'public-traversal'=73
|
||||
'id'=74
|
||||
'doc'=75
|
||||
'mode'=76
|
||||
'emits'=77
|
||||
'receiver'=78
|
||||
'requires'=79
|
||||
'any'=80
|
||||
'get'=81
|
||||
'set'=82
|
||||
'watch'=83
|
||||
'start'=84
|
||||
'stop'=85
|
||||
'read'=86
|
||||
'write'=87
|
||||
'resolve'=88
|
||||
'connect'=89
|
||||
'disconnect'=90
|
||||
'call'=91
|
||||
'watch-start'=92
|
||||
'watch-stop'=93
|
||||
'subscribe'=94
|
||||
'unsubscribe'=95
|
||||
'optimistic-register'=96
|
||||
'crdt'=97
|
||||
'optional-one'=98
|
||||
'exactly-one'=99
|
||||
'many-unique'=100
|
||||
'many'=101
|
||||
'ordered'=102
|
||||
'unit'=103
|
||||
'watch-handle'=104
|
||||
'message'=105
|
||||
'atom-ref'=106
|
||||
'interface-ref'=107
|
||||
'optional'=108
|
||||
'list'=109
|
||||
'record'=110
|
||||
'bool'=111
|
||||
'bytes'=112
|
||||
'double'=113
|
||||
'int32'=114
|
||||
'int64'=115
|
||||
'string'=116
|
||||
'uint32'=117
|
||||
'uint64'=118
|
||||
'true'=119
|
||||
'false'=120
|
||||
'null'=121
|
||||
'->'=122
|
||||
':'=123
|
||||
';'=124
|
||||
','=125
|
||||
'.'=126
|
||||
'{'=127
|
||||
'}'=128
|
||||
'['=129
|
||||
']'=130
|
||||
'('=131
|
||||
')'=132
|
||||
'<'=133
|
||||
'>'=134
|
||||
'&'=135
|
||||
'='=136
|
||||
CREATION=1
|
||||
INITIALIZE=2
|
||||
WORKSPACE=3
|
||||
EXECUTION=4
|
||||
SNAPSHOT=5
|
||||
TRANSACTION=6
|
||||
REMOTE=7
|
||||
TARGETS=8
|
||||
PORTABLE=9
|
||||
REPLICA=10
|
||||
LOCAL=11
|
||||
FROM=12
|
||||
RESULT_BYTES=13
|
||||
RPC_CALLS=14
|
||||
DEADLINE_MS=15
|
||||
QUERY=16
|
||||
REFLECTION=17
|
||||
SPECIALIZE=18
|
||||
ROOT=19
|
||||
DOCUMENT=20
|
||||
FRAGMENTS=21
|
||||
VIEW=22
|
||||
MAX=23
|
||||
ALLOW=24
|
||||
POLL=25
|
||||
QUERYABLE=26
|
||||
RPC=27
|
||||
QUERY_REASON=28
|
||||
TYPE=29
|
||||
OBJECT=30
|
||||
STORABLE=31
|
||||
IMPLEMENTS=32
|
||||
REF=33
|
||||
FRAGMENT=34
|
||||
IMPORT=35
|
||||
EXTERNAL=36
|
||||
ATOM=37
|
||||
INTERFACE=38
|
||||
INTERFACES=39
|
||||
PACKAGE=40
|
||||
VALUE=41
|
||||
RELATION=42
|
||||
OPERATION=43
|
||||
FUNCTION=44
|
||||
CONSTRUCTOR=45
|
||||
CONSTRUCTS=46
|
||||
INPUT=47
|
||||
CONFORM=48
|
||||
AS=49
|
||||
BIND=50
|
||||
STATIC=51
|
||||
TO=52
|
||||
PRIVATE=53
|
||||
SHARED=54
|
||||
STATE=55
|
||||
EDGE=56
|
||||
PROJECTION=57
|
||||
WITH=58
|
||||
USING=59
|
||||
VIA=60
|
||||
MATERIALIZE=61
|
||||
IF=62
|
||||
ABSENT=63
|
||||
ON=64
|
||||
POLICY=65
|
||||
DEFAULT=66
|
||||
SOURCE=67
|
||||
REPOSITORY=68
|
||||
COMMIT=69
|
||||
REVISION=70
|
||||
SEMANTIC_MAJOR=71
|
||||
ON_DELETE=72
|
||||
RETAIN_OTHER=73
|
||||
KEYED=74
|
||||
PUBLIC_TRAVERSAL=75
|
||||
ID=76
|
||||
DOC=77
|
||||
MODE=78
|
||||
EMITS=79
|
||||
RECEIVER=80
|
||||
REQUIRES=81
|
||||
ANY=82
|
||||
GET=83
|
||||
SET=84
|
||||
WATCH=85
|
||||
START=86
|
||||
STOP=87
|
||||
READ=88
|
||||
WRITE=89
|
||||
RESOLVE=90
|
||||
CONNECT=91
|
||||
DISCONNECT=92
|
||||
CALL=93
|
||||
WATCH_START=94
|
||||
WATCH_STOP=95
|
||||
SUBSCRIBE=96
|
||||
UNSUBSCRIBE=97
|
||||
REGISTER=98
|
||||
CRDT=99
|
||||
OPTIONAL_ONE=100
|
||||
EXACTLY_ONE=101
|
||||
MANY_UNIQUE=102
|
||||
MANY=103
|
||||
ORDERED=104
|
||||
UNIT=105
|
||||
WATCH_HANDLE=106
|
||||
MESSAGE=107
|
||||
ATOM_REF=108
|
||||
INTERFACE_REF=109
|
||||
OPTIONAL=110
|
||||
LIST=111
|
||||
RECORD=112
|
||||
BOOL=113
|
||||
BYTES=114
|
||||
DOUBLE=115
|
||||
INT32=116
|
||||
INT64=117
|
||||
STRING=118
|
||||
UINT32=119
|
||||
UINT64=120
|
||||
TRUE=121
|
||||
FALSE=122
|
||||
NULL=123
|
||||
ARROW=124
|
||||
COLON=125
|
||||
SEMI=126
|
||||
COMMA=127
|
||||
DOT=128
|
||||
LBRACE=129
|
||||
RBRACE=130
|
||||
LBRACK=131
|
||||
RBRACK=132
|
||||
LPAREN=133
|
||||
RPAREN=134
|
||||
LT=135
|
||||
GT=136
|
||||
AMP=137
|
||||
EQUAL=138
|
||||
INTEGER=139
|
||||
JSON_NUMBER=140
|
||||
IDENTIFIER=141
|
||||
STRING_LITERAL=142
|
||||
LINE_COMMENT=143
|
||||
BLOCK_COMMENT=144
|
||||
WS=145
|
||||
'creation'=1
|
||||
'initialize'=2
|
||||
'workspace'=3
|
||||
'execution'=4
|
||||
'snapshot'=5
|
||||
'transaction'=6
|
||||
'remote'=7
|
||||
'targets'=8
|
||||
'portable'=9
|
||||
'replica'=10
|
||||
'local'=11
|
||||
'from'=12
|
||||
'result-bytes'=13
|
||||
'rpc-calls'=14
|
||||
'deadline-ms'=15
|
||||
'query'=16
|
||||
'reflection'=17
|
||||
'specialize'=18
|
||||
'root'=19
|
||||
'document'=20
|
||||
'fragments'=21
|
||||
'view'=22
|
||||
'max'=23
|
||||
'allow'=24
|
||||
'poll'=25
|
||||
'queryable'=26
|
||||
'rpc'=27
|
||||
'query-reason'=28
|
||||
'type'=29
|
||||
'object'=30
|
||||
'storable'=31
|
||||
'implements'=32
|
||||
'ref'=33
|
||||
'fragment'=34
|
||||
'import'=35
|
||||
'external'=36
|
||||
'atom'=37
|
||||
'interface'=38
|
||||
'interfaces'=39
|
||||
'package'=40
|
||||
'value'=41
|
||||
'relation'=42
|
||||
'operation'=43
|
||||
'function'=44
|
||||
'constructor'=45
|
||||
'constructs'=46
|
||||
'input'=47
|
||||
'conform'=48
|
||||
'as'=49
|
||||
'bind'=50
|
||||
'static'=51
|
||||
'to'=52
|
||||
'private'=53
|
||||
'shared'=54
|
||||
'state'=55
|
||||
'edge'=56
|
||||
'projection'=57
|
||||
'with'=58
|
||||
'using'=59
|
||||
'via'=60
|
||||
'materialize'=61
|
||||
'if'=62
|
||||
'absent'=63
|
||||
'on'=64
|
||||
'policy'=65
|
||||
'default'=66
|
||||
'source'=67
|
||||
'repository'=68
|
||||
'commit'=69
|
||||
'revision'=70
|
||||
'semantic-major'=71
|
||||
'on-delete'=72
|
||||
'retain-other'=73
|
||||
'keyed'=74
|
||||
'public-traversal'=75
|
||||
'id'=76
|
||||
'doc'=77
|
||||
'mode'=78
|
||||
'emits'=79
|
||||
'receiver'=80
|
||||
'requires'=81
|
||||
'any'=82
|
||||
'get'=83
|
||||
'set'=84
|
||||
'watch'=85
|
||||
'start'=86
|
||||
'stop'=87
|
||||
'read'=88
|
||||
'write'=89
|
||||
'resolve'=90
|
||||
'connect'=91
|
||||
'disconnect'=92
|
||||
'call'=93
|
||||
'watch-start'=94
|
||||
'watch-stop'=95
|
||||
'subscribe'=96
|
||||
'unsubscribe'=97
|
||||
'register'=98
|
||||
'crdt'=99
|
||||
'optional-one'=100
|
||||
'exactly-one'=101
|
||||
'many-unique'=102
|
||||
'many'=103
|
||||
'ordered'=104
|
||||
'unit'=105
|
||||
'watch-handle'=106
|
||||
'message'=107
|
||||
'atom-ref'=108
|
||||
'interface-ref'=109
|
||||
'optional'=110
|
||||
'list'=111
|
||||
'record'=112
|
||||
'bool'=113
|
||||
'bytes'=114
|
||||
'double'=115
|
||||
'int32'=116
|
||||
'int64'=117
|
||||
'string'=118
|
||||
'uint32'=119
|
||||
'uint64'=120
|
||||
'true'=121
|
||||
'false'=122
|
||||
'null'=123
|
||||
'->'=124
|
||||
':'=125
|
||||
';'=126
|
||||
','=127
|
||||
'.'=128
|
||||
'{'=129
|
||||
'}'=130
|
||||
'['=131
|
||||
']'=132
|
||||
'('=133
|
||||
')'=134
|
||||
'<'=135
|
||||
'>'=136
|
||||
'&'=137
|
||||
'='=138
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,279 +1,283 @@
|
||||
WORKSPACE=1
|
||||
EXECUTION=2
|
||||
SNAPSHOT=3
|
||||
TRANSACTION=4
|
||||
REMOTE=5
|
||||
TARGETS=6
|
||||
PORTABLE=7
|
||||
REPLICA=8
|
||||
LOCAL=9
|
||||
FROM=10
|
||||
RESULT_BYTES=11
|
||||
RPC_CALLS=12
|
||||
DEADLINE_MS=13
|
||||
QUERY=14
|
||||
REFLECTION=15
|
||||
SPECIALIZE=16
|
||||
ROOT=17
|
||||
DOCUMENT=18
|
||||
FRAGMENTS=19
|
||||
VIEW=20
|
||||
MAX=21
|
||||
ALLOW=22
|
||||
POLL=23
|
||||
QUERYABLE=24
|
||||
RPC=25
|
||||
QUERY_REASON=26
|
||||
TYPE=27
|
||||
OBJECT=28
|
||||
STORABLE=29
|
||||
IMPLEMENTS=30
|
||||
REF=31
|
||||
FRAGMENT=32
|
||||
IMPORT=33
|
||||
EXTERNAL=34
|
||||
ATOM=35
|
||||
INTERFACE=36
|
||||
INTERFACES=37
|
||||
PACKAGE=38
|
||||
VALUE=39
|
||||
RELATION=40
|
||||
OPERATION=41
|
||||
FUNCTION=42
|
||||
CONSTRUCTOR=43
|
||||
CONSTRUCTS=44
|
||||
INPUT=45
|
||||
CONFORM=46
|
||||
AS=47
|
||||
BIND=48
|
||||
STATIC=49
|
||||
TO=50
|
||||
PRIVATE=51
|
||||
SHARED=52
|
||||
STATE=53
|
||||
EDGE=54
|
||||
PROJECTION=55
|
||||
WITH=56
|
||||
USING=57
|
||||
VIA=58
|
||||
MATERIALIZE=59
|
||||
IF=60
|
||||
ABSENT=61
|
||||
ON=62
|
||||
POLICY=63
|
||||
DEFAULT=64
|
||||
SOURCE=65
|
||||
REPOSITORY=66
|
||||
COMMIT=67
|
||||
REVISION=68
|
||||
SEMANTIC_MAJOR=69
|
||||
ON_DELETE=70
|
||||
RETAIN_OTHER=71
|
||||
KEYED=72
|
||||
PUBLIC_TRAVERSAL=73
|
||||
ID=74
|
||||
DOC=75
|
||||
MODE=76
|
||||
EMITS=77
|
||||
RECEIVER=78
|
||||
REQUIRES=79
|
||||
ANY=80
|
||||
GET=81
|
||||
SET=82
|
||||
WATCH=83
|
||||
START=84
|
||||
STOP=85
|
||||
READ=86
|
||||
WRITE=87
|
||||
RESOLVE=88
|
||||
CONNECT=89
|
||||
DISCONNECT=90
|
||||
CALL=91
|
||||
WATCH_START=92
|
||||
WATCH_STOP=93
|
||||
SUBSCRIBE=94
|
||||
UNSUBSCRIBE=95
|
||||
OPTIMISTIC_REGISTER=96
|
||||
CRDT=97
|
||||
OPTIONAL_ONE=98
|
||||
EXACTLY_ONE=99
|
||||
MANY_UNIQUE=100
|
||||
MANY=101
|
||||
ORDERED=102
|
||||
UNIT=103
|
||||
WATCH_HANDLE=104
|
||||
MESSAGE=105
|
||||
ATOM_REF=106
|
||||
INTERFACE_REF=107
|
||||
OPTIONAL=108
|
||||
LIST=109
|
||||
RECORD=110
|
||||
BOOL=111
|
||||
BYTES=112
|
||||
DOUBLE=113
|
||||
INT32=114
|
||||
INT64=115
|
||||
STRING=116
|
||||
UINT32=117
|
||||
UINT64=118
|
||||
TRUE=119
|
||||
FALSE=120
|
||||
NULL=121
|
||||
ARROW=122
|
||||
COLON=123
|
||||
SEMI=124
|
||||
COMMA=125
|
||||
DOT=126
|
||||
LBRACE=127
|
||||
RBRACE=128
|
||||
LBRACK=129
|
||||
RBRACK=130
|
||||
LPAREN=131
|
||||
RPAREN=132
|
||||
LT=133
|
||||
GT=134
|
||||
AMP=135
|
||||
EQUAL=136
|
||||
INTEGER=137
|
||||
JSON_NUMBER=138
|
||||
IDENTIFIER=139
|
||||
STRING_LITERAL=140
|
||||
LINE_COMMENT=141
|
||||
BLOCK_COMMENT=142
|
||||
WS=143
|
||||
'workspace'=1
|
||||
'execution'=2
|
||||
'snapshot'=3
|
||||
'transaction'=4
|
||||
'remote'=5
|
||||
'targets'=6
|
||||
'portable'=7
|
||||
'replica'=8
|
||||
'local'=9
|
||||
'from'=10
|
||||
'result-bytes'=11
|
||||
'rpc-calls'=12
|
||||
'deadline-ms'=13
|
||||
'query'=14
|
||||
'reflection'=15
|
||||
'specialize'=16
|
||||
'root'=17
|
||||
'document'=18
|
||||
'fragments'=19
|
||||
'view'=20
|
||||
'max'=21
|
||||
'allow'=22
|
||||
'poll'=23
|
||||
'queryable'=24
|
||||
'rpc'=25
|
||||
'query-reason'=26
|
||||
'type'=27
|
||||
'object'=28
|
||||
'storable'=29
|
||||
'implements'=30
|
||||
'ref'=31
|
||||
'fragment'=32
|
||||
'import'=33
|
||||
'external'=34
|
||||
'atom'=35
|
||||
'interface'=36
|
||||
'interfaces'=37
|
||||
'package'=38
|
||||
'value'=39
|
||||
'relation'=40
|
||||
'operation'=41
|
||||
'function'=42
|
||||
'constructor'=43
|
||||
'constructs'=44
|
||||
'input'=45
|
||||
'conform'=46
|
||||
'as'=47
|
||||
'bind'=48
|
||||
'static'=49
|
||||
'to'=50
|
||||
'private'=51
|
||||
'shared'=52
|
||||
'state'=53
|
||||
'edge'=54
|
||||
'projection'=55
|
||||
'with'=56
|
||||
'using'=57
|
||||
'via'=58
|
||||
'materialize'=59
|
||||
'if'=60
|
||||
'absent'=61
|
||||
'on'=62
|
||||
'policy'=63
|
||||
'default'=64
|
||||
'source'=65
|
||||
'repository'=66
|
||||
'commit'=67
|
||||
'revision'=68
|
||||
'semantic-major'=69
|
||||
'on-delete'=70
|
||||
'retain-other'=71
|
||||
'keyed'=72
|
||||
'public-traversal'=73
|
||||
'id'=74
|
||||
'doc'=75
|
||||
'mode'=76
|
||||
'emits'=77
|
||||
'receiver'=78
|
||||
'requires'=79
|
||||
'any'=80
|
||||
'get'=81
|
||||
'set'=82
|
||||
'watch'=83
|
||||
'start'=84
|
||||
'stop'=85
|
||||
'read'=86
|
||||
'write'=87
|
||||
'resolve'=88
|
||||
'connect'=89
|
||||
'disconnect'=90
|
||||
'call'=91
|
||||
'watch-start'=92
|
||||
'watch-stop'=93
|
||||
'subscribe'=94
|
||||
'unsubscribe'=95
|
||||
'optimistic-register'=96
|
||||
'crdt'=97
|
||||
'optional-one'=98
|
||||
'exactly-one'=99
|
||||
'many-unique'=100
|
||||
'many'=101
|
||||
'ordered'=102
|
||||
'unit'=103
|
||||
'watch-handle'=104
|
||||
'message'=105
|
||||
'atom-ref'=106
|
||||
'interface-ref'=107
|
||||
'optional'=108
|
||||
'list'=109
|
||||
'record'=110
|
||||
'bool'=111
|
||||
'bytes'=112
|
||||
'double'=113
|
||||
'int32'=114
|
||||
'int64'=115
|
||||
'string'=116
|
||||
'uint32'=117
|
||||
'uint64'=118
|
||||
'true'=119
|
||||
'false'=120
|
||||
'null'=121
|
||||
'->'=122
|
||||
':'=123
|
||||
';'=124
|
||||
','=125
|
||||
'.'=126
|
||||
'{'=127
|
||||
'}'=128
|
||||
'['=129
|
||||
']'=130
|
||||
'('=131
|
||||
')'=132
|
||||
'<'=133
|
||||
'>'=134
|
||||
'&'=135
|
||||
'='=136
|
||||
CREATION=1
|
||||
INITIALIZE=2
|
||||
WORKSPACE=3
|
||||
EXECUTION=4
|
||||
SNAPSHOT=5
|
||||
TRANSACTION=6
|
||||
REMOTE=7
|
||||
TARGETS=8
|
||||
PORTABLE=9
|
||||
REPLICA=10
|
||||
LOCAL=11
|
||||
FROM=12
|
||||
RESULT_BYTES=13
|
||||
RPC_CALLS=14
|
||||
DEADLINE_MS=15
|
||||
QUERY=16
|
||||
REFLECTION=17
|
||||
SPECIALIZE=18
|
||||
ROOT=19
|
||||
DOCUMENT=20
|
||||
FRAGMENTS=21
|
||||
VIEW=22
|
||||
MAX=23
|
||||
ALLOW=24
|
||||
POLL=25
|
||||
QUERYABLE=26
|
||||
RPC=27
|
||||
QUERY_REASON=28
|
||||
TYPE=29
|
||||
OBJECT=30
|
||||
STORABLE=31
|
||||
IMPLEMENTS=32
|
||||
REF=33
|
||||
FRAGMENT=34
|
||||
IMPORT=35
|
||||
EXTERNAL=36
|
||||
ATOM=37
|
||||
INTERFACE=38
|
||||
INTERFACES=39
|
||||
PACKAGE=40
|
||||
VALUE=41
|
||||
RELATION=42
|
||||
OPERATION=43
|
||||
FUNCTION=44
|
||||
CONSTRUCTOR=45
|
||||
CONSTRUCTS=46
|
||||
INPUT=47
|
||||
CONFORM=48
|
||||
AS=49
|
||||
BIND=50
|
||||
STATIC=51
|
||||
TO=52
|
||||
PRIVATE=53
|
||||
SHARED=54
|
||||
STATE=55
|
||||
EDGE=56
|
||||
PROJECTION=57
|
||||
WITH=58
|
||||
USING=59
|
||||
VIA=60
|
||||
MATERIALIZE=61
|
||||
IF=62
|
||||
ABSENT=63
|
||||
ON=64
|
||||
POLICY=65
|
||||
DEFAULT=66
|
||||
SOURCE=67
|
||||
REPOSITORY=68
|
||||
COMMIT=69
|
||||
REVISION=70
|
||||
SEMANTIC_MAJOR=71
|
||||
ON_DELETE=72
|
||||
RETAIN_OTHER=73
|
||||
KEYED=74
|
||||
PUBLIC_TRAVERSAL=75
|
||||
ID=76
|
||||
DOC=77
|
||||
MODE=78
|
||||
EMITS=79
|
||||
RECEIVER=80
|
||||
REQUIRES=81
|
||||
ANY=82
|
||||
GET=83
|
||||
SET=84
|
||||
WATCH=85
|
||||
START=86
|
||||
STOP=87
|
||||
READ=88
|
||||
WRITE=89
|
||||
RESOLVE=90
|
||||
CONNECT=91
|
||||
DISCONNECT=92
|
||||
CALL=93
|
||||
WATCH_START=94
|
||||
WATCH_STOP=95
|
||||
SUBSCRIBE=96
|
||||
UNSUBSCRIBE=97
|
||||
REGISTER=98
|
||||
CRDT=99
|
||||
OPTIONAL_ONE=100
|
||||
EXACTLY_ONE=101
|
||||
MANY_UNIQUE=102
|
||||
MANY=103
|
||||
ORDERED=104
|
||||
UNIT=105
|
||||
WATCH_HANDLE=106
|
||||
MESSAGE=107
|
||||
ATOM_REF=108
|
||||
INTERFACE_REF=109
|
||||
OPTIONAL=110
|
||||
LIST=111
|
||||
RECORD=112
|
||||
BOOL=113
|
||||
BYTES=114
|
||||
DOUBLE=115
|
||||
INT32=116
|
||||
INT64=117
|
||||
STRING=118
|
||||
UINT32=119
|
||||
UINT64=120
|
||||
TRUE=121
|
||||
FALSE=122
|
||||
NULL=123
|
||||
ARROW=124
|
||||
COLON=125
|
||||
SEMI=126
|
||||
COMMA=127
|
||||
DOT=128
|
||||
LBRACE=129
|
||||
RBRACE=130
|
||||
LBRACK=131
|
||||
RBRACK=132
|
||||
LPAREN=133
|
||||
RPAREN=134
|
||||
LT=135
|
||||
GT=136
|
||||
AMP=137
|
||||
EQUAL=138
|
||||
INTEGER=139
|
||||
JSON_NUMBER=140
|
||||
IDENTIFIER=141
|
||||
STRING_LITERAL=142
|
||||
LINE_COMMENT=143
|
||||
BLOCK_COMMENT=144
|
||||
WS=145
|
||||
'creation'=1
|
||||
'initialize'=2
|
||||
'workspace'=3
|
||||
'execution'=4
|
||||
'snapshot'=5
|
||||
'transaction'=6
|
||||
'remote'=7
|
||||
'targets'=8
|
||||
'portable'=9
|
||||
'replica'=10
|
||||
'local'=11
|
||||
'from'=12
|
||||
'result-bytes'=13
|
||||
'rpc-calls'=14
|
||||
'deadline-ms'=15
|
||||
'query'=16
|
||||
'reflection'=17
|
||||
'specialize'=18
|
||||
'root'=19
|
||||
'document'=20
|
||||
'fragments'=21
|
||||
'view'=22
|
||||
'max'=23
|
||||
'allow'=24
|
||||
'poll'=25
|
||||
'queryable'=26
|
||||
'rpc'=27
|
||||
'query-reason'=28
|
||||
'type'=29
|
||||
'object'=30
|
||||
'storable'=31
|
||||
'implements'=32
|
||||
'ref'=33
|
||||
'fragment'=34
|
||||
'import'=35
|
||||
'external'=36
|
||||
'atom'=37
|
||||
'interface'=38
|
||||
'interfaces'=39
|
||||
'package'=40
|
||||
'value'=41
|
||||
'relation'=42
|
||||
'operation'=43
|
||||
'function'=44
|
||||
'constructor'=45
|
||||
'constructs'=46
|
||||
'input'=47
|
||||
'conform'=48
|
||||
'as'=49
|
||||
'bind'=50
|
||||
'static'=51
|
||||
'to'=52
|
||||
'private'=53
|
||||
'shared'=54
|
||||
'state'=55
|
||||
'edge'=56
|
||||
'projection'=57
|
||||
'with'=58
|
||||
'using'=59
|
||||
'via'=60
|
||||
'materialize'=61
|
||||
'if'=62
|
||||
'absent'=63
|
||||
'on'=64
|
||||
'policy'=65
|
||||
'default'=66
|
||||
'source'=67
|
||||
'repository'=68
|
||||
'commit'=69
|
||||
'revision'=70
|
||||
'semantic-major'=71
|
||||
'on-delete'=72
|
||||
'retain-other'=73
|
||||
'keyed'=74
|
||||
'public-traversal'=75
|
||||
'id'=76
|
||||
'doc'=77
|
||||
'mode'=78
|
||||
'emits'=79
|
||||
'receiver'=80
|
||||
'requires'=81
|
||||
'any'=82
|
||||
'get'=83
|
||||
'set'=84
|
||||
'watch'=85
|
||||
'start'=86
|
||||
'stop'=87
|
||||
'read'=88
|
||||
'write'=89
|
||||
'resolve'=90
|
||||
'connect'=91
|
||||
'disconnect'=92
|
||||
'call'=93
|
||||
'watch-start'=94
|
||||
'watch-stop'=95
|
||||
'subscribe'=96
|
||||
'unsubscribe'=97
|
||||
'register'=98
|
||||
'crdt'=99
|
||||
'optional-one'=100
|
||||
'exactly-one'=101
|
||||
'many-unique'=102
|
||||
'many'=103
|
||||
'ordered'=104
|
||||
'unit'=105
|
||||
'watch-handle'=106
|
||||
'message'=107
|
||||
'atom-ref'=108
|
||||
'interface-ref'=109
|
||||
'optional'=110
|
||||
'list'=111
|
||||
'record'=112
|
||||
'bool'=113
|
||||
'bytes'=114
|
||||
'double'=115
|
||||
'int32'=116
|
||||
'int64'=117
|
||||
'string'=118
|
||||
'uint32'=119
|
||||
'uint64'=120
|
||||
'true'=121
|
||||
'false'=122
|
||||
'null'=123
|
||||
'->'=124
|
||||
':'=125
|
||||
';'=126
|
||||
','=127
|
||||
'.'=128
|
||||
'{'=129
|
||||
'}'=130
|
||||
'['=131
|
||||
']'=132
|
||||
'('=133
|
||||
')'=134
|
||||
'<'=135
|
||||
'>'=136
|
||||
'&'=137
|
||||
'='=138
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -53,6 +53,9 @@ import { EdgeDeclContext } from "./QuixosCapabilityParser.js";
|
||||
import { EdgeEndpointContext } from "./QuixosCapabilityParser.js";
|
||||
import { ConformanceDeclContext } from "./QuixosCapabilityParser.js";
|
||||
import { ConformanceItemContext } from "./QuixosCapabilityParser.js";
|
||||
import { InitializationDeclContext } from "./QuixosCapabilityParser.js";
|
||||
import { InitializationFieldContext } from "./QuixosCapabilityParser.js";
|
||||
import { CreationOwnerMappingContext } from "./QuixosCapabilityParser.js";
|
||||
import { StateFieldBindingDeclContext } from "./QuixosCapabilityParser.js";
|
||||
import { RelationshipMaterializationDeclContext } from "./QuixosCapabilityParser.js";
|
||||
import { OperationBindingDeclContext } from "./QuixosCapabilityParser.js";
|
||||
@@ -390,6 +393,24 @@ export class QuixosCapabilityVisitor<Result> extends AbstractParseTreeVisitor<Re
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitConformanceItem?: (ctx: ConformanceItemContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `QuixosCapabilityParser.initializationDecl`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitInitializationDecl?: (ctx: InitializationDeclContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `QuixosCapabilityParser.initializationField`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitInitializationField?: (ctx: InitializationFieldContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `QuixosCapabilityParser.creationOwnerMapping`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitCreationOwnerMapping?: (ctx: CreationOwnerMappingContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `QuixosCapabilityParser.stateFieldBindingDecl`.
|
||||
* @param ctx the parse tree
|
||||
|
||||
@@ -1009,6 +1009,14 @@ const lowerDependencyPort = (state: LoweringState, context: DependencyPortContex
|
||||
: undefined;
|
||||
}
|
||||
const atomId = requireSymbol(state, state.atoms, targetName, context, "atom");
|
||||
if (context.CREATION())
|
||||
return atomId
|
||||
? {
|
||||
id,
|
||||
displayName: name,
|
||||
requirement: { kind: "creation", atomId, inputType: lowerValueType(state, context.valueType()) },
|
||||
}
|
||||
: undefined;
|
||||
return atomId
|
||||
? {
|
||||
id,
|
||||
@@ -1229,7 +1237,11 @@ const lowerGenericPackageExport = (
|
||||
throw new GenericTypeError("missing-constructor-input", id, "Constructor ports require an explicit input type");
|
||||
return {
|
||||
...base,
|
||||
requirement: { kind: "constructor", target, inputType: state.types.expression(port.valueType()!) },
|
||||
requirement: {
|
||||
kind: port.CREATION() ? "creation" : "constructor",
|
||||
target,
|
||||
inputType: state.types.expression(port.valueType()!),
|
||||
},
|
||||
};
|
||||
});
|
||||
const operation = "receiverRequirement" in context ? context : undefined;
|
||||
@@ -1567,8 +1579,8 @@ const lowerState = (state: LoweringState, context: StateDeclContext): StateSlotD
|
||||
attachedTo: atomId,
|
||||
displayName: identifier(context.identifier(0)),
|
||||
valueType: lowerValueType(state, context.valueType()),
|
||||
storagePolicy: policy.OPTIMISTIC_REGISTER()
|
||||
? { kind: "optimistic-register" }
|
||||
storagePolicy: policy.REGISTER()
|
||||
? { kind: "register" }
|
||||
: {
|
||||
kind: "crdt-document",
|
||||
updateType: lowerValueType(state, policy.valueType()),
|
||||
@@ -1774,6 +1786,24 @@ const lowerBoundDependencies = (
|
||||
}
|
||||
const atomName = identifier(entry.identifier(1));
|
||||
const atomId = requireSymbol(state, state.atoms, atomName, entry, "atom");
|
||||
if (entry.CREATION())
|
||||
return atomId
|
||||
? [
|
||||
{
|
||||
portId,
|
||||
binding: {
|
||||
kind: "creation",
|
||||
atomId,
|
||||
owners: entry.creationOwnerMapping().map((owner) => ({
|
||||
interfaceRevisionId: new TypeSubstitution(state.types.environment()).application(
|
||||
state.types.interface(owner.interfaceType()),
|
||||
),
|
||||
inputPath: owner.identifier().map(identifier),
|
||||
})),
|
||||
},
|
||||
},
|
||||
]
|
||||
: [];
|
||||
return atomId ? [{ portId, binding: { kind: "constructor", atomId } }] : [];
|
||||
});
|
||||
};
|
||||
@@ -2025,8 +2055,43 @@ const lowerConformance = (
|
||||
const lowered = lowerRelationshipMaterialization(state, interfaceName, materialization);
|
||||
return lowered ? [lowered] : [];
|
||||
});
|
||||
const initializers = context
|
||||
.conformanceItem()
|
||||
.flatMap((item) => (item.initializationDecl() ? [item.initializationDecl()!] : []));
|
||||
if (initializers.length > 1)
|
||||
loweringIssue(state, context, "duplicate-initialization", "Declare one initialization mapping per owner");
|
||||
const initialization = initializers.flatMap((initializer) =>
|
||||
initializer.initializationField().flatMap((field): import("../capability-model/types.js").InitializationField[] => {
|
||||
const input = identifier(field.identifier(0));
|
||||
const attachment = requireSymbol(
|
||||
state,
|
||||
state.attachments,
|
||||
identifier(field.identifier(1)),
|
||||
field,
|
||||
"initialization attachment",
|
||||
);
|
||||
if (!attachment) return [];
|
||||
if (field.STATE() && attachment.attachment.kind === "state")
|
||||
return [{ input, binding: { kind: "state", slotId: attachment.attachment.id } }];
|
||||
if (field.EDGE() && attachment.attachment.kind === "edge") {
|
||||
const projectionId = requireSymbol(
|
||||
state,
|
||||
attachment.projections,
|
||||
identifier(field.identifier(2)),
|
||||
field,
|
||||
"initialization projection",
|
||||
);
|
||||
return projectionId
|
||||
? [{ input, binding: { kind: "edge", edgeTypeId: attachment.attachment.id, projectionId } }]
|
||||
: [];
|
||||
}
|
||||
loweringIssue(state, field, "invalid-initialization", "Initialization attachment kind does not match");
|
||||
return [];
|
||||
}),
|
||||
);
|
||||
state.interfaces.set(interfaceName, originalSymbol);
|
||||
return {
|
||||
...(initializers.length ? { initialization } : {}),
|
||||
atomId,
|
||||
interfaceRevisionId: interfaceSymbol.revisionId,
|
||||
...(context.stringLiteral() ? { id: capabilityId.conformance(stringValue(context.stringLiteral()!)) } : {}),
|
||||
@@ -2562,7 +2627,7 @@ const compileCapabilityResourceSourceInternal = (
|
||||
types.push(requirement.valueType);
|
||||
}
|
||||
if (requirement.kind === "edge") types.push({ kind: "object-ref", expectation: requirement.target });
|
||||
if (requirement.kind === "constructor")
|
||||
if (requirement.kind === "constructor" || requirement.kind === "creation")
|
||||
types.push(requirement.inputType, { kind: "object-ref", expectation: requirement.target });
|
||||
if (requirement.kind === "interface") requires.push(requirement.application);
|
||||
}
|
||||
|
||||
@@ -149,6 +149,10 @@ export const runtimeContracts = (workspace: WorkspaceRevision): RuntimeContract[
|
||||
}
|
||||
if (binding.kind === "state") parent.dependencies.add(`attachment:${binding.slotId}`);
|
||||
if (binding.kind === "edge") parent.dependencies.add(`attachment:${binding.edgeTypeId}`);
|
||||
if (binding.kind === "creation") {
|
||||
for (const owner of binding.owners)
|
||||
parent.dependencies.add(conformanceKey(binding.atomId, owner.interfaceRevisionId));
|
||||
}
|
||||
if (binding.kind === "constructor") {
|
||||
parent.dependencies.add(`constructor:${binding.atomId}`);
|
||||
const ctor = workspace.constructors.find((entry) => entry.atomId === binding.atomId);
|
||||
@@ -210,6 +214,9 @@ export const runtimeContracts = (workspace: WorkspaceRevision): RuntimeContract[
|
||||
atomId: conformance.atomId,
|
||||
interfaceRevisionId: conformance.interfaceRevisionId,
|
||||
operations: sorted(conformance.operationBindings, (entry) => entry.operationId),
|
||||
...(conformance.initialization
|
||||
? { initialization: sorted(conformance.initialization, (entry) => entry.input) }
|
||||
: {}),
|
||||
materializations: sorted(conformance.relationshipMaterializations, (entry) => entry.memberId),
|
||||
});
|
||||
parent.dependencies.add(`interface:${conformance.interfaceRevisionId}`);
|
||||
|
||||
@@ -89,6 +89,8 @@ export function validateExecutionContracts(workspace: WorkspaceRevision): Capabi
|
||||
const query = packages.get(requirement.packageRevisionId)?.queries?.find((q) => q.id === requirement.queryId);
|
||||
if (query?.placement?.kind !== "local")
|
||||
fail(portPath, "Portable operations require a local query dependency");
|
||||
} else if (requirement.kind === "creation") {
|
||||
if (entry.execution.kind !== "transaction") fail(portPath, "Object creation requires transaction execution");
|
||||
} else if (requirement.kind !== "interface")
|
||||
fail(portPath, `Portable execution does not support ${requirement.kind} dependencies`);
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ export type GenericDependencyPort = Omit<DependencyPort, "requirement"> & {
|
||||
application: InterfaceApplicationExpression;
|
||||
operations?: import("./types.js").OperationId[];
|
||||
}
|
||||
| { kind: "creation"; target: ObjectTypeExpression; inputType: ValueTypeExpression }
|
||||
| { kind: "constructor"; target: ObjectTypeExpression; inputType: ValueTypeExpression };
|
||||
};
|
||||
|
||||
@@ -101,6 +102,7 @@ export const specializePackageExport = (
|
||||
...(requirement.operations ? { operations: requirement.operations } : {}),
|
||||
},
|
||||
};
|
||||
case "creation":
|
||||
case "constructor": {
|
||||
const target = substitution.object(requirement.target);
|
||||
if (target.kind !== "atom")
|
||||
@@ -112,7 +114,7 @@ export const specializePackageExport = (
|
||||
return {
|
||||
...port,
|
||||
requirement: {
|
||||
kind: "constructor",
|
||||
kind: requirement.kind,
|
||||
atomId: target.atomId,
|
||||
inputType: substitution.value(requirement.inputType),
|
||||
},
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
import type {
|
||||
BoundDependency,
|
||||
Conformance,
|
||||
DependencyPort,
|
||||
InitializationField,
|
||||
ValueType,
|
||||
WorkspaceRevision,
|
||||
} from "./types.js";
|
||||
import type { CapabilityValidationIssue } from "./validation.js";
|
||||
import { cardinalityValueType, valueTypesEqual } from "./validation.js";
|
||||
|
||||
/** Creation grants seed inputs on new objects, never general private-state authority. */
|
||||
export function validateInitialization(workspace: WorkspaceRevision): CapabilityValidationIssue[] {
|
||||
const issues: CapabilityValidationIssue[] = [];
|
||||
const fail = (path: string, message: string) => issues.push({ code: "invalid-initialization", path, message });
|
||||
const ownerKey = (owner: Conformance) => `${owner.atomId}/${owner.interfaceRevisionId}`;
|
||||
const shapes = new Map<string, ValueType>();
|
||||
const fieldType = (owner: Conformance, field: InitializationField): ValueType | undefined => {
|
||||
const binding = field.binding;
|
||||
const attachment = owner.privateAttachments.find(
|
||||
(a) => a.kind === binding.kind && a.id === (binding.kind === "state" ? binding.slotId : binding.edgeTypeId),
|
||||
);
|
||||
if (!attachment) {
|
||||
fail(ownerKey(owner), `Initialization input ${field.input} must name an attachment owned by this conformance`);
|
||||
return;
|
||||
}
|
||||
if (attachment.kind === "state") return attachment.valueType;
|
||||
if (binding.kind !== "edge") return;
|
||||
const index = attachment.endpoints.findIndex((e) => e.projectionId === binding.projectionId);
|
||||
const endpoint = attachment.endpoints[index];
|
||||
const target = attachment.endpoints[1 - index];
|
||||
if (!endpoint || !target || endpoint.constraint.kind !== "atom" || endpoint.constraint.atomId !== owner.atomId) {
|
||||
fail(ownerKey(owner), `Initialization input ${field.input} must name an edge projection on the newborn atom`);
|
||||
return;
|
||||
}
|
||||
if (endpoint.cardinality === "many" || endpoint.cardinality === "many-unique") {
|
||||
const fields: Record<string, ValueType> = {
|
||||
key: { kind: "scalar", name: "string" },
|
||||
target: cardinalityValueType(target.constraint, "exactly-one"),
|
||||
};
|
||||
if (endpoint.keyType)
|
||||
fields.mapKey = { kind: "scalar", name: endpoint.keyType === "boolean" ? "bool" : endpoint.keyType };
|
||||
return { kind: "list", value: { kind: "record", fields } };
|
||||
}
|
||||
return cardinalityValueType(target.constraint, endpoint.cardinality);
|
||||
};
|
||||
for (const owner of workspace.conformances) {
|
||||
if (!owner.initialization) continue;
|
||||
const fields: Record<string, ValueType> = Object.create(null);
|
||||
const destinations = new Set<string>();
|
||||
for (const field of owner.initialization) {
|
||||
const path = `${ownerKey(owner)}/${field.input}`;
|
||||
if (!field.input || Object.hasOwn(fields, field.input))
|
||||
fail(path, "Initialization input names must be nonempty and distinct");
|
||||
const destination = JSON.stringify(field.binding);
|
||||
if (destinations.has(destination)) fail(path, "An attachment may have only one initialization input");
|
||||
destinations.add(destination);
|
||||
const type = fieldType(owner, field);
|
||||
if (type) fields[field.input] = type;
|
||||
}
|
||||
shapes.set(ownerKey(owner), { kind: "record", fields });
|
||||
}
|
||||
const checkBindings = (ports: DependencyPort[], dependencies: BoundDependency[], path: string) => {
|
||||
for (const dependency of dependencies) {
|
||||
if (dependency.binding.kind !== "creation") continue;
|
||||
const binding = dependency.binding;
|
||||
const requirement = ports.find((p) => p.id === dependency.portId)?.requirement;
|
||||
if (requirement?.kind !== "creation") continue; // General binding validation reports the kind mismatch.
|
||||
const portPath = `${path}/${dependency.portId}`;
|
||||
if (binding.atomId !== requirement.atomId) fail(portPath, `Creation port requires atom ${requirement.atomId}`);
|
||||
const initialized = new Set<string>();
|
||||
const supplied = new Set<string>();
|
||||
for (const mapping of binding.owners) {
|
||||
const key = `${binding.atomId}/${mapping.interfaceRevisionId}`;
|
||||
if (supplied.has(key)) fail(portPath, `Duplicate initialization owner ${key}`);
|
||||
supplied.add(key);
|
||||
const owner = workspace.conformances.find((o) => ownerKey(o) === key);
|
||||
const shape = shapes.get(key);
|
||||
if (!owner || !shape) {
|
||||
fail(portPath, `Owner ${key} has no declared initialization mapping`);
|
||||
continue;
|
||||
}
|
||||
let seed: ValueType | undefined = requirement.inputType;
|
||||
for (const component of mapping.inputPath) seed = seed?.kind === "record" ? seed.fields[component] : undefined;
|
||||
if (!seed || !valueTypesEqual(seed, shape))
|
||||
fail(
|
||||
portPath,
|
||||
`Seed input${mapping.inputPath.map((p) => `.${p}`).join("")} does not match initialization inputs of ${key}`,
|
||||
);
|
||||
for (const field of owner.initialization!)
|
||||
if (field.binding.kind === "state") initialized.add(field.binding.slotId);
|
||||
}
|
||||
const states = [
|
||||
...workspace.sharedAttachments,
|
||||
...workspace.conformances.flatMap((o) => o.privateAttachments),
|
||||
].filter((a) => a.kind === "state" && a.attachedTo === binding.atomId);
|
||||
for (const state of states)
|
||||
if (state.kind === "state" && state.defaultValue === undefined && !initialized.has(state.id))
|
||||
fail(portPath, `Required state ${state.id} has no default or declared seed mapping`);
|
||||
}
|
||||
};
|
||||
const exports = new Map(
|
||||
workspace.packageImports.flatMap((p) => p.exports.map((e) => [`${p.revisionId}/${e.id}`, e] as const)),
|
||||
);
|
||||
for (const owner of workspace.conformances)
|
||||
for (const operation of owner.operationBindings) {
|
||||
if (operation.binding.kind !== "package") continue;
|
||||
const entry = exports.get(`${operation.binding.packageRevisionId}/${operation.binding.exportId}`);
|
||||
if (entry)
|
||||
checkBindings(
|
||||
entry.dependencyPorts,
|
||||
operation.binding.dependencies,
|
||||
`${ownerKey(owner)}/${operation.operationId}`,
|
||||
);
|
||||
}
|
||||
for (const constructor of workspace.constructors) {
|
||||
const entry = exports.get(`${constructor.packageRevisionId}/${constructor.exportId}`);
|
||||
if (entry) checkBindings(entry.dependencyPorts, constructor.dependencies, `constructor/${constructor.atomId}`);
|
||||
}
|
||||
return issues;
|
||||
}
|
||||
@@ -181,7 +181,7 @@ export interface InterfaceRevision {
|
||||
argumentRequirements?: { target: ObjectExpectation; required: InterfaceRevisionId }[];
|
||||
}
|
||||
|
||||
export type StoragePolicy = { kind: "optimistic-register" } | { kind: "crdt-document"; updateType: ValueType };
|
||||
export type StoragePolicy = { kind: "register" } | { kind: "crdt-document"; updateType: ValueType };
|
||||
|
||||
export interface StateSlotDefinition {
|
||||
kind: "state";
|
||||
@@ -246,6 +246,7 @@ export type DependencyPortRequirement =
|
||||
/** Exact public operation identities, not implementation export names. */
|
||||
operations?: OperationId[];
|
||||
}
|
||||
| { kind: "creation"; atomId: AtomId; inputType: ValueType }
|
||||
| { kind: "constructor"; atomId: AtomId; inputType?: ValueType };
|
||||
|
||||
export interface DependencyPort {
|
||||
@@ -320,6 +321,12 @@ export type DependencyBinding =
|
||||
interfaceRevisionId: InterfaceRevisionId;
|
||||
via?: EdgeTraversal;
|
||||
}
|
||||
| {
|
||||
kind: "creation";
|
||||
atomId: AtomId;
|
||||
owners: { interfaceRevisionId: InterfaceRevisionId; inputPath: string[] }[];
|
||||
via?: never;
|
||||
}
|
||||
| { kind: "constructor"; atomId: AtomId };
|
||||
|
||||
export interface BoundDependency {
|
||||
@@ -376,7 +383,13 @@ export interface OperationBinding {
|
||||
queryReason?: string;
|
||||
}
|
||||
|
||||
export interface InitializationField {
|
||||
input: string;
|
||||
binding: { kind: "state"; slotId: SlotId } | { kind: "edge"; edgeTypeId: EdgeTypeId; projectionId: EdgeProjectionId };
|
||||
}
|
||||
|
||||
export interface Conformance {
|
||||
initialization?: InitializationField[];
|
||||
/** Absent only for legacy assemblies awaiting explicit ownership enrollment. */
|
||||
id?: ConformanceId;
|
||||
semanticMajor?: number;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { validateInitialization } from "./initialization.js";
|
||||
import { validateExecutionContracts } from "./execution.js";
|
||||
import { resolveForwardedBinding, type ConcreteBinding } from "./forwarding.js";
|
||||
import type {
|
||||
@@ -42,6 +43,7 @@ import { specializePackageExport } from "./generic-packages.js";
|
||||
import { isDeepStrictEqual } from "node:util";
|
||||
|
||||
export type CapabilityValidationIssueCode =
|
||||
| "invalid-initialization"
|
||||
| "invalid-execution-contract"
|
||||
| "invalid-query-contract"
|
||||
| "query-provider-reason-required"
|
||||
@@ -1043,6 +1045,7 @@ const validatePackages = (
|
||||
);
|
||||
}
|
||||
break;
|
||||
case "creation":
|
||||
case "constructor":
|
||||
if (port.requirement.inputType)
|
||||
validateValueType(issues, port.requirement.inputType, `${portPath}.requirement.inputType`, indexes);
|
||||
@@ -1794,14 +1797,14 @@ const validateConformances = (
|
||||
});
|
||||
if (
|
||||
operation.scope === "class" &&
|
||||
(binding.dependencies.some((entry) => entry.binding.kind !== "constructor") ||
|
||||
packageExport.dependencyPorts.some((entry) => entry.requirement.kind !== "constructor"))
|
||||
(binding.dependencies.some((entry) => !["constructor", "creation"].includes(entry.binding.kind)) ||
|
||||
packageExport.dependencyPorts.some((entry) => !["constructor", "creation"].includes(entry.requirement.kind)))
|
||||
) {
|
||||
issue(
|
||||
issues,
|
||||
"invalid-package-binding",
|
||||
bindingPath,
|
||||
"Class functions may inject constructors, not instance-dependent ports",
|
||||
"Class functions require receiverless dependencies such as creation ports",
|
||||
);
|
||||
}
|
||||
validateBoundDependencies(issues, {
|
||||
@@ -2084,7 +2087,7 @@ export const validateWorkspaceRevision = (workspace: WorkspaceRevision): Capabil
|
||||
validatePackages(workspace, issues, indexes);
|
||||
validateConformances(workspace, issues, indexes);
|
||||
validateConstructors(workspace, issues, indexes);
|
||||
issues.push(...validateExecutionContracts(workspace));
|
||||
issues.push(...validateExecutionContracts(workspace), ...validateInitialization(workspace));
|
||||
return issues;
|
||||
};
|
||||
|
||||
@@ -2327,6 +2330,11 @@ export const computeCapabilityClosure = (
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "creation": {
|
||||
for (const owner of dependency.binding.owners)
|
||||
queued.push({ atomId: dependency.binding.atomId, interfaceRevisionId: owner.interfaceRevisionId });
|
||||
break;
|
||||
}
|
||||
case "constructor": {
|
||||
constructors.add(dependency.binding.atomId);
|
||||
const constructor = plan.constructors.get(dependency.binding.atomId);
|
||||
|
||||
Reference in New Issue
Block a user