{"id":24537450,"url":"https://github.com/paraself/deploy-site","last_synced_at":"2025-03-16T01:22:47.875Z","repository":{"id":55827306,"uuid":"201209272","full_name":"paraself/deploy-site","owner":"paraself","description":null,"archived":false,"fork":false,"pushed_at":"2022-12-11T01:21:51.000Z","size":111,"stargazers_count":1,"open_issues_count":5,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-12-06T09:15:50.600Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/paraself.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-08-08T08:02:10.000Z","updated_at":"2020-04-09T20:15:40.000Z","dependencies_parsed_at":"2023-01-26T12:25:13.417Z","dependency_job_id":null,"html_url":"https://github.com/paraself/deploy-site","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paraself%2Fdeploy-site","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paraself%2Fdeploy-site/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paraself%2Fdeploy-site/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paraself%2Fdeploy-site/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/paraself","download_url":"https://codeload.github.com/paraself/deploy-site/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243811073,"owners_count":20351649,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-22T14:12:45.019Z","updated_at":"2025-03-16T01:22:47.840Z","avatar_url":"https://github.com/paraself.png","language":"TypeScript","readme":"# deploy-site\n\n## 接口说明与使用例子\n```typescript\nimport AV from 'leancloud-storage'\nimport { DeploySite, Version, DeployType } from 'deploy-site'\nimport { ReadStream } from 'fs';\n\n// 存储部署信息的leancloud表\nconst CLASSNAME = 'Deploy'\nconst LEANCLOUD_APP_GROUP = process.env.LEANCLOUD_APP_GROUP || 'local'\nexport let deploySite = new DeploySite\u003cstring\u003e({\n  // 设置部署组名,防止不同组直接传递redis消息\n  groupName: LEANCLOUD_APP_GROUP,\n  // 如果有多个实例,需设置redis地址,使用redis传递消息,提交新部署时让所有实例同时执行部署. \n  // 如果没有设置此项,则只会部署在接收到部署请求的实例上执行部署更新\n  redisUrl: process.env.REDIS_URL_pteppp_cache,\n  // 临时目录\n  tmpPath: 'tmp',\n  // 部署的本地存储地址\n  deployPath: 'public',\n  // 将部署保存在leancloud的 'Deploy' 表中\n  saveCallback:async (params:{\n    name:string\n    zipFile:ReadStream, \n    type: string,\n    version: Version\n  }) =\u003e {\n    let {name,zipFile,type,version} = params\n    let result = await new AV.Object(CLASSNAME).set({\n      name,\n      type,\n      version,\n      file: new AV.File(name, zipFile)\n    }).save()\n    return result.get('objectId')\n  },\n  // 从leancloud的 'Deploy' 表中读取需要的部署数据\n  restoreCallback:async (\n    params: {\n    name?:string\n    /**\n     * 是否只返回最新版本\n     */\n    newest?:boolean\n    /**\n     * 是否只返回需部署版本\n     */\n    onlyCurrent?:boolean\n    /**\n     * 只返回指定的id的内容\n     */\n    id?:string\n    }) =\u003e {\n    let { name, newest, onlyCurrent, id } = params\n    if (newest) {\n      let result = await new AV.Query\u003cAV.Object\u003e(CLASSNAME).equalTo('name',name).descending('createdAt').first()\n      return (result\u0026\u0026[AVObject2Deploy(result)]) || []\n    }\n    if (onlyCurrent) {\n      let result = await new AV.Query\u003cAV.Object\u003e(CLASSNAME)\n        .equalTo('name', name)\n        .equalTo('current', true)\n        .descending('createdAt').first()\n      return (result\u0026\u0026[AVObject2Deploy(result)]) || []\n    }\n    if (id) {\n      let result = await new AV.Query\u003cAV.Object\u003e(CLASSNAME).get(id)\n      return (result\u0026\u0026[AVObject2Deploy(result)]) || []\n    }\n    return (await new AV.Query\u003cAV.Object\u003e(CLASSNAME).equalTo('name', name).descending('createdAt').find())\n      .map(e =\u003eAVObject2Deploy(e))\n  },\n\n   //改变部署的版本\n  changeCurrentDeployCallback: async (params: {id: string})=\u003e{\n    let { id } = params\n    let result = await new AV.Query\u003cAV.Object\u003e(CLASSNAME).get(id)\n    let name = result.get('name')\n\n    // 当前版本的 current 字段为true , 一个name下, 只能有一个current 为true的数据\n    let results = await new AV.Query\u003cAV.Object\u003e(CLASSNAME)\n      .equalTo('name', name)\n      .equalTo('current', true)\n      .find()\n    if (results.length \u003e 0) {\n      results.map(e =\u003e e.set('current', false))\n      AV.Object.saveAll(results)\n    }\n    await result.set('current', true).save()\n    return {name}\n  },\n  // 站点信息\n  sites: [\n    {\n      // 网站名, 通过网站名识别提交的部署,和切换版本\n      name: 'test',\n      // 网站域名\n      host: ['test.site.com'],\n      // 支持端口,暂时不会进行此内容判断\n      protocol: ['http','https'],\n      //部署密匙,防止恶意调用\n      key: 'deploykey',\n      // 网站的根路径\n      route: '/',\n      //部署回调\n      resultCallback:(err?:{name:string,error:string}, msg?:{name:string,id:string}) =\u003e {\n            if(err) console.log(err.name+' error : '+err.error)\n            if(msg) console.log(msg.name+' deploy succeed id : '+ msg.id)\n       }\n    },\n  ]\n})\n\nif (process.env.NODE_ENV) {\n  // 启动时执行部署操作\n  deploySite.deploy()\n}\n\nimport express from 'express'\n\nvar app = express()\n// 注册部署的路由\n// 部署的rest接口为. post: 域名/deploy-upload/encodeURIComponent(name)  表单内容为\n// key: 部署密匙 , app: 网站内容的zip压缩包 , type: 更新类型,内容为 pacth, minor, major\napp.use('/deploy-upload', deploySite.routerUpload())\n\n// 注册网站的路由\napp.use('/', deploySite.routerHost())\n\n// 因为网站的路由为 '/' 要比部署路由后注册, 否则上传部署时会先符合网站路由的规则, 导致访问的是网站路由\n\n```\n## 数据表结构\n### DeployConfig表\n用于部署配置\n```\nname:string -- 部署名, 用以标示不同的网站提交内容\nkey:string -- 部署key, 用以认证部署提交\nroute:{[key:string]:string} -- 路由-文件夹路径 的映射列表 . 留空表示根路由使用根目录\nhost:string[] -- 访问此网站的域名\nlink: string -- 部署信息提示工具中的链接, 用了指向部署的目标网站\nforceHttps: boolean -- 是否强制使用https, 非https访问则跳转到https\nnonWww: boolean -- 是否强制使用非www, www地址则跳转到非www地址\nhistoryFallback : string[] -- 使用fallback的路由, 没有静态资源时, 跳转到路由的根路径\n```\n\n### Deploy表\n作为部署实例, 用于部署记录, 和存储部署包内容\n```\nname:string -- 部署名, 和 Deploy表 中的name对应\nfile:AV.File -- 部署内容的压缩文件\ntype:'patch'|'minor'|'major'  -- 版本推进类型\ncurrent:boolean -- 是否是此name配置下当前使用的版本, 一个name下只能有一个current为true的部署\nversion:{patch:number,minor:number,major:number} -- 此部署的版本\n```\n\n## 管理系统功能\n1. 添加/删除/修改 DeployConfig 条目\n2. 查看某个网站配置下的所有部署\n3. 更改某个网站部署的当前使用版本, 通过云函数 Deploy.SetDeploy({id:string}) 设置部署的objectId 来更改\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparaself%2Fdeploy-site","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fparaself%2Fdeploy-site","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparaself%2Fdeploy-site/lists"}