From e4e148502e2c51eb6bfdfed0a4ae521b7e9a80d8 Mon Sep 17 00:00:00 2001 From: Codex Bot Date: Thu, 12 Nov 2026 17:02:17 +0800 Subject: [PATCH] docs(config): explain SDK example and compiler configuration --- headless/consumer.mjs | 3 +++ next.config.ts | 2 ++ 2 files changed, 5 insertions(+) diff --git a/headless/consumer.mjs b/headless/consumer.mjs index cb973c3..7faa658 100644 --- a/headless/consumer.mjs +++ b/headless/consumer.mjs @@ -26,6 +26,7 @@ const files=new Map(),requests=new Map(); /** 通过对象身份及active校验本地leader句柄;仅演示单进程fence,不是数据库条件写。 */ const check=handle=>{assert.strictEqual(handle,leader);assert.equal(handle.active,true);}; // StoragePort示例:claim取得独占句柄,recover读克隆镜像,commit先准备镜像/文件再一次同步发布。 +// 文件值直接保存传入 bytes 引用;示例要求宿主提供不可变字节载荷,不演示流式文件读写或增量日志。 const storage={ /** 只允许一个活跃leader并递增fence;release幂等失效该句柄,不清除已提交镜像。 */ async claim(requested){assert.equal(leader,undefined);assert.deepEqual(requested,scope);let active=true;const handle={scope:requested,fence:++fence,get active(){return active;},async release(){active=false;if(leader===handle)leader=undefined;}};leader=handle;return handle;}, @@ -59,6 +60,7 @@ const transport=async input=>{ if(known){assert.equal(known.body,input.body);return{status:200,body:known.receipt};} // 示例只含一个canvas版本,先要求版本一致,再应用变更并验证整个文档;每次接受使版本递增一次。 assert.deepEqual(body.expected_versions,{[scope.projectId]:version}); + // server 赋值在 validate 之前,断言失败不会恢复旧 server;此替身只用于下方合法协议路径,不是生产事务实现。 server=applyChanges(server,body.operations.flatMap(operation=>operation.changes));validateDocument(server,registry);version++; // 回执逐一覆盖operations逻辑ID,并携complete=false的模型切片;记录原body方便重试校验。 const receipt={protocol_version:2,request_id:input.requestId,status:'applied',operation_ids:body.operations.map(operation=>operation.id),model:{...model(),complete:false}}; @@ -96,4 +98,5 @@ try{ const hit=hitProjectedCanvas(projection,queries,registry,'portable-view',{space:'scene',point:{x:40,y:10},zoom:1});assert.equal(hit.complete,true);assert.ok(hit.hits.some(hit=>hit.target.id===target.id)); // 输出可机器读取的结果摘要;finally即使断言失败也关闭engine并验证存储领导权已释放。 console.log(JSON.stringify({status:'ok',portableBindings:true,elements:2,count:2,undoDepth,reopened:true,transientViews:0,protocol:2,requests:requests.size,sourceFiles:files.size})); +// 顺序等待 close 后再检查 Storage;若 close 本身拒绝,storage.close 不会执行,错误向脚本调用者传播。 }finally{await engine.close();storage.close();} diff --git a/next.config.ts b/next.config.ts index 42a2bb6..1e8417f 100644 --- a/next.config.ts +++ b/next.config.ts @@ -8,6 +8,7 @@ const config: NextConfig = { reactStrictMode: true, poweredByHeader: false, /** 在现有规则后追加匹配ReactFlow ESM入口的loader,再返回原配置对象,保留框架其它规则。 */ webpack(config) { + // 规则只按路径匹配,不按客户端/服务端分支;loader 自身再检查安装版本和四段源码锚点。 config.module.rules.push({ test: /[\\/]@xyflow[\\/]react[\\/]dist[\\/]esm[\\/]index\.(?:mjs|js)$/, use: [{ loader: require.resolve("./scripts/loaders/xyflow-retained.cjs") }], @@ -25,6 +26,7 @@ const config: NextConfig = { }, /** 只给版本目录内带12位十六进制摘要的JSON分片配置一年immutable缓存,文件内容变化应生成新文件名。 * 不对图标目录manifest、页面或全部JSON一概设置immutable。 */ + // 这里只匹配 URL 外观,不重新读取文件验证摘要;重生成文件名和旧资源保留由资源脚本/发布流程负责。 async headers() { return [{ source: "/canvas-icons/:version/:asset([a-z0-9-]+-[a-f0-9]{12}\\.json)",