Compare commits

..
11 changed files with 282 additions and 70 deletions
+4
View File
@@ -0,0 +1,4 @@
{
"monorepoCommit": "15b93e42825a3f8055f6305999a12c5b1cc73330",
"sourcePath": "quixos-instance/packages/todo-react-runtime"
}
+8
View File
@@ -0,0 +1,8 @@
{
"messages": {
"org.quixos.web-studio.ReactProps": {
"module": "@quixos/camino-package-runtime",
"export": "opaqueReactPropsBinding"
}
}
}
Generated
+7 -7
View File
@@ -37,17 +37,17 @@
"quixosNixHelpers": {
"flake": false,
"locked": {
"lastModified": 1788543053,
"narHash": "sha256-3YReATWEVxZinYVi/l3cwOz+oFoZUrwj24kUBQTmUpQ=",
"ref": "refs/tags/quixos-reachability/56bbcd22d17f8c7f120b1e0b5bd1d5a86e91a80a",
"rev": "56bbcd22d17f8c7f120b1e0b5bd1d5a86e91a80a",
"revCount": 8,
"lastModified": 1789354913,
"narHash": "sha256-vCdz/2jZ15GpA7YkmjLGOuO/LoZIeI8v7joDD5EI0oE=",
"ref": "refs/tags/quixos-reachability/8b2a224698da3659dd9a81e237dfe79238ee2836",
"rev": "8b2a224698da3659dd9a81e237dfe79238ee2836",
"revCount": 18,
"type": "git",
"url": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-nix-helpers.git"
},
"original": {
"ref": "refs/tags/quixos-reachability/56bbcd22d17f8c7f120b1e0b5bd1d5a86e91a80a",
"rev": "56bbcd22d17f8c7f120b1e0b5bd1d5a86e91a80a",
"ref": "refs/tags/quixos-reachability/8b2a224698da3659dd9a81e237dfe79238ee2836",
"rev": "8b2a224698da3659dd9a81e237dfe79238ee2836",
"type": "git",
"url": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-nix-helpers.git"
}
+2 -1
View File
@@ -6,7 +6,7 @@
flake-utils.url = "github:numtide/flake-utils";
quixosNixHelpers = {
url = "git+https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-nix-helpers.git?ref=refs/tags/quixos-reachability/56bbcd22d17f8c7f120b1e0b5bd1d5a86e91a80a&rev=56bbcd22d17f8c7f120b1e0b5bd1d5a86e91a80a";
url = "git+https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-nix-helpers.git?ref=refs/tags/quixos-reachability/8b2a224698da3659dd9a81e237dfe79238ee2836&rev=8b2a224698da3659dd9a81e237dfe79238ee2836";
flake = false;
};
};
@@ -18,6 +18,7 @@
quixosHelpers.mkCaminoTsYarnNixifyFlake {
inherit inputs nixpkgs flake-utils;
packageRoot = ./.;
bindingOptions = builtins.fromJSON (builtins.readFile ./bindings.json);
promptName = "todo-react-runtime";
bundle = {
entry = "dist/server.js";
+1 -1
View File
@@ -12,7 +12,7 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@quixos/camino-package-runtime": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/camino-package-runtime.git#commit=a998690446ecf647e3af78e369492c1a3663b66d"
"@quixos/camino-package-runtime": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/camino-package-runtime.git#commit=110e41b268c8ac309e6757f2af3331de417ff9b0"
},
"devDependencies": {
"@types/node": "^24",
+1 -1
View File
@@ -1,6 +1,6 @@
quixos-lock version 1 {
quixos source {
repository "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos.git";
commit "9c3ab572ecfbc83785038c3d9f174516df15d63f";
commit "15b93e42825a3f8055f6305999a12c5b1cc73330";
}
}
+232
View File
@@ -0,0 +1,232 @@
// Generated by quixos-codegen-ts. Do not edit. Binding ABI version 1.
import { bindQxHandler, type BindingValue, type QxObjectRef, type QxWatchHandle, type QxHandler, type QxDerived, type QxContextLifecycle, type QxLiveValue, type RelationshipCollection, type QxHandlerSpec, type QxMessages } from "@quixos/camino-package-runtime";
import { opaqueReactPropsBinding as message0 } from "@quixos/camino-package-runtime";
export const packageRevisionId = "package:todo-react-runtime@1";
export type Contexts = { "createComponent": { "objectId": QxObjectRef<"atom:atom:task-react-component">; "input": QxObjectRef<"atom:atom:task">; "ports": { } } & QxContextLifecycle<{ "objectId": QxObjectRef<"atom:atom:task-react-component">; "input": QxObjectRef<"atom:atom:task">; "ports": { } } & {signal?: AbortSignal}>; "propsGet": { "objectId": QxObjectRef<"atom:atom:task-react-component">; "input": null; "ports": { "subject": { "resolve": () => Promise<Array<QxObjectRef<"atom:atom:task">>>; "collection": () => Promise<RelationshipCollection<QxObjectRef<"atom:atom:task">>> }; "title": { "get": () => Promise<string>; "live": () => Promise<QxLiveValue> }; "status": { "get": () => Promise<string>; "live": () => Promise<QxLiveValue> }; "priority": { "get": () => Promise<string>; "live": () => Promise<QxLiveValue> }; "notes": { "get": () => Promise<string>; "live": () => Promise<QxLiveValue> }; "dueDate": { "get": () => Promise<string>; "live": () => Promise<QxLiveValue> }; "energy": { "get": () => Promise<string>; "live": () => Promise<QxLiveValue> } } } & QxContextLifecycle<{ "objectId": QxObjectRef<"atom:atom:task-react-component">; "input": null; "ports": { "subject": { "resolve": () => Promise<Array<QxObjectRef<"atom:atom:task">>>; "collection": () => Promise<RelationshipCollection<QxObjectRef<"atom:atom:task">>> }; "title": { "get": () => Promise<string>; "live": () => Promise<QxLiveValue> }; "status": { "get": () => Promise<string>; "live": () => Promise<QxLiveValue> }; "priority": { "get": () => Promise<string>; "live": () => Promise<QxLiveValue> }; "notes": { "get": () => Promise<string>; "live": () => Promise<QxLiveValue> }; "dueDate": { "get": () => Promise<string>; "live": () => Promise<QxLiveValue> }; "energy": { "get": () => Promise<string>; "live": () => Promise<QxLiveValue> } } } & {signal?: AbortSignal}>; "propsWatch": { "objectId": QxObjectRef<"atom:atom:task-react-component">; "input": null; "ports": { "subject": { "resolve": () => Promise<Array<QxObjectRef<"atom:atom:task">>>; "collection": () => Promise<RelationshipCollection<QxObjectRef<"atom:atom:task">>> }; "title": { "get": () => Promise<string>; "live": () => Promise<QxLiveValue> }; "status": { "get": () => Promise<string>; "live": () => Promise<QxLiveValue> }; "priority": { "get": () => Promise<string>; "live": () => Promise<QxLiveValue> }; "notes": { "get": () => Promise<string>; "live": () => Promise<QxLiveValue> }; "dueDate": { "get": () => Promise<string>; "live": () => Promise<QxLiveValue> }; "energy": { "get": () => Promise<string>; "live": () => Promise<QxLiveValue> } } } & QxContextLifecycle<{ "objectId": QxObjectRef<"atom:atom:task-react-component">; "input": null; "ports": { "subject": { "resolve": () => Promise<Array<QxObjectRef<"atom:atom:task">>>; "collection": () => Promise<RelationshipCollection<QxObjectRef<"atom:atom:task">>> }; "title": { "get": () => Promise<string>; "live": () => Promise<QxLiveValue> }; "status": { "get": () => Promise<string>; "live": () => Promise<QxLiveValue> }; "priority": { "get": () => Promise<string>; "live": () => Promise<QxLiveValue> }; "notes": { "get": () => Promise<string>; "live": () => Promise<QxLiveValue> }; "dueDate": { "get": () => Promise<string>; "live": () => Promise<QxLiveValue> }; "energy": { "get": () => Promise<string>; "live": () => Promise<QxLiveValue> } } } & {signal?: AbortSignal}>; "propsWatchStop": { "objectId": QxObjectRef<"atom:atom:task-react-component">; "input": QxWatchHandle; "ports": { } } & QxContextLifecycle<{ "objectId": QxObjectRef<"atom:atom:task-react-component">; "input": QxWatchHandle; "ports": { } } & {signal?: AbortSignal}>; "sourceGet": { "objectId": QxObjectRef<"atom:atom:task-react-component">; "input": null; "ports": { } } & QxContextLifecycle<{ "objectId": QxObjectRef<"atom:atom:task-react-component">; "input": null; "ports": { } } & {signal?: AbortSignal}> };
export type Implementation = { "createComponent": QxHandler<Contexts["createComponent"], QxObjectRef<"atom:atom:task-react-component">>; "propsGet": QxHandler<Contexts["propsGet"], BindingValue<typeof message0>> | QxDerived<Contexts["propsGet"], BindingValue<typeof message0>>; "propsWatch": QxDerived<Contexts["propsWatch"], BindingValue<typeof message0>>; "propsWatchStop": QxHandler<Contexts["propsWatchStop"], null>; "sourceGet": QxHandler<Contexts["sourceGet"], string> | QxDerived<Contexts["sourceGet"], string> };
const messages = { "org.quixos.web-studio.ReactProps": message0 } satisfies QxMessages;
const specs = {
"createComponent": {
"inputType": {
"kind": "object-ref",
"expectation": {
"kind": "atom",
"atomId": "atom:task"
}
},
"outputType": {
"kind": "object-ref",
"expectation": {
"kind": "atom",
"atomId": "atom:task-react-component"
}
},
"ports": {}
},
"propsGet": {
"inputType": {
"kind": "builtin",
"name": "unit"
},
"outputType": {
"kind": "message",
"descriptorId": "org.quixos.web-studio.ReactProps"
},
"ports": {
"subject": {
"kind": "edge",
"id": "port:todo-react:subject",
"primitives": [
"resolve"
]
},
"title": {
"kind": "state",
"valueType": {
"kind": "scalar",
"name": "string"
},
"primitives": [
"read"
],
"id": "port:todo-react:title"
},
"status": {
"kind": "state",
"valueType": {
"kind": "scalar",
"name": "string"
},
"primitives": [
"read"
],
"id": "port:todo-react:status"
},
"priority": {
"kind": "state",
"valueType": {
"kind": "scalar",
"name": "string"
},
"primitives": [
"read"
],
"id": "port:todo-react:priority"
},
"notes": {
"kind": "state",
"valueType": {
"kind": "scalar",
"name": "string"
},
"primitives": [
"read"
],
"id": "port:todo-react:notes"
},
"dueDate": {
"kind": "state",
"valueType": {
"kind": "scalar",
"name": "string"
},
"primitives": [
"read"
],
"id": "port:todo-react:due-date"
},
"energy": {
"kind": "state",
"valueType": {
"kind": "scalar",
"name": "string"
},
"primitives": [
"read"
],
"id": "port:todo-react:energy"
}
}
},
"propsWatch": {
"inputType": {
"kind": "builtin",
"name": "unit"
},
"outputType": {
"kind": "builtin",
"name": "watch-handle"
},
"eventType": {
"kind": "message",
"descriptorId": "org.quixos.web-studio.ReactProps"
},
"ports": {
"subject": {
"kind": "edge",
"id": "port:todo-react:subject",
"primitives": [
"resolve"
]
},
"title": {
"kind": "state",
"valueType": {
"kind": "scalar",
"name": "string"
},
"primitives": [
"read"
],
"id": "port:todo-react:title"
},
"status": {
"kind": "state",
"valueType": {
"kind": "scalar",
"name": "string"
},
"primitives": [
"read"
],
"id": "port:todo-react:status"
},
"priority": {
"kind": "state",
"valueType": {
"kind": "scalar",
"name": "string"
},
"primitives": [
"read"
],
"id": "port:todo-react:priority"
},
"notes": {
"kind": "state",
"valueType": {
"kind": "scalar",
"name": "string"
},
"primitives": [
"read"
],
"id": "port:todo-react:notes"
},
"dueDate": {
"kind": "state",
"valueType": {
"kind": "scalar",
"name": "string"
},
"primitives": [
"read"
],
"id": "port:todo-react:due-date"
},
"energy": {
"kind": "state",
"valueType": {
"kind": "scalar",
"name": "string"
},
"primitives": [
"read"
],
"id": "port:todo-react:energy"
}
}
},
"propsWatchStop": {
"inputType": {
"kind": "builtin",
"name": "watch-handle"
},
"outputType": {
"kind": "builtin",
"name": "unit"
},
"ports": {}
},
"sourceGet": {
"inputType": {
"kind": "builtin",
"name": "unit"
},
"outputType": {
"kind": "scalar",
"name": "string"
},
"ports": {}
}
} satisfies Record<string, QxHandlerSpec>;
export const createRuntime = (implementation: Implementation) => ({
packageRevisionId,
exports: {
"export:todo-react-runtime:create-component": bindQxHandler(specs["createComponent"], implementation["createComponent"], messages),
"export:todo-react-runtime:props-get": bindQxHandler(specs["propsGet"], implementation["propsGet"], messages),
"export:todo-react-runtime:props-watch": bindQxHandler(specs["propsWatch"], implementation["propsWatch"], messages),
"export:todo-react-runtime:props-watch-stop": bindQxHandler(specs["propsWatchStop"], implementation["propsWatchStop"], messages),
"export:todo-react-runtime:source-get": bindQxHandler(specs["sourceGet"], implementation["sourceGet"], messages),
},
});
+5 -10
View File
@@ -1,13 +1,8 @@
import { servePackageRuntime } from "@quixos/camino-package-runtime";
import { createRuntime, type Implementation } from "./gen/qx.js";
import { createComponent, props, source, stopWatch } from "./todo-react.impl.js";
servePackageRuntime({
packageRevisionId: "package:todo-react-runtime@1",
exports: {
"export:todo-react-runtime:create-component": createComponent,
"export:todo-react-runtime:source-get": source,
"export:todo-react-runtime:props-get": props,
"export:todo-react-runtime:props-watch": props,
"export:todo-react-runtime:props-watch-stop": stopWatch,
},
});
const implementation: Implementation = {
createComponent, sourceGet: source, propsGet: props, propsWatch: props, propsWatchStop: stopWatch,
};
servePackageRuntime(createRuntime(implementation));
+17 -45
View File
@@ -1,52 +1,24 @@
import fs from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { derived, type RuntimeContext } from "@quixos/camino-package-runtime";
import type { Contexts } from "./gen/qx.js";
const dirname = path.dirname(fileURLToPath(import.meta.url));
const componentSourcePath = path.join(dirname, "todo-component.mjs");
export const source = async () => await fs.readFile(componentSourcePath, "utf8");
export const createComponent = (context: RuntimeContext) => context.objectId;
export const props = derived(async (context: RuntimeContext) => {
const tasks = await context.edge("port:todo-react:subject").resolve();
if (tasks.length !== 1) {
throw new Error(`Task component ${context.objectId} has ${tasks.length} subjects`);
}
const titlePort = context.state<string>("port:todo-react:title");
const statusPort = context.state<string>("port:todo-react:status");
const priorityPort = context.state<string>("port:todo-react:priority");
const notesPort = context.state<string>("port:todo-react:notes");
const dueDatePort = context.state<string>("port:todo-react:due-date");
const energyPort = context.state<string>("port:todo-react:energy");
const [title, status, priority, titleLive, statusLive, priorityLive, notesLive, dueDateLive, energyLive] =
await Promise.all([
titlePort.get(),
statusPort.get(),
priorityPort.get(),
titlePort.live(),
statusPort.live(),
priorityPort.live(),
notesPort.live(),
dueDatePort.live(),
energyPort.live(),
]);
const priorityText = priority && priority !== "NORMAL"
? ` ${priority.toLowerCase()}`
: "";
const componentSourcePath = path.join(path.dirname(fileURLToPath(import.meta.url)), "todo-component.mjs");
export const source = () => fs.readFile(componentSourcePath, "utf8");
export const createComponent = ({ objectId }: Contexts["createComponent"]) => objectId;
export const props = { kind: "derived" as const, get: async ({ objectId, ports }: Contexts["propsGet"]): Promise<Record<string, unknown>> => {
const tasks = await ports.subject.resolve();
if (tasks.length !== 1) throw new Error(`Task component has ${tasks.length} subjects`);
const [title, status, priority, titleLive, statusLive, priorityLive, notesLive, dueDateLive, energyLive] = await Promise.all([
ports.title.get(), ports.status.get(), ports.priority.get(),
ports.title.live(), ports.status.live(), ports.priority.live(),
ports.notes.live(), ports.dueDate.live(), ports.energy.live(),
]);
const priorityText = priority && priority !== "NORMAL" ? ` ${priority.toLowerCase()}` : "";
return {
task_id: tasks[0],
component_id: context.objectId,
title: titleLive,
status: statusLive,
priority: priorityLive,
notes: notesLive,
due_date: dueDateLive,
energy: energyLive,
display_label: `[${status ?? "OPEN"}]${priorityText} ${title ?? "Untitled task"}`,
task_id: tasks[0], component_id: objectId, title: titleLive, status: statusLive,
priority: priorityLive, notes: notesLive, due_date: dueDateLive, energy: energyLive,
display_label: `[${status || "OPEN"}]${priorityText} ${title || "Untitled task"}`,
};
});
}};
export const stopWatch = () => null;
+1 -1
View File
@@ -161,7 +161,7 @@ cacheEntries = {
"@connectrpc/connect@npm:2.1.2" = { filename = "@connectrpc-connect-npm-2.1.2-ab34825de3-4e15000890.zip"; hash = "sha512-ThUACJAjt1Lv1E+pQKWuHh+gDhvrxLoM7ScruTWSDYw7hbd0UOZErUQruMqaJ1sMFxNviWuo7/A2F4Ex2wHWFQ=="; };
"@esbuild/linux-arm64@npm:0.25.12" = { filename = "@esbuild-linux-arm64-npm-0.25.12-a5aaa0e70e-10c0.zip"; hash = "sha512-tm9zhnNR4GZv4A+Sgbt9jdCJ0iGlzvYxGCaxaScbhFH14mX7QWJRYaCvFCZB1dseApmaq6mNwbilL0wJnbB8tw=="; };
"@esbuild/linux-x64@npm:0.25.12" = { filename = "@esbuild-linux-x64-npm-0.25.12-07c7c22cce-10c0.zip"; hash = "sha512-U2QGT8ZIZN8q2WPSFDC32+sZGKgp49gvnHzIf/vKVR4xIzjcgBbjAIKI+FqfGBmGBWu8eCpS7lR9JDXdUHOFkw=="; };
"@quixos/camino-package-runtime@https://gitea-external.egads.tutti.syntaxblitz.net/quixos/camino-package-runtime.git#commit=a998690446ecf647e3af78e369492c1a3663b66d" = { filename = "@quixos-camino-package-runtime-https-683bcbf33c-c90d5d5c53.zip"; hash = "sha512-yQ1dXFMR2k+xbkka2rrhsAcrQFZlJAZEYM0hqwGzdV5RJ+fhQEh3BEgoPiL2yxrxulU4zg/jsj8BTBFRp1feyg=="; };
"@quixos/camino-package-runtime@https://gitea-external.egads.tutti.syntaxblitz.net/quixos/camino-package-runtime.git#commit=110e41b268c8ac309e6757f2af3331de417ff9b0" = { filename = "@quixos-camino-package-runtime-https-5a5a438f14-75b1ffcea9.zip"; hash = "sha512-dbH/zqm6gwFck1pSrJAEXNUl6wfHpOL+jj4IwdHCyf5VOMKInCLr73Yx9NYUvqn3zw3AOfdm/8bUeTz2Htxo/A=="; };
"@types/node@npm:24.13.3" = { filename = "@types-node-npm-24.13.3-b512a0bbeb-a5bc08f49b.zip"; hash = "sha512-pbwI9JuVgdzcqQ4CzXcZejx5mECAdmSULlzVFhpVPU0q6AZPfjKUQQ10jX0Ji1wYSL5/pQwG8pxBk6sWvk5Z6w=="; };
"@typescript/typescript-linux-arm64@npm:7.0.2" = { filename = "@typescript-typescript-linux-arm64-npm-7.0.2-9cacfc53a0-10c0.zip"; hash = "sha512-s4c7nGT/lQIw6x0IfrL0b3ECy/D0g7UoDLdiIWJoM6EGXk5N/dmXdxUdA8Cr3hV/3nO2BYKTQ6Ai8/zGhiSQ3A=="; };
"@typescript/typescript-linux-x64@npm:7.0.2" = { filename = "@typescript-typescript-linux-x64-npm-7.0.2-8dd7ff8d24-10c0.zip"; hash = "sha512-k9EUK5CZ3OOPnyslp8SAAonHJpnpPmlaulppI/NmFyCzNs3UN/TLPUkyQia3KIxgbyTzKoXI5L5fl8Uj9bJ7Cg=="; };
+4 -4
View File
@@ -213,14 +213,14 @@ __metadata:
languageName: node
linkType: hard
"@quixos/camino-package-runtime@https://gitea-external.egads.tutti.syntaxblitz.net/quixos/camino-package-runtime.git#commit=a998690446ecf647e3af78e369492c1a3663b66d":
"@quixos/camino-package-runtime@https://gitea-external.egads.tutti.syntaxblitz.net/quixos/camino-package-runtime.git#commit=110e41b268c8ac309e6757f2af3331de417ff9b0":
version: 0.1.0
resolution: "@quixos/camino-package-runtime@https://gitea-external.egads.tutti.syntaxblitz.net/quixos/camino-package-runtime.git#commit=a998690446ecf647e3af78e369492c1a3663b66d"
resolution: "@quixos/camino-package-runtime@https://gitea-external.egads.tutti.syntaxblitz.net/quixos/camino-package-runtime.git#commit=110e41b268c8ac309e6757f2af3331de417ff9b0"
dependencies:
"@bufbuild/protobuf": "npm:^2.12.1"
"@connectrpc/connect": "npm:^2.1.2"
"@connectrpc/connect-node": "npm:^2.1.2"
checksum: 10c0/c90d5d5c5311da4fb16e491adabae1b0072b40566524064460cd21ab01b3755e5127e7e14048770448283e22f6cb1af1ba5538ce0fe3b23f014c1151a757deca
checksum: 10c0/75b1ffcea9ba83015c935a52ac90045cd525eb07c7a4e2fe8e3e08c1d1c2c9fe5538c2889c22ebef7631f4d614bea9f7cf0dc039f766ffc6d4793cf61edc68fc
languageName: node
linkType: hard
@@ -228,7 +228,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@quixos/todo-react-runtime@workspace:."
dependencies:
"@quixos/camino-package-runtime": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/camino-package-runtime.git#commit=a998690446ecf647e3af78e369492c1a3663b66d"
"@quixos/camino-package-runtime": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/camino-package-runtime.git#commit=110e41b268c8ac309e6757f2af3331de417ff9b0"
"@types/node": "npm:^24"
esbuild: "npm:^0.25.12"
typescript: "npm:^7.0.2"