2026-09-16 00:12:39 -07:00
import assert from "node:assert/strict" ;
import test from "node:test" ;
import fs from "node:fs/promises" ;
import os from "node:os" ;
import path from "node:path" ;
import { execFile } from "node:child_process" ;
import { promisify } from "node:util" ;
import { createRequire } from "node:module" ;
import { compileCapabilityResourceSource , compileCapabilitySource } from "../src/capability-language/parser.js" ;
import { generateTypeScriptBindings , generatePackageDescriptor } from "../src/bindings/index.js" ;
import { genericImplementationType } from "../src/bindings/generics.js" ;
import { compileWorkspaceRevision , runtimeContracts } from "../src/capability-model/index.js" ;
import { generateAppliedClientContracts } from "../src/bindings/client.js" ;
const source = { repository : "https://example.test/generic.git" , commit : "a" . repeat ( 40 ) };
2026-09-17 11:29:56 -07:00
test ( "runtime conformance descriptors preserve closed and universal collection item types" , async ( t ) => {
const sdk = path . resolve ( "../quixos-instance/packages/camino-package-runtime/dist/index.js" );
// The protocol is also published and tested as a standalone subtree. This
// integration uses the real SDK only when both projects are checked out.
if (
! ( await fs . access ( sdk ). then (
() => true ,
() => false ,
))
) {
t . skip ( "Real SDK integration requires the monorepo checkout" );
return ;
}
const collection = compileCapabilityResourceSource (
`interface Collection<object Item> id "collection" revision "collection@1" {
relation items id "items" : many-unique object Item {resolve id "get"; connect id "add";}
}` ,
{ source },
);
assert . ok ( collection . ok && collection . resource . kind === "interface" );
if ( ! collection . ok || collection . resource . kind !== "interface" ) throw Error ( "interface failed" );
const pkg = compileCapabilityResourceSource (
`import interface Collection;
external atom Book id "book"; external atom Tool id "tool";
package P id "p" revision "p@1" {
operation both id "both" : record {book:atom-ref<Book>; tool:atom-ref<Tool>;} -> unit mode call receiver any requires {
interface books id "books" : Collection<atom Book>;
interface tools id "tools" : Collection<atom Tool>;
};
operation inspect<object Item> id "inspect" : ref<Item> -> unit mode call receiver any requires {
interface items id "items" : Collection<Item>;
2026-09-18 18:54:09 -07:00
reflection metadata id "metadata" [atoms, interfaces];
2026-09-17 11:29:56 -07:00
};
}` ,
{ source , environment : { interfaces : new Map ([[ "Collection" , collection . resource . revision ]]) } },
);
assert . ok ( pkg . ok && pkg . resource . kind === "package" , JSON . stringify ( pkg . diagnostics ));
if ( ! pkg . ok || pkg . resource . kind !== "package" ) throw Error ( "package failed" );
const directory = await fs . mkdtemp ( path . join ( os . tmpdir (), "qx-conformance-types-" ));
try {
const generated = generateTypeScriptBindings (
{
format : "quixos-bindings" ,
version : 1 ,
interfaces : pkg.resource.specializations ?? [],
interfaceTemplates : [ collection . resource . revision ],
packages : [ pkg . resource . revision ],
},
"p@1" ,
{ runtimeModule : sdk },
);
await fs . writeFile ( path . join ( directory , "bindings.mts" ), generated );
await fs . writeFile (
path . join ( directory , "consumer.mts" ),
`import type {Implementation} from "./bindings.mjs";
const implementation: Implementation = {
both: async (context) => {
const view = await context.conform.tryConform(context.objectId, context.ports.books.contract);
if (view) {
await view["items.connect"](context.input.book);
// @ts-expect-error Tool is not Book
await view["items.connect"](context.input.tool);
}
return null;
},
inspect: async (context) => {
2026-09-18 18:54:09 -07:00
await context.ports.metadata.read({selector:{kind:"atoms",interfaceRevisionId:"named"}});
// @ts-expect-error Queries are outside this port's declared authority.
await context.ports.metadata.read({selector:{kind:"queries"}});
// @ts-expect-error Interface inventory does not support atom filters.
await context.ports.metadata.read({selector:{kind:"interfaces",atomId:"book"}});
2026-09-17 11:29:56 -07:00
const view = await context.conform.tryConform(context.objectId, context.ports.items.contract);
if (view) await view["items.connect"](context.input);
return null;
},
};` ,
);
const compiler = path . join (
path . dirname ( createRequire ( import . meta . url ). resolve ( "typescript/package.json" )),
"bin/tsc" ,
);
const result = await promisify ( execFile )( process . execPath , [
compiler ,
"--ignoreConfig" ,
"--noEmit" ,
"--strict" ,
"--skipLibCheck" ,
"--target" ,
"es2023" ,
"--module" ,
"nodenext" ,
path . join ( directory , "consumer.mts" ),
]). catch (( error ) => {
throw Error ( error . stdout + error . stderr );
});
assert . equal ( result . stderr , "" );
} finally {
await fs . rm ( directory , { recursive : true , force : true });
}
});
2026-09-16 00:12:39 -07:00
test ( "generic port aliases retain their defining scope, including shadowed alias names" , () => {
const iface = compileCapabilityResourceSource (
'type Box<value V> = list<V>; interface Data<value V> id "data" revision "data@1" {value payload id "payload" : Box<V> {get id "payload:get";}}' ,
{ source },
);
assert . ok ( iface . ok , JSON . stringify ( iface . diagnostics ));
if ( iface . resource . kind !== "interface" ) throw new Error ( "expected interface" );
const pkg = compileCapabilityResourceSource (
'import interface Data; type Box<value V> = optional<V>; package P id "p" revision "p@1" {operation fetch<value V> id "data@1" : unit -> list<Box<V>> mode call receiver any requires {interface data id "data" : Data<Box<V>>;};}' ,
{ source , environment : { interfaces : new Map ([[ "Data" , iface . resource . revision ]]) } },
);
assert . ok ( pkg . ok , JSON . stringify ( pkg . diagnostics ));
if ( pkg . resource . kind !== "package" ) throw new Error ( "expected package" );
const generated = generateTypeScriptBindings (
{
format : "quixos-bindings" ,
version : 1 ,
interfaces : [],
interfaceTemplates : [ iface . resource . revision ],
packages : [ pkg . resource . revision ],
},
pkg . resource . revision . revisionId ,
);
assert . match ( generated , /"payload.get":\(\)=>Promise<Array<\(T0 \| null\)>>/ );
});
const definition = () => {
const result = compileCapabilityResourceSource (
`package Generic id "generic" revision "generic@1" {
operation echo<value T> id "echo" : T -> T mode call receiver any;
}` ,
{ source },
);
assert . ok ( result . ok , JSON . stringify ( result . diagnostics ));
if ( result . resource . kind !== "package" ) throw new Error ( "expected package" );
return result . resource . revision ;
};
test ( "generic package exports specialize per binding without changing immutable source identity" , () => {
const iface = compileCapabilityResourceSource (
`interface Echo<value T> id "echo-interface" revision "echo-interface@1" {
operation echo id "echo-member" : T -> T {call id "echo-call";}
}` ,
{ source },
);
assert . ok ( iface . ok );
if ( iface . resource . kind !== "interface" ) throw new Error ( "expected interface" );
const pkg = definition ();
const result = compileCapabilitySource (
`workspace W id "w" revision "w@1" commit " ${ source . commit } " {
import interface Echo; import package Generic; atom Thing id "thing";
conform Thing as Echo<string> id "string-echo" {bind echo.call to package Generic.echo<string>;}
conform Thing as Echo<list<int64>> id "list-echo" {bind echo.call to package Generic.echo<list<int64>>;}
}` ,
"workspace.qx" ,
{ interfaces : new Map ([[ "Echo" , iface . resource . revision ]]), packages : new Map ([[ "Generic" , pkg ]]) },
);
assert . ok ( result . ok , JSON . stringify ( result . diagnostics ));
assert . equal ( pkg . exports . length , 0 , "source definition was not mutated" );
const closed = result . workspace . packageImports [ 0 ];
assert . equal ( closed . revisionId , pkg . revisionId );
assert . equal ( closed . exports . length , 2 );
assert . notEqual ( closed . exports [ 0 ]. id , closed . exports [ 1 ]. id );
const oneApplication = structuredClone ( result . workspace );
oneApplication . packageImports [ 0 ]. exports . splice ( 1 );
oneApplication . conformances . splice ( 1 );
assert . notDeepEqual (
runtimeContracts ( oneApplication ),
runtimeContracts ( result . workspace ),
"New specializations invalidate the executable contract even with unchanged package source" ,
);
const schema = {
format : "quixos-bindings" as const ,
version : 1 as const ,
interfaces : result.workspace.interfaceImports ,
packages : [ closed ],
};
const generated = generateTypeScriptBindings ( schema , pkg . revisionId );
assert . match ( generated , /"echo":\s*\(<T0>/ );
for ( const entry of closed . exports ) {
assert . ok ( generated . includes ( entry . id ));
assert . ok ( generatePackageDescriptor ( schema , pkg . revisionId ). includes ( entry . id ));
}
const forged = structuredClone ( result . workspace );
forged . packageImports [ 0 ]. exports [ 0 ]. outputType = { kind : "scalar" , name : "bool" };
const rejected = compileWorkspaceRevision ( forged );
assert . equal ( rejected . ok , false );
if ( ! rejected . ok ) assert . ok ( rejected . issues . some (( issue ) => issue . message . includes ( "Specialized export differs" )));
});
test ( "generated universal implementations compile and cannot assume a concrete value type" , async () => {
const pkg = definition ();
const signature = genericImplementationType ( pkg . genericExports ! [ 0 ], [], () => {
throw new Error ( "unexpected concrete type" );
});
const directory = await fs . mkdtemp ( path . join ( os . tmpdir (), "qx-generic-ts-" ));
const require = createRequire ( import . meta . url );
const compiler = path . join ( path . dirname ( require . resolve ( "typescript/package.json" )), "bin/tsc" );
const run = promisify ( execFile );
2026-09-17 11:29:56 -07:00
const preamble = `type QxObjectRef<T extends string>={readonly identity:T}; type QxConformer={}; type QxContextLifecycle<C>={signal?:AbortSignal}; type Handler= ${ signature } ; \ n` ;
2026-09-16 00:12:39 -07:00
try {
const file = path . join ( directory , "generic.ts" );
await fs . writeFile ( file , preamble + `const handler:Handler=({input})=>input;` );
await run ( process . execPath , [ compiler , "--ignoreConfig" , "--noEmit" , "--strict" , "--target" , "es2023" , file ]);
await fs . writeFile ( file , preamble + `const handler:Handler=({input})=>"not universally T";` );
await assert . rejects (
run ( process . execPath , [ compiler , "--ignoreConfig" , "--noEmit" , "--strict" , "--target" , "es2023" , file ]),
( error ) => {
assert . match ( String (( error as { stdout : string }). stdout ), /not assignable/ );
return true ;
},
);
} finally {
await fs . rm ( directory , { recursive : true , force : true });
}
});
test ( "generic Self follows the receiver parameter, never a preceding export" , () => {
const compile = ( declaration : string ) =>
compileCapabilityResourceSource ( `package P id "p" revision "p@1" { ${ declaration } }` , { source });
const valid = compile ( 'operation identity<object T> id "identity" : unit -> ref<Self> mode call receiver object T;' );
assert . ok ( valid . ok , JSON . stringify ( valid . diagnostics ));
if ( valid . resource . kind !== "package" ) throw new Error ( "expected package" );
const definition = valid . resource . revision . genericExports ! [ 0 ];
assert . deepEqual ( definition . outputType , {
kind : "object-ref" ,
expectation : { kind : "parameter" , parameterId : definition.parameters [ 0 ]. id },
});
assert . equal ( compile ( 'function identity<value T> id "identity" : T -> ref<Self>;' ). ok , false );
assert . equal (
compile ( 'operation events<value T> id "events" : unit -> watch-handle mode watch-start receiver any;' ). ok ,
false ,
);
});
test ( "typed presentation and factory consumers preserve distinct closed applications and return targets" , async () => {
const interfaces = new Map ();
for ( const text of [
'interface Presentation<value Props> id "presentation" revision "presentation@1" {operation props id "props" : unit -> Props {call id "props:get";}}' ,
'interface Factory<object Result> id "factory" revision "factory@1" {operation create id "create" : unit -> ref<Result> {call id "create:call";}}' ,
]) {
const result = compileCapabilityResourceSource ( text , { source });
assert . ok ( result . ok , JSON . stringify ( result . diagnostics ));
interfaces . set ( result . resource . revision . displayName , result . resource . revision );
}
const pkg = compileCapabilityResourceSource (
`import interface Presentation; import interface Factory;
external atom Note id "note"; external atom Notebook id "notebook";
package Views id "views" revision "views@1" {
operation note id "note-view" : unit -> unit mode call receiver any requires {interface props id "props" : Presentation<record {title:string; note:atom-ref<Note>;}>;};
operation notebook id "notebook-view" : unit -> unit mode call receiver any requires {interface props id "props" : Presentation<record {count:int32;}>;};
operation factory id "factory-view" : unit -> unit mode call receiver any requires {interface factory id "factory" : Factory<atom Note>;};
}` ,
{ source , environment : { interfaces } },
);
assert . ok ( pkg . ok , JSON . stringify ( pkg . diagnostics ));
const closed = pkg . resource . specializations ! ;
const presentation = closed . find (
( contract ) =>
contract . application ? . definitionId === "presentation@1" && JSON . stringify ( contract ). includes ( '"title"' ),
) ! ;
const factory = closed . find (( contract ) => contract . application ? . definitionId === "factory@1" ) ! ;
const contracts = generateAppliedClientContracts ( closed );
const directory = await fs . mkdtemp ( path . join ( os . tmpdir (), "qx-presentation-types-" ));
const compiler = path . join (
path . dirname ( createRequire ( import . meta . url ). resolve ( "typescript/package.json" )),
"bin/tsc" ,
);
const run = promisify ( execFile );
const usage = `type Props=CapabilityOutput< ${ JSON . stringify ( presentation . revisionId ) } ,"props:get">;
type Created=CapabilityOutput< ${ JSON . stringify ( factory . revisionId ) } ,"create:call">;
const render=({camino,render}:{camino:Props;render:{onSelect:(note:Created)=>void;compact:boolean}})=>{render.onSelect(camino.note);return camino.title;}; \ n` ;
try {
const file = path . join ( directory , "consumer.ts" );
await fs . writeFile ( file , contracts + usage );
await run ( process . execPath , [ compiler , "--ignoreConfig" , "--noEmit" , "--strict" , "--target" , "es2023" , file ]);
await fs . writeFile ( file , contracts + usage + "const wrong=(props:Props)=>props.count;" );
await assert . rejects (
run ( process . execPath , [ compiler , "--ignoreConfig" , "--noEmit" , "--strict" , "--target" , "es2023" , file ]),
( error ) => {
assert . match ( String (( error as { stdout : string }). stdout ), /count.*does not exist/ );
return true ;
},
);
} finally {
await fs . rm ( directory , { recursive : true , force : true });
}
});