{"_id":"@anycms/web-client","_rev":"2-2acbcba9cdf0677e5c81cf67efab4b0c","name":"@anycms/web-client","dist-tags":{"latest":"0.1.3"},"versions":{"0.1.2":{"name":"@anycms/web-client","version":"0.1.2","keywords":["anycms","web-client","query-builder","typescript","crud"],"author":{"name":"Liangdi"},"license":"MIT","_id":"@anycms/web-client@0.1.2","maintainers":[{"name":"wuliangdi","email":"wu@liangdi.me"}],"dist":{"shasum":"adb8def862a5fe4fa21e09a5a23467b95cbaebb5","tarball":"https://registry.npmjs.org/@anycms/web-client/-/web-client-0.1.2.tgz","fileCount":6,"integrity":"sha512-p8frgvKJ760wx4GWVV2EyxqsGzDUtrin3KzeP3zoLRnVVY2+VcT5FEVVcnik1Zi2h3TyockI3HIUbI3PgD8OSQ==","signatures":[{"sig":"MEUCIQC5Msw0zLs+HNVoC9v7QvK3sFX66za8Us5Bdt83vPqP+AIgQXiE4a0odCMStE091XT0zKNNpLDNm8iFpKAsjg3HTFk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":37414},"main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}},"gitHead":"e1f2c5339ba7431ccf50736e5e834145770d6340","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"wuliangdi","email":"wu@liangdi.me"},"repository":{"url":"git+https://git.404.net.cn/anycms-rs/anycms-web.git","type":"git","directory":"ts-sdk"},"_npmVersion":"10.9.2","description":"TypeScript SDK for anycms-web CRUD routes and JsonQuery engine","directories":{},"_nodeVersion":"22.16.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":">=5.0"},"_npmOperationalInternal":{"tmp":"tmp/web-client_0.1.2_1778959154837_0.8233685821731838","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@anycms/web-client","version":"0.1.3","description":"TypeScript SDK for anycms-web CRUD routes and JsonQuery engine","keywords":["anycms","web-client","query-builder","typescript","crud"],"license":"MIT","author":{"name":"Liangdi"},"repository":{"type":"git","url":"git+https://git.404.net.cn/anycms-rs/anycms-web.git","directory":"ts-sdk"},"main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}},"scripts":{"build":"tsc","prepublishOnly":"npm run build"},"devDependencies":{"typescript":">=5.0"},"publishConfig":{"access":"public"},"_id":"@anycms/web-client@0.1.3","gitHead":"e1f2c5339ba7431ccf50736e5e834145770d6340","_nodeVersion":"22.16.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-KMkls0xnNlsgdT96Hih3M6YCM5H6r4uOPzo15DuRnWMiNNJmm4mLEsVmA41HlHy52AcM4tR3O8lzuvZesun++g==","shasum":"7fda23727afee7f42ba895ddd5570c42ae37e35b","tarball":"https://registry.npmjs.org/@anycms/web-client/-/web-client-0.1.3.tgz","fileCount":6,"unpackedSize":38062,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCvFEVgOwBAKOoT0Ikjix+G0Zdvlfa8IJdvvFavXyM1CwIge731xz2MctjOSc+zLPPOHv5Uxrzun0LTx1f5+HqXCo4="}]},"_npmUser":{"name":"wuliangdi","email":"wu@liangdi.me"},"directories":{},"maintainers":[{"name":"wuliangdi","email":"wu@liangdi.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/web-client_0.1.3_1778959469908_0.09531760711626447"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-16T19:19:14.749Z","modified":"2026-05-16T19:24:30.179Z","0.1.2":"2026-05-16T19:19:14.968Z","0.1.3":"2026-05-16T19:24:30.034Z"},"author":{"name":"Liangdi"},"license":"MIT","keywords":["anycms","web-client","query-builder","typescript","crud"],"repository":{"type":"git","url":"git+https://git.404.net.cn/anycms-rs/anycms-web.git","directory":"ts-sdk"},"description":"TypeScript SDK for anycms-web CRUD routes and JsonQuery engine","maintainers":[{"name":"wuliangdi","email":"wu@liangdi.me"}],"readme":"# @anycms/web-client\n\nTypeScript SDK for [anycms-web](https://github.com/liangdi/anycms-web) CRUD routes and JsonQuery engine.\n\n提供类型安全的查询构建器和 CRUD API 客户端，与后端 `crud_routes!` 宏生成的路由一一对应。\n\n## 安装\n\n```bash\nnpm install @anycms/web-client\n```\n\n## 使用\n\n### CRUD API 客户端\n\n```ts\nimport { QueryBuilder, createEntityApi } from '@anycms/web-client';\n\nconst api = createEntityApi<Customer>('/api/customer');\n\n// 列表查询（POST /api/customer/list）\nconst result = await api.query(\n  new QueryBuilder().eq('status', 1).page(1, 20).build()\n);\n// result: { items: Customer[], total: number, page: number, pageSize: number }\n\n// CRUD\nconst created = await api.create({ name: 'New' });\nconst item = await api.get('id');\nconst updated = await api.update('id', { name: 'Updated' });\nawait api.delete('id');\n```\n\n### QueryBuilder 查询\n\n```ts\n// 简单查询\nconst query = new QueryBuilder()\n  .eq('status', 1)\n  .in('level', [1, 2, 3])\n  .keyword('搜索关键词')\n  .sort('created_time', 'desc')\n  .page(1, 20)\n  .build();\n\n// AND/OR 嵌套: status=1 AND (level=1 OR level=2)\nconst query = new QueryBuilder()\n  .eq('status', 1)\n  .or(b => b.eq('level', 1).eq('level', 2))\n  .build();\n\n// 复杂嵌套: (type=1 AND level>=2) OR (type=2 AND level=3)\nconst query = new QueryBuilder()\n  .orGroup([\n    b => b.eq('type', 1).gte('level', 2),\n    b => b.eq('type', 2).eq('level', 3),\n  ])\n  .build();\n\n// 范围查询\nconst query = new QueryBuilder()\n  .between('price', 100, 500)\n  .build();\n\n// 文本过滤\nconst query = new QueryBuilder()\n  .notContains('title', 'spam')\n  .isEmpty('remark')\n  .build();\n```\n\n## 路由对应关系\n\nSDK 方法与 `crud_routes!` 宏生成的端点一一对应：\n\n| SDK 方法 | HTTP 方法 | 路径 | 说明 |\n|----------|-----------|------|------|\n| `query(jsonQuery)` | POST | `/list` | JsonQuery 查询 |\n| `get(id)` | GET | `/{id}` | 按 ID 获取 |\n| `create(data)` | POST | `` | 创建 |\n| `update(id, data)` | PUT | `/{id}` | 更新 |\n| `delete(id)` | DELETE | `/{id}` | 删除 |\n\n## 响应格式\n\n后端返回 `ApiResult<T>` 统一响应，SDK 自动解包：\n\n```ts\ninterface ApiResult<T> {\n  success: boolean;\n  data?: T | T[];         // 单个对象或数组\n  message?: string;       // 错误信息\n  code?: number;          // 错误码\n  pagination?: {          // 分页（仅列表查询）\n    total: number;\n    page: number;\n    pageSize: number;\n    currentPage: number;\n  };\n  errors?: { field: string; message: string }[];  // 字段级校验错误\n  traceId?: string;\n}\n```\n\n错误时抛出 `ApiError`：\n\n```ts\ntry {\n  await api.get('invalid-id');\n} catch (e) {\n  if (e instanceof ApiError) {\n    console.log(e.code, e.message, e.errors);\n  }\n}\n```\n\n## API 参考\n\n### QueryBuilder\n\n| 方法 | 说明 |\n|------|------|\n| `eq(field, value)` | 等于 |\n| `ne(field, value)` | 不等于 |\n| `gt(field, value)` | 大于 |\n| `gte(field, value)` | 大于等于 |\n| `lt(field, value)` | 小于 |\n| `lte(field, value)` | 小于等于 |\n| `contains(field, value)` | 模糊包含 (LIKE %value%) |\n| `notContains(field, value)` | 不包含 (NOT LIKE %value%) |\n| `startsWith(field, value)` | 前缀匹配 |\n| `endsWith(field, value)` | 后缀匹配 |\n| `in(field, values)` | 在列表中 |\n| `notIn(field, values)` | 不在列表中 |\n| `between(field, min, max)` | 范围查询 |\n| `isNull(field)` | 为空 (IS NULL) |\n| `isNotNull(field)` | 不为空 (IS NOT NULL) |\n| `isEmpty(field)` | 空字符串 (= '' OR IS NULL) |\n| `isNotEmpty(field)` | 非空字符串 (!= '' AND IS NOT NULL) |\n| `keyword(keyword)` | 关键词搜索 |\n| `sort(field, order)` | 排序 (order: 'asc' / 'desc') |\n| `asc(field)` | 升序排序 |\n| `desc(field)` | 降序排序 |\n| `page(page, pageSize)` | 分页 (默认 pageSize=20) |\n| `or(fn)` | 添加 OR 组 |\n| `and(fn)` | 添加 AND 组 |\n| `orGroup(fns)` | 多个 AND 组之间 OR |\n| `build()` | 构建 JsonQuery 对象 |\n\n### createEntityApi\n\n```ts\nconst api = createEntityApi<T>(basePath, options?)\n```\n\n**Options:**\n\n| 参数 | 说明 |\n|------|------|\n| `baseUrl` | 基础 URL 前缀 |\n| `fetch` | 自定义 fetch 函数 |\n| `headers` | 默认请求头 |\n\n## License\n\nMIT\n","readmeFilename":"README.md"}