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:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user