Add checked React field bindings and Web Studio factories
Replace opaque props with checked generic presentation contracts and lazy typed interface references. Generate readonly/writable field APIs and component checks. Preserve CRDT editing through explicit resolved getter/setter contracts, binding- fenced delta RPCs, native watches and replica-aware field adapters. Custom setters retain semantic writes; storage snapshots never grant write authority. Cover concurrent edits, lost acknowledgements, readonly contracts and authorization. Add receiver-free static factory dispatch, state-field binding shorthand, and conformance-based creation. Migrate TODO, editable scaffolds and authoring guides. Verify language/codegen, SDK, RPC, browser lifecycle, local scaffolds, production browser bundling and CRDT persistence with temporary PostgreSQL.
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -21,100 +21,101 @@ INPUT=20
|
||||
CONFORM=21
|
||||
AS=22
|
||||
BIND=23
|
||||
TO=24
|
||||
PRIVATE=25
|
||||
SHARED=26
|
||||
STATE=27
|
||||
EDGE=28
|
||||
PROJECTION=29
|
||||
WITH=30
|
||||
USING=31
|
||||
VIA=32
|
||||
MATERIALIZE=33
|
||||
IF=34
|
||||
ABSENT=35
|
||||
ON=36
|
||||
POLICY=37
|
||||
DEFAULT=38
|
||||
SOURCE=39
|
||||
REPOSITORY=40
|
||||
COMMIT=41
|
||||
REVISION=42
|
||||
SEMANTIC_MAJOR=43
|
||||
ON_DELETE=44
|
||||
RETAIN_OTHER=45
|
||||
KEYED=46
|
||||
PUBLIC_TRAVERSAL=47
|
||||
ID=48
|
||||
DOC=49
|
||||
MODE=50
|
||||
EMITS=51
|
||||
RECEIVER=52
|
||||
REQUIRES=53
|
||||
ANY=54
|
||||
GET=55
|
||||
SET=56
|
||||
WATCH=57
|
||||
START=58
|
||||
STOP=59
|
||||
READ=60
|
||||
WRITE=61
|
||||
RESOLVE=62
|
||||
CONNECT=63
|
||||
DISCONNECT=64
|
||||
CALL=65
|
||||
WATCH_START=66
|
||||
WATCH_STOP=67
|
||||
SUBSCRIBE=68
|
||||
UNSUBSCRIBE=69
|
||||
OPTIMISTIC_REGISTER=70
|
||||
CRDT=71
|
||||
OPTIONAL_ONE=72
|
||||
EXACTLY_ONE=73
|
||||
MANY_UNIQUE=74
|
||||
MANY=75
|
||||
ORDERED=76
|
||||
UNIT=77
|
||||
WATCH_HANDLE=78
|
||||
MESSAGE=79
|
||||
ATOM_REF=80
|
||||
INTERFACE_REF=81
|
||||
OPTIONAL=82
|
||||
LIST=83
|
||||
RECORD=84
|
||||
BOOL=85
|
||||
BYTES=86
|
||||
DOUBLE=87
|
||||
INT32=88
|
||||
INT64=89
|
||||
STRING=90
|
||||
UINT32=91
|
||||
UINT64=92
|
||||
TRUE=93
|
||||
FALSE=94
|
||||
NULL=95
|
||||
ARROW=96
|
||||
COLON=97
|
||||
SEMI=98
|
||||
COMMA=99
|
||||
DOT=100
|
||||
LBRACE=101
|
||||
RBRACE=102
|
||||
LBRACK=103
|
||||
RBRACK=104
|
||||
LPAREN=105
|
||||
RPAREN=106
|
||||
LT=107
|
||||
GT=108
|
||||
AMP=109
|
||||
EQUAL=110
|
||||
INTEGER=111
|
||||
JSON_NUMBER=112
|
||||
IDENTIFIER=113
|
||||
STRING_LITERAL=114
|
||||
LINE_COMMENT=115
|
||||
BLOCK_COMMENT=116
|
||||
WS=117
|
||||
STATIC=24
|
||||
TO=25
|
||||
PRIVATE=26
|
||||
SHARED=27
|
||||
STATE=28
|
||||
EDGE=29
|
||||
PROJECTION=30
|
||||
WITH=31
|
||||
USING=32
|
||||
VIA=33
|
||||
MATERIALIZE=34
|
||||
IF=35
|
||||
ABSENT=36
|
||||
ON=37
|
||||
POLICY=38
|
||||
DEFAULT=39
|
||||
SOURCE=40
|
||||
REPOSITORY=41
|
||||
COMMIT=42
|
||||
REVISION=43
|
||||
SEMANTIC_MAJOR=44
|
||||
ON_DELETE=45
|
||||
RETAIN_OTHER=46
|
||||
KEYED=47
|
||||
PUBLIC_TRAVERSAL=48
|
||||
ID=49
|
||||
DOC=50
|
||||
MODE=51
|
||||
EMITS=52
|
||||
RECEIVER=53
|
||||
REQUIRES=54
|
||||
ANY=55
|
||||
GET=56
|
||||
SET=57
|
||||
WATCH=58
|
||||
START=59
|
||||
STOP=60
|
||||
READ=61
|
||||
WRITE=62
|
||||
RESOLVE=63
|
||||
CONNECT=64
|
||||
DISCONNECT=65
|
||||
CALL=66
|
||||
WATCH_START=67
|
||||
WATCH_STOP=68
|
||||
SUBSCRIBE=69
|
||||
UNSUBSCRIBE=70
|
||||
OPTIMISTIC_REGISTER=71
|
||||
CRDT=72
|
||||
OPTIONAL_ONE=73
|
||||
EXACTLY_ONE=74
|
||||
MANY_UNIQUE=75
|
||||
MANY=76
|
||||
ORDERED=77
|
||||
UNIT=78
|
||||
WATCH_HANDLE=79
|
||||
MESSAGE=80
|
||||
ATOM_REF=81
|
||||
INTERFACE_REF=82
|
||||
OPTIONAL=83
|
||||
LIST=84
|
||||
RECORD=85
|
||||
BOOL=86
|
||||
BYTES=87
|
||||
DOUBLE=88
|
||||
INT32=89
|
||||
INT64=90
|
||||
STRING=91
|
||||
UINT32=92
|
||||
UINT64=93
|
||||
TRUE=94
|
||||
FALSE=95
|
||||
NULL=96
|
||||
ARROW=97
|
||||
COLON=98
|
||||
SEMI=99
|
||||
COMMA=100
|
||||
DOT=101
|
||||
LBRACE=102
|
||||
RBRACE=103
|
||||
LBRACK=104
|
||||
RBRACK=105
|
||||
LPAREN=106
|
||||
RPAREN=107
|
||||
LT=108
|
||||
GT=109
|
||||
AMP=110
|
||||
EQUAL=111
|
||||
INTEGER=112
|
||||
JSON_NUMBER=113
|
||||
IDENTIFIER=114
|
||||
STRING_LITERAL=115
|
||||
LINE_COMMENT=116
|
||||
BLOCK_COMMENT=117
|
||||
WS=118
|
||||
'workspace'=1
|
||||
'type'=2
|
||||
'object'=3
|
||||
@@ -138,90 +139,91 @@ WS=117
|
||||
'conform'=21
|
||||
'as'=22
|
||||
'bind'=23
|
||||
'to'=24
|
||||
'private'=25
|
||||
'shared'=26
|
||||
'state'=27
|
||||
'edge'=28
|
||||
'projection'=29
|
||||
'with'=30
|
||||
'using'=31
|
||||
'via'=32
|
||||
'materialize'=33
|
||||
'if'=34
|
||||
'absent'=35
|
||||
'on'=36
|
||||
'policy'=37
|
||||
'default'=38
|
||||
'source'=39
|
||||
'repository'=40
|
||||
'commit'=41
|
||||
'revision'=42
|
||||
'semantic-major'=43
|
||||
'on-delete'=44
|
||||
'retain-other'=45
|
||||
'keyed'=46
|
||||
'public-traversal'=47
|
||||
'id'=48
|
||||
'doc'=49
|
||||
'mode'=50
|
||||
'emits'=51
|
||||
'receiver'=52
|
||||
'requires'=53
|
||||
'any'=54
|
||||
'get'=55
|
||||
'set'=56
|
||||
'watch'=57
|
||||
'start'=58
|
||||
'stop'=59
|
||||
'read'=60
|
||||
'write'=61
|
||||
'resolve'=62
|
||||
'connect'=63
|
||||
'disconnect'=64
|
||||
'call'=65
|
||||
'watch-start'=66
|
||||
'watch-stop'=67
|
||||
'subscribe'=68
|
||||
'unsubscribe'=69
|
||||
'optimistic-register'=70
|
||||
'crdt'=71
|
||||
'optional-one'=72
|
||||
'exactly-one'=73
|
||||
'many-unique'=74
|
||||
'many'=75
|
||||
'ordered'=76
|
||||
'unit'=77
|
||||
'watch-handle'=78
|
||||
'message'=79
|
||||
'atom-ref'=80
|
||||
'interface-ref'=81
|
||||
'optional'=82
|
||||
'list'=83
|
||||
'record'=84
|
||||
'bool'=85
|
||||
'bytes'=86
|
||||
'double'=87
|
||||
'int32'=88
|
||||
'int64'=89
|
||||
'string'=90
|
||||
'uint32'=91
|
||||
'uint64'=92
|
||||
'true'=93
|
||||
'false'=94
|
||||
'null'=95
|
||||
'->'=96
|
||||
':'=97
|
||||
';'=98
|
||||
','=99
|
||||
'.'=100
|
||||
'{'=101
|
||||
'}'=102
|
||||
'['=103
|
||||
']'=104
|
||||
'('=105
|
||||
')'=106
|
||||
'<'=107
|
||||
'>'=108
|
||||
'&'=109
|
||||
'='=110
|
||||
'static'=24
|
||||
'to'=25
|
||||
'private'=26
|
||||
'shared'=27
|
||||
'state'=28
|
||||
'edge'=29
|
||||
'projection'=30
|
||||
'with'=31
|
||||
'using'=32
|
||||
'via'=33
|
||||
'materialize'=34
|
||||
'if'=35
|
||||
'absent'=36
|
||||
'on'=37
|
||||
'policy'=38
|
||||
'default'=39
|
||||
'source'=40
|
||||
'repository'=41
|
||||
'commit'=42
|
||||
'revision'=43
|
||||
'semantic-major'=44
|
||||
'on-delete'=45
|
||||
'retain-other'=46
|
||||
'keyed'=47
|
||||
'public-traversal'=48
|
||||
'id'=49
|
||||
'doc'=50
|
||||
'mode'=51
|
||||
'emits'=52
|
||||
'receiver'=53
|
||||
'requires'=54
|
||||
'any'=55
|
||||
'get'=56
|
||||
'set'=57
|
||||
'watch'=58
|
||||
'start'=59
|
||||
'stop'=60
|
||||
'read'=61
|
||||
'write'=62
|
||||
'resolve'=63
|
||||
'connect'=64
|
||||
'disconnect'=65
|
||||
'call'=66
|
||||
'watch-start'=67
|
||||
'watch-stop'=68
|
||||
'subscribe'=69
|
||||
'unsubscribe'=70
|
||||
'optimistic-register'=71
|
||||
'crdt'=72
|
||||
'optional-one'=73
|
||||
'exactly-one'=74
|
||||
'many-unique'=75
|
||||
'many'=76
|
||||
'ordered'=77
|
||||
'unit'=78
|
||||
'watch-handle'=79
|
||||
'message'=80
|
||||
'atom-ref'=81
|
||||
'interface-ref'=82
|
||||
'optional'=83
|
||||
'list'=84
|
||||
'record'=85
|
||||
'bool'=86
|
||||
'bytes'=87
|
||||
'double'=88
|
||||
'int32'=89
|
||||
'int64'=90
|
||||
'string'=91
|
||||
'uint32'=92
|
||||
'uint64'=93
|
||||
'true'=94
|
||||
'false'=95
|
||||
'null'=96
|
||||
'->'=97
|
||||
':'=98
|
||||
';'=99
|
||||
','=100
|
||||
'.'=101
|
||||
'{'=102
|
||||
'}'=103
|
||||
'['=104
|
||||
']'=105
|
||||
'('=106
|
||||
')'=107
|
||||
'<'=108
|
||||
'>'=109
|
||||
'&'=110
|
||||
'='=111
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -21,100 +21,101 @@ INPUT=20
|
||||
CONFORM=21
|
||||
AS=22
|
||||
BIND=23
|
||||
TO=24
|
||||
PRIVATE=25
|
||||
SHARED=26
|
||||
STATE=27
|
||||
EDGE=28
|
||||
PROJECTION=29
|
||||
WITH=30
|
||||
USING=31
|
||||
VIA=32
|
||||
MATERIALIZE=33
|
||||
IF=34
|
||||
ABSENT=35
|
||||
ON=36
|
||||
POLICY=37
|
||||
DEFAULT=38
|
||||
SOURCE=39
|
||||
REPOSITORY=40
|
||||
COMMIT=41
|
||||
REVISION=42
|
||||
SEMANTIC_MAJOR=43
|
||||
ON_DELETE=44
|
||||
RETAIN_OTHER=45
|
||||
KEYED=46
|
||||
PUBLIC_TRAVERSAL=47
|
||||
ID=48
|
||||
DOC=49
|
||||
MODE=50
|
||||
EMITS=51
|
||||
RECEIVER=52
|
||||
REQUIRES=53
|
||||
ANY=54
|
||||
GET=55
|
||||
SET=56
|
||||
WATCH=57
|
||||
START=58
|
||||
STOP=59
|
||||
READ=60
|
||||
WRITE=61
|
||||
RESOLVE=62
|
||||
CONNECT=63
|
||||
DISCONNECT=64
|
||||
CALL=65
|
||||
WATCH_START=66
|
||||
WATCH_STOP=67
|
||||
SUBSCRIBE=68
|
||||
UNSUBSCRIBE=69
|
||||
OPTIMISTIC_REGISTER=70
|
||||
CRDT=71
|
||||
OPTIONAL_ONE=72
|
||||
EXACTLY_ONE=73
|
||||
MANY_UNIQUE=74
|
||||
MANY=75
|
||||
ORDERED=76
|
||||
UNIT=77
|
||||
WATCH_HANDLE=78
|
||||
MESSAGE=79
|
||||
ATOM_REF=80
|
||||
INTERFACE_REF=81
|
||||
OPTIONAL=82
|
||||
LIST=83
|
||||
RECORD=84
|
||||
BOOL=85
|
||||
BYTES=86
|
||||
DOUBLE=87
|
||||
INT32=88
|
||||
INT64=89
|
||||
STRING=90
|
||||
UINT32=91
|
||||
UINT64=92
|
||||
TRUE=93
|
||||
FALSE=94
|
||||
NULL=95
|
||||
ARROW=96
|
||||
COLON=97
|
||||
SEMI=98
|
||||
COMMA=99
|
||||
DOT=100
|
||||
LBRACE=101
|
||||
RBRACE=102
|
||||
LBRACK=103
|
||||
RBRACK=104
|
||||
LPAREN=105
|
||||
RPAREN=106
|
||||
LT=107
|
||||
GT=108
|
||||
AMP=109
|
||||
EQUAL=110
|
||||
INTEGER=111
|
||||
JSON_NUMBER=112
|
||||
IDENTIFIER=113
|
||||
STRING_LITERAL=114
|
||||
LINE_COMMENT=115
|
||||
BLOCK_COMMENT=116
|
||||
WS=117
|
||||
STATIC=24
|
||||
TO=25
|
||||
PRIVATE=26
|
||||
SHARED=27
|
||||
STATE=28
|
||||
EDGE=29
|
||||
PROJECTION=30
|
||||
WITH=31
|
||||
USING=32
|
||||
VIA=33
|
||||
MATERIALIZE=34
|
||||
IF=35
|
||||
ABSENT=36
|
||||
ON=37
|
||||
POLICY=38
|
||||
DEFAULT=39
|
||||
SOURCE=40
|
||||
REPOSITORY=41
|
||||
COMMIT=42
|
||||
REVISION=43
|
||||
SEMANTIC_MAJOR=44
|
||||
ON_DELETE=45
|
||||
RETAIN_OTHER=46
|
||||
KEYED=47
|
||||
PUBLIC_TRAVERSAL=48
|
||||
ID=49
|
||||
DOC=50
|
||||
MODE=51
|
||||
EMITS=52
|
||||
RECEIVER=53
|
||||
REQUIRES=54
|
||||
ANY=55
|
||||
GET=56
|
||||
SET=57
|
||||
WATCH=58
|
||||
START=59
|
||||
STOP=60
|
||||
READ=61
|
||||
WRITE=62
|
||||
RESOLVE=63
|
||||
CONNECT=64
|
||||
DISCONNECT=65
|
||||
CALL=66
|
||||
WATCH_START=67
|
||||
WATCH_STOP=68
|
||||
SUBSCRIBE=69
|
||||
UNSUBSCRIBE=70
|
||||
OPTIMISTIC_REGISTER=71
|
||||
CRDT=72
|
||||
OPTIONAL_ONE=73
|
||||
EXACTLY_ONE=74
|
||||
MANY_UNIQUE=75
|
||||
MANY=76
|
||||
ORDERED=77
|
||||
UNIT=78
|
||||
WATCH_HANDLE=79
|
||||
MESSAGE=80
|
||||
ATOM_REF=81
|
||||
INTERFACE_REF=82
|
||||
OPTIONAL=83
|
||||
LIST=84
|
||||
RECORD=85
|
||||
BOOL=86
|
||||
BYTES=87
|
||||
DOUBLE=88
|
||||
INT32=89
|
||||
INT64=90
|
||||
STRING=91
|
||||
UINT32=92
|
||||
UINT64=93
|
||||
TRUE=94
|
||||
FALSE=95
|
||||
NULL=96
|
||||
ARROW=97
|
||||
COLON=98
|
||||
SEMI=99
|
||||
COMMA=100
|
||||
DOT=101
|
||||
LBRACE=102
|
||||
RBRACE=103
|
||||
LBRACK=104
|
||||
RBRACK=105
|
||||
LPAREN=106
|
||||
RPAREN=107
|
||||
LT=108
|
||||
GT=109
|
||||
AMP=110
|
||||
EQUAL=111
|
||||
INTEGER=112
|
||||
JSON_NUMBER=113
|
||||
IDENTIFIER=114
|
||||
STRING_LITERAL=115
|
||||
LINE_COMMENT=116
|
||||
BLOCK_COMMENT=117
|
||||
WS=118
|
||||
'workspace'=1
|
||||
'type'=2
|
||||
'object'=3
|
||||
@@ -138,90 +139,91 @@ WS=117
|
||||
'conform'=21
|
||||
'as'=22
|
||||
'bind'=23
|
||||
'to'=24
|
||||
'private'=25
|
||||
'shared'=26
|
||||
'state'=27
|
||||
'edge'=28
|
||||
'projection'=29
|
||||
'with'=30
|
||||
'using'=31
|
||||
'via'=32
|
||||
'materialize'=33
|
||||
'if'=34
|
||||
'absent'=35
|
||||
'on'=36
|
||||
'policy'=37
|
||||
'default'=38
|
||||
'source'=39
|
||||
'repository'=40
|
||||
'commit'=41
|
||||
'revision'=42
|
||||
'semantic-major'=43
|
||||
'on-delete'=44
|
||||
'retain-other'=45
|
||||
'keyed'=46
|
||||
'public-traversal'=47
|
||||
'id'=48
|
||||
'doc'=49
|
||||
'mode'=50
|
||||
'emits'=51
|
||||
'receiver'=52
|
||||
'requires'=53
|
||||
'any'=54
|
||||
'get'=55
|
||||
'set'=56
|
||||
'watch'=57
|
||||
'start'=58
|
||||
'stop'=59
|
||||
'read'=60
|
||||
'write'=61
|
||||
'resolve'=62
|
||||
'connect'=63
|
||||
'disconnect'=64
|
||||
'call'=65
|
||||
'watch-start'=66
|
||||
'watch-stop'=67
|
||||
'subscribe'=68
|
||||
'unsubscribe'=69
|
||||
'optimistic-register'=70
|
||||
'crdt'=71
|
||||
'optional-one'=72
|
||||
'exactly-one'=73
|
||||
'many-unique'=74
|
||||
'many'=75
|
||||
'ordered'=76
|
||||
'unit'=77
|
||||
'watch-handle'=78
|
||||
'message'=79
|
||||
'atom-ref'=80
|
||||
'interface-ref'=81
|
||||
'optional'=82
|
||||
'list'=83
|
||||
'record'=84
|
||||
'bool'=85
|
||||
'bytes'=86
|
||||
'double'=87
|
||||
'int32'=88
|
||||
'int64'=89
|
||||
'string'=90
|
||||
'uint32'=91
|
||||
'uint64'=92
|
||||
'true'=93
|
||||
'false'=94
|
||||
'null'=95
|
||||
'->'=96
|
||||
':'=97
|
||||
';'=98
|
||||
','=99
|
||||
'.'=100
|
||||
'{'=101
|
||||
'}'=102
|
||||
'['=103
|
||||
']'=104
|
||||
'('=105
|
||||
')'=106
|
||||
'<'=107
|
||||
'>'=108
|
||||
'&'=109
|
||||
'='=110
|
||||
'static'=24
|
||||
'to'=25
|
||||
'private'=26
|
||||
'shared'=27
|
||||
'state'=28
|
||||
'edge'=29
|
||||
'projection'=30
|
||||
'with'=31
|
||||
'using'=32
|
||||
'via'=33
|
||||
'materialize'=34
|
||||
'if'=35
|
||||
'absent'=36
|
||||
'on'=37
|
||||
'policy'=38
|
||||
'default'=39
|
||||
'source'=40
|
||||
'repository'=41
|
||||
'commit'=42
|
||||
'revision'=43
|
||||
'semantic-major'=44
|
||||
'on-delete'=45
|
||||
'retain-other'=46
|
||||
'keyed'=47
|
||||
'public-traversal'=48
|
||||
'id'=49
|
||||
'doc'=50
|
||||
'mode'=51
|
||||
'emits'=52
|
||||
'receiver'=53
|
||||
'requires'=54
|
||||
'any'=55
|
||||
'get'=56
|
||||
'set'=57
|
||||
'watch'=58
|
||||
'start'=59
|
||||
'stop'=60
|
||||
'read'=61
|
||||
'write'=62
|
||||
'resolve'=63
|
||||
'connect'=64
|
||||
'disconnect'=65
|
||||
'call'=66
|
||||
'watch-start'=67
|
||||
'watch-stop'=68
|
||||
'subscribe'=69
|
||||
'unsubscribe'=70
|
||||
'optimistic-register'=71
|
||||
'crdt'=72
|
||||
'optional-one'=73
|
||||
'exactly-one'=74
|
||||
'many-unique'=75
|
||||
'many'=76
|
||||
'ordered'=77
|
||||
'unit'=78
|
||||
'watch-handle'=79
|
||||
'message'=80
|
||||
'atom-ref'=81
|
||||
'interface-ref'=82
|
||||
'optional'=83
|
||||
'list'=84
|
||||
'record'=85
|
||||
'bool'=86
|
||||
'bytes'=87
|
||||
'double'=88
|
||||
'int32'=89
|
||||
'int64'=90
|
||||
'string'=91
|
||||
'uint32'=92
|
||||
'uint64'=93
|
||||
'true'=94
|
||||
'false'=95
|
||||
'null'=96
|
||||
'->'=97
|
||||
':'=98
|
||||
';'=99
|
||||
','=100
|
||||
'.'=101
|
||||
'{'=102
|
||||
'}'=103
|
||||
'['=104
|
||||
']'=105
|
||||
'('=106
|
||||
')'=107
|
||||
'<'=108
|
||||
'>'=109
|
||||
'&'=110
|
||||
'='=111
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -47,6 +47,7 @@ import { EdgeDeclContext } from "./QuixosCapabilityParser.js";
|
||||
import { EdgeEndpointContext } from "./QuixosCapabilityParser.js";
|
||||
import { ConformanceDeclContext } from "./QuixosCapabilityParser.js";
|
||||
import { ConformanceItemContext } from "./QuixosCapabilityParser.js";
|
||||
import { StateFieldBindingDeclContext } from "./QuixosCapabilityParser.js";
|
||||
import { RelationshipMaterializationDeclContext } from "./QuixosCapabilityParser.js";
|
||||
import { OperationBindingDeclContext } from "./QuixosCapabilityParser.js";
|
||||
import { MemberOperationRefContext } from "./QuixosCapabilityParser.js";
|
||||
@@ -347,6 +348,12 @@ export class QuixosCapabilityVisitor<Result> extends AbstractParseTreeVisitor<Re
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitConformanceItem?: (ctx: ConformanceItemContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `QuixosCapabilityParser.stateFieldBindingDecl`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitStateFieldBindingDecl?: (ctx: StateFieldBindingDeclContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `QuixosCapabilityParser.relationshipMaterializationDecl`.
|
||||
* @param ctx the parse tree
|
||||
|
||||
@@ -552,6 +552,7 @@ const lowerOperationMember = (state: LoweringState, context: OperationMemberCont
|
||||
inputType,
|
||||
outputType,
|
||||
mode: "call",
|
||||
...(context.STATIC() ? { scope: "class" as const } : {}),
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -702,7 +703,15 @@ const lowerInterfaceTemplate = (
|
||||
inputType,
|
||||
outputType,
|
||||
operations: [
|
||||
signature("call", capabilityId.operation(stringValue(operation.stringLiteral(1))), inputType, outputType),
|
||||
{
|
||||
...signature(
|
||||
"call",
|
||||
capabilityId.operation(stringValue(operation.stringLiteral(1))),
|
||||
inputType,
|
||||
outputType,
|
||||
),
|
||||
...(operation.STATIC() ? { scope: "class" as const } : {}),
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
@@ -1430,6 +1439,42 @@ const lowerConformance = (
|
||||
const operationBindings = context
|
||||
.conformanceItem()
|
||||
.flatMap<WorkspaceRevision["conformances"][number]["operationBindings"][number]>((item) => {
|
||||
const field = item.stateFieldBindingDecl();
|
||||
if (field) {
|
||||
const memberName = identifier(field.identifier(0));
|
||||
const member = interfaceSymbol.definition?.members.find((entry) => entry.displayName === memberName);
|
||||
const attachment = requireSymbol(
|
||||
state,
|
||||
state.attachments,
|
||||
identifier(field.identifier(1)),
|
||||
field,
|
||||
"attachment",
|
||||
);
|
||||
if (!member || member.kind !== "value" || attachment?.attachment.kind !== "state") {
|
||||
loweringIssue(
|
||||
state,
|
||||
field,
|
||||
"invalid-state-field-binding",
|
||||
"Field shorthand requires a value member and a state slot",
|
||||
);
|
||||
return [];
|
||||
}
|
||||
const primitives = {
|
||||
get: "read",
|
||||
set: "write",
|
||||
"watch-start": "watch-start",
|
||||
"watch-stop": "watch-stop",
|
||||
} as const;
|
||||
const slotId = attachment.attachment.id;
|
||||
return member.operations.map((operation) => ({
|
||||
operationId: operation.id,
|
||||
binding: {
|
||||
kind: "state" as const,
|
||||
slotId,
|
||||
primitive: primitives[operation.displayName as keyof typeof primitives],
|
||||
},
|
||||
}));
|
||||
}
|
||||
const bindingContext = item.operationBindingDecl();
|
||||
if (!bindingContext) {
|
||||
return [];
|
||||
|
||||
@@ -142,7 +142,7 @@ export const scaffoldRecipe = async (
|
||||
if (react) {
|
||||
create(
|
||||
"src/component.tsx",
|
||||
`// Props are opaque at the platform boundary until capability generics exist.\nexport default function Component(_props: {camino: unknown; render: unknown; dispatch: (action: unknown) => void}) {\n return <section><h1>${name}</h1><p>Edit this component, then run qx-workspace check.</p></section>;\n}\n`,
|
||||
`// Add a checked props export, select it in quixos.check.json options.react,\n// then use its generated ReactResults type. Scaffold bundle does this for you.\nexport default function Component(_props: {camino: Record<string, never>; render: unknown; dispatch: (action: unknown) => void}) {\n return <section><h1>${name}</h1></section>;\n}\n`,
|
||||
);
|
||||
create(
|
||||
"src/impl/sourceGet.ts",
|
||||
@@ -180,14 +180,7 @@ export const scaffoldRecipe = async (
|
||||
bindingOutput: "src/gen/qx.ts",
|
||||
...(react
|
||||
? {
|
||||
options: {
|
||||
messages: {
|
||||
"org.quixos.web-studio.ReactProps": {
|
||||
module: "@quixos/camino-package-runtime",
|
||||
export: "opaqueReactPropsBinding",
|
||||
},
|
||||
},
|
||||
},
|
||||
options: { react: { propsExports: [] } },
|
||||
}
|
||||
: {}),
|
||||
}),
|
||||
@@ -394,9 +387,20 @@ export const scaffoldRecipe = async (
|
||||
for (const [file, content] of Object.entries(spec.initialFiles)) {
|
||||
if (
|
||||
typeof content !== "string" ||
|
||||
["quixos.lock", "flake.nix", "quixos.toolchain.json", "quixos.check.json", "package.json"].includes(file)
|
||||
["quixos.lock", "flake.nix", "quixos.toolchain.json", "package.json"].includes(file)
|
||||
)
|
||||
throw new Error(`Not an initial authored file: ${file}`);
|
||||
if (file === "quixos.check.json") {
|
||||
const check = JSON.parse(content);
|
||||
if (
|
||||
check.backend !== "typescript" ||
|
||||
check.bindingOutput !== "src/gen/qx.ts" ||
|
||||
Object.keys(check).some((key) => !["backend", "bindingOutput", "options"].includes(key))
|
||||
)
|
||||
throw new Error(
|
||||
"Initial check configuration may customize binding options, not the scaffold verification backend or output",
|
||||
);
|
||||
}
|
||||
const existing = files.findIndex((entry) => entry.file === prefix + file);
|
||||
if (existing >= 0) files.splice(existing, 1);
|
||||
create(file, content);
|
||||
|
||||
@@ -310,6 +310,9 @@ const main = async () => {
|
||||
throw new Error("Interface scaffold requires name, id, revision and Quixos toolchain source");
|
||||
const request: StructuralRequest = {
|
||||
kind: "interface",
|
||||
// Like package scaffolding, declaration creation is provisional. Imports
|
||||
// can be attached next; the normal check verifies the complete graph.
|
||||
validation: "syntax",
|
||||
source: spec.source,
|
||||
files: [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user