@deveco-test/deveco-cli-openharmony-arm64 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +837 -0
- package/SKILL.md +186 -0
- package/THIRD-PARTY-LICENSES +5566 -0
- package/dist/cli.js +1422 -0
- package/dist/internal/doc-init-background.js +66 -0
- package/docs.zip +4 -0
- package/index.zip +0 -0
- package/package.json +108 -0
- package/scripts/install-better-sqlite3.mjs +51 -0
- package/scripts/install-jieba-wasm.mjs +47 -0
- package/scripts/lib/better-sqlite3-vendor.mjs +128 -0
- package/scripts/lib/cli-data-dir.mjs +44 -0
- package/scripts/lib/doc-init-log-path.mjs +15 -0
- package/scripts/lib/jieba-wasm-vendor.mjs +102 -0
- package/scripts/postinstall.mjs +64 -0
- package/src/resources/aclPermission/aclPermissionsInfo.json +311 -0
- package/templates/application/AppScope/app.json5 +10 -0
- package/templates/application/AppScope/resources/base/element/string.json +8 -0
- package/templates/application/AppScope/resources/base/media/layered_image.json +7 -0
- package/templates/application/build-profile.json5 +42 -0
- package/templates/application/code-linter.json5 +32 -0
- package/templates/application/entry/build-profile.json5 +33 -0
- package/templates/application/entry/gitignore.txt +6 -0
- package/templates/application/entry/hvigorfile.ts +7 -0
- package/templates/application/entry/obfuscation-rules.txt +20 -0
- package/templates/application/entry/oh-package.json5 +10 -0
- package/templates/application/entry/src/main/ets/entryability/EntryAbility.ets +63 -0
- package/templates/application/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets +31 -0
- package/templates/application/entry/src/main/ets/pages/Index.ets +38 -0
- package/templates/application/entry/src/main/module.json5 +50 -0
- package/templates/application/entry/src/main/resources/base/element/color.json +8 -0
- package/templates/application/entry/src/main/resources/base/element/float.json +8 -0
- package/templates/application/entry/src/main/resources/base/element/string.json +16 -0
- package/templates/application/entry/src/main/resources/base/media/layered_image.json +7 -0
- package/templates/application/entry/src/main/resources/base/profile/backup_config.json +3 -0
- package/templates/application/entry/src/main/resources/base/profile/main_pages.json +5 -0
- package/templates/application/entry/src/main/resources/dark/element/color.json +8 -0
- package/templates/application/gitignore.txt +12 -0
- package/templates/application/hvigor/hvigor-config.json5 +23 -0
- package/templates/application/hvigorfile.ts +7 -0
- package/templates/application/oh-package.json5 +10 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import*as h from"fs";import*as T from"path";import Mi from"adm-zip";import ki from"proper-lockfile";import vi from"ora";import*as A from"fs";import*as at from"path";var Bt=["harmonyos-guides","harmonyos-references","best-practices","harmonyos-faqs","harmonyos-releases","harmonyos-roadmap"],dt={"harmonyos-guides":"\u5F00\u53D1\u6307\u5357","harmonyos-references":"API\u53C2\u8003","best-practices":"\u6700\u4F73\u5B9E\u8DF5","harmonyos-faqs":"FAQ","harmonyos-releases":"\u7248\u672C\u8BF4\u660E","harmonyos-roadmap":"\u53D8\u66F4\u9884\u544A"};var H="1.9.1",Vi=48*1024*1024,Ae=280,De=6,Ie=100,Te=3,Ce=28,Mt=10,Re=/API参考|APIReference/i;var Ne=6,mt=700,kt=250,vt=400,Pe=1320,Oe=120,Le=450,Be=250,Me=500,ke=480,ve=80,Fe=200,ze=60,He=200,je=40,Ue=200,Ze=200,$e=40,j=500,Ge=Object.fromEntries(Bt.map((t,e)=>[dt[t],e])),O=Object.fromEntries(Bt.map((t,e)=>[t,e]));import*as tt from"fs";import*as m from"path";import{fileURLToPath as Ve}from"url";import*as L from"fs";import*as Qe from"path";import{homedir as xr}from"os";import*as Xe from"fs";import*as E from"path";function V(t,e){let n=E.relative(e,t);return n===""||!E.isAbsolute(n)&&!n.startsWith(`..${E.sep}`)&&n!==".."}function U(t){let e=E.resolve(t),n=[],r=e;for(;;)try{let o=Xe.realpathSync(r);return n.length===0?o:E.join(o,...n.reverse())}catch(o){if(o.code!=="ENOENT")throw o;let i=E.dirname(r);if(i===r)return e;n.push(E.basename(r)),r=i}}function We(t,e){let n=U(e),r=U(t);return V(r,n)?r:null}function Ft(t){let e=t.trim();return(e.startsWith('"')&&e.endsWith('"')||e.startsWith("'")&&e.endsWith("'"))&&(e=e.slice(1,-1).trim()),e}function qe(t){let e=Ft(t);if(!e)throw new Error("Path must not be empty.");return U(e)}var Er="deveco-cli",zt,k=class extends Error{constructor(e){super(e),this.name="CliDataDirError"}};function Je(){let t=process.env.DEVECO_CLI_DATA_DIR,n=(t===void 0||t===""?"":Ft(t))||Qe.join(xr(),".local","share",Er);try{return qe(n)}catch(r){throw new k(r instanceof Error?r.message:String(r))}}async function Ye(){let t=Je();await L.promises.mkdir(t,{recursive:!0});let e;try{e=await L.promises.realpath(t)}catch(r){throw new k(`DEVECO_CLI_DATA_DIR is not usable: ${r instanceof Error?r.message:String(r)}`)}if(!(await L.promises.stat(e)).isDirectory())throw new k("DEVECO_CLI_DATA_DIR must be a writable directory.");return zt=e,e}function K(){if(zt!==void 0)return zt;let t=Je();try{if(L.existsSync(t))return L.realpathSync(t)}catch{}return t}var _r="docs";function Z(){return m.join(K(),_r)}function g(){return m.join(Z(),".index")}function ft(){return m.join(g(),"build.lock")}function et(){return m.join(g(),"build-status.json")}function $(){return m.join(g(),"build-meta.json")}function G(){return m.join(g(),"search.db")}function nt(){return m.join(g(),"sqlite-backend.json")}function rt(){return m.join(g(),"jieba-backend.json")}function C(){return m.join(g(),".tmp")}function br(){return m.join(K(),"logs")}function Ht(){return m.join(br(),"doc-init.log")}function wr(t,e){let n=e;for(;!n.endsWith(`${m.sep}dist`)&&n!==m.dirname(n);)n=m.dirname(n);return n}function Ke(t,e){return m.dirname(wr(t,e))}function tn(){let t=Ve(import.meta.url),e=m.dirname(t);return t.includes(`${m.sep}dist${m.sep}`)?Ke(t,e):m.join(e,"..","..","..")}function Ar(...t){let e=Ve(import.meta.url),n=m.dirname(e);return e.includes(`${m.sep}dist${m.sep}`)?[m.join(Ke(e,n),...t)]:[m.join(n,"..","..","..",...t)]}function en(...t){let e=tn(),n=tt.realpathSync(e);for(let r of Ar(...t))try{let o=tt.lstatSync(r);if(o.isSymbolicLink()||!o.isFile())throw new Error(`Unsafe documentation package asset: ${t.join("/")} must be a regular file.`);let i=tt.realpathSync(r);if(!V(i,n))throw new Error(`Unsafe documentation package asset: ${t.join("/")} is outside the package.`);return i}catch(o){if(o.code!=="ENOENT")throw o}return null}function v(){return en("docs.zip")}function jt(){return en("index.zip")}function nn(){return m.join(tn(),"index","data")}import*as R from"fs";import*as F from"path";var N=["harmonyos-terms.txt","harmonyos-synonyms.json","harmonyos-stopwords.txt"],Ut=class extends Error{constructor(e){super(e),this.name="LexiconNotFoundError"}};var Zt=null;function $t(t){Zt=t}function rn(){if(Zt)return Zt;let t=g();if(N.every(o=>R.existsSync(F.join(t,o))))return t;let n=nn();if(N.every(o=>R.existsSync(F.join(n,o))))return n;throw new Ut("Lexicon files not found. Install the documentation index first (index.zip).")}function X(t){let e=F.join(rn(),t);return R.readFileSync(e,"utf-8")}function on(t,e){return R.readFileSync(F.join(e,t),"utf-8")}async function sn(t,e=rn()){await R.promises.mkdir(t,{recursive:!0});for(let n of N){let r=F.join(e,n),o=F.join(t,n);await R.promises.copyFile(r,o)}}import*as Gt from"fs";import*as Dr from"yauzl";function Xt(){let t=v();return t!==null&&Gt.existsSync(t)}import*as y from"fs";import*as P from"path";import an from"adm-zip";import*as ot from"fs";import*as gt from"path";var pt=class extends Error{constructor(e){super(`Unsafe documentation path: ${e}`),this.name="DocPathSafetyError"}};function Qt(t){return t instanceof k||t instanceof pt||t instanceof Error&&(t.name==="CliDataDirError"||t.name==="DocPathSafetyError")}function Jt(t){return new pt(t)}function Ir(){return U(K())}function qt(t,e,n){let r=We(t,e);if(r===null)throw Jt(`${n} resolves outside the data directory.`);return r}async function Wt(t,e){await ot.promises.mkdir(t,{recursive:!0});let n=qt(t,e,"directory");if(!(await ot.promises.stat(n)).isDirectory())throw Jt("path must be a directory.")}function it(t){let e=Ir();try{let n=qt(t,e,"file");if(!ot.statSync(n).isFile())throw Jt("path must be a regular file.")}catch(n){if(n.code==="ENOENT"){qt(gt.dirname(t),e,"file parent");return}throw n}}async function st(t={}){let e=t.mode??"write",n=await Ye();await Wt(Z(),n),await Wt(g(),n),e==="write"&&await Wt(C(),n);for(let r of[G(),$(),et(),ft(),rt(),nt(),...N.map(o=>gt.join(g(),o))])it(r)}var Yt=["search.db","build-meta.json",...N],Tr=["corpus.json","corpus-offsets.json","orama.dpack"];async function Cr(t){for(let e of Tr)await y.promises.rm(P.join(t,e),{force:!0})}async function Rr(t){let e=await y.promises.readdir(t,{withFileTypes:!0});for(let n of e)n.name!==".index"&&await y.promises.rm(P.join(t,n.name),{recursive:!0,force:!0})}function cn(t){let n=new an(t).getEntry("build-meta.json");if(!n)throw new Error("index.zip is missing build-meta.json");return JSON.parse(n.getData().toString("utf-8"))}async function Nr(t){let e=g();await y.promises.mkdir(e,{recursive:!0});for(let n of Yt){let r=P.join(e,n);await y.promises.rm(r,{force:!0}),await y.promises.rename(P.join(t,n),r)}await Cr(e),await y.promises.rm(C(),{recursive:!0,force:!0})}function un(t){let e=jt();if(!e)return!1;try{let n=cn(e);return n.indexVersion===H&&n.docsZipSha256===t&&n.segmentCount>0}catch{return!1}}async function ln(t){await st({mode:"write"});let e=jt();if(!e)throw new Error("index.zip not found");let n=cn(e);if(n.docsZipSha256!==t)throw new Error("Bundled index.zip does not match docs.zip. Rebuild index.zip with npm run build:index.");if(n.segmentCount<=0)throw new Error("Bundled index.zip is empty");let r=C();await y.promises.rm(r,{recursive:!0,force:!0}),await y.promises.mkdir(r,{recursive:!0});let o=new an(e);for(let s of Yt){let a=o.getEntry(s);if(!a)throw new Error(`index.zip is missing ${s}`);await y.promises.writeFile(P.join(r,s),a.getData())}let i=JSON.parse(await y.promises.readFile(P.join(r,"build-meta.json"),"utf-8"));if(!y.existsSync(P.join(r,"search.db")))throw new Error("index.zip is missing search.db");return await Nr(r),await y.promises.mkdir(Z(),{recursive:!0}),await Rr(Z()),i}async function dn(){await y.promises.rm(C(),{recursive:!0,force:!0});let t=g();for(let e of Yt)await y.promises.rm(P.join(t,e),{force:!0})}import{createHash as mn}from"crypto";import*as fn from"fs";async function ht(t){return new Promise((e,n)=>{let r=mn("sha256"),o=fn.createReadStream(t);o.on("data",i=>r.update(i)),o.on("error",n),o.on("end",()=>e(r.digest("hex")))})}function pn(t){return mn("sha256").update(t,"utf8").digest("hex")}function gn(t,e){let n=e?on(t,e):X(t);return pn(n)}function St(t){return gn("harmonyos-synonyms.json",t)}function yt(t){return gn("harmonyos-terms.txt",t)}var Pr={state:"idle",phase:0,phaseLabel:"Idle",current:0,total:0,message:"",startedAt:0,updatedAt:0,error:null};async function hn(){try{let t=await A.promises.readFile(et(),"utf-8");return JSON.parse(t)}catch{return{...Pr}}}async function Vt(t){let e=et();await A.promises.mkdir(at.dirname(e),{recursive:!0}),await A.promises.writeFile(e,JSON.stringify(t,null,2))}function Sn(t){let e=Date.now();return{state:"extracting",phase:1,phaseLabel:"Extracting documentation",current:0,total:0,message:t,startedAt:e,updatedAt:e,error:null}}async function B(t){let n={...await hn(),...t,updatedAt:Date.now()};return await Vt(n),n}async function Kt(){let t=v();return t?ht(t):null}async function te(){try{let t=await A.promises.readFile($(),"utf-8");return JSON.parse(t)}catch{return null}}async function ee(t=!1){if(t)return"no-index";let e=await te();if(!e||e.segmentCount===0)return"no-index";let n=await Kt();return n&&e.docsZipSha256!==n?"docs-changed":e.indexVersion!==H?"engine-upgraded":e.termsHash!==yt()?"terms-changed":e.synonymsHash!==St()?"synonyms-changed":null}function ne(){if(!Xt()||!A.existsSync(G())||!A.existsSync($()))return!1;let t=at.dirname(G());if(!N.every(e=>A.existsSync(at.join(t,e))))return!1;try{let e=A.readFileSync($(),"utf-8");return JSON.parse(e).segmentCount>0}catch{return!1}}async function yn(t=!1){return t?!0:Xt()?ne()?await ee()!==null:!0:!1}import*as x from"fs";import*as mr from"os";import*as _ from"path";var xn=new Set(["picker","dialog","sheet","panel","popup","menu","layout","view","gesture","animation","transition","recognizer","manager","kit"]);var En=new Set(["a","an","and","api","app","application","arkts","arkui","for","get","harmonyos","how","in","oh","ohos","on","or","set","the","to","use","using","what","when","where","which","with","without","data","file","main","model","name","network","stage","system","type","user"]),_n=new Set(["ability","extension","module","service","context","options","config","info","event","code","state","type","data","request","response","client","server","handler","helper","utils","factory","builder","listener","callback","observer","provider","consumer","delegate","adapter","driver","buffer","stream","channel","session","task","worker","controller","component","container","attribute","descriptor","modifier","validator","parser","formatter","encoder","decoder","filter","converter","generator","iterator","dispatcher","resolver","scanner","tracker","monitor","scheduler","renderer","loader","subscriber","proxy","button","surface","stack","heap","map","set","array","list"]);var Or=/@ohos\.[a-z][a-zA-Z0-9.]+/gi,Lr=/\b[a-z][a-z0-9]*[A-Z][a-zA-Z0-9]+\b/g,Br=/[A-Z][a-zA-Z0-9]{2,}/g,Mr=/@[A-Z][a-zA-Z0-9]*/g,kr=/[a-z][a-zA-Z0-9]*\.[a-zA-Z][a-zA-Z0-9]+/g,bn=6,vr=/^[a-z][a-z0-9]{2,}$/,Fr=/^([a-z][a-z0-9]{2,})\s+([a-z][a-z0-9]{2,})$/,zr=/^@ohos\.[a-z][a-zA-Z0-9.]+$/i,Hr=/^[a-z][a-z0-9]*[A-Z][a-zA-Z0-9]+$/,jr=/^[A-Z][a-zA-Z0-9]+$/;function re(t){return zr.test(t)}function Ur(t){return Hr.test(t)&&t.length>=bn}function Zr(t){return jr.test(t)}function oe(t){return re(t)||Ur(t)||Zr(t)}function $r(t){let e=t.trim().toLowerCase();return _n.has(e)?!1:xn.has(e)}function Gr(t,e){let n=e.trim().charAt(0).toUpperCase(),r=e.trim().slice(1).toLowerCase();return`${t.trim().toLowerCase()}${n}${r}`}function xt(t){let n=t.replace(/^@ohos\./i,"").split(".").filter(Boolean);return n[n.length-1]?.trim()||void 0}function ie(t){return[...t.matchAll(Or)].map(e=>e[0])}function se(t,e=bn){let n=[];for(let r of t.matchAll(Lr))r[0].length>=e&&n.push(r[0]);return n}function W(t){return t.filter(e=>{let n=e.toLowerCase();return!t.some(r=>{if(r===e)return!1;let o=r.toLowerCase();return o.length>n.length&&o.endsWith(n)&&n.length>=4})})}function D(t,e){let n=e.trim();if(!n)return;t.add(n);let r=n.toLowerCase();r!==n&&t.add(r)}function Xr(t){let e=new Set;D(e,t);let n=xt(t);return n&&D(e,n),W([...e])}function ae(t){if(re(t))return Xr(t);let e=new Set;return D(e,t),W([...e])}function ce(t){let e=t.trim();if(/[A-Z]/.test(e))return null;let n=e.match(Fr);if(!n)return null;let r=n[1].toLowerCase(),o=n[2].toLowerCase();if(!vr.test(r)||En.has(r)||!$r(o))return null;let i=Gr(r,o);return{first:r,second:o,camelCase:i,lower:i.toLowerCase()}}function wn(t){let e=ce(t.trim());return!e||e.second!=="manager"?null:e}function ue(t,e,n){let r=n.toLowerCase(),o=new RegExp(`@ohos\\.[^\\s(]*${n}`,"i");for(let i of[t,e])if(i&&(i.toLowerCase().includes(r)||o.test(i)))return!0;return!1}function An(t){let e=t.trim();if(oe(e))return ae(e);let n=new Set;for(let r of ie(t)){D(n,r);let o=xt(r);o&&D(n,o)}for(let r of se(t))D(n,r);for(let r of t.matchAll(Mr))n.add(r[0]);for(let r of t.matchAll(kr))n.add(r[0]);for(let r of t.matchAll(Br))r[0].length>=4&&n.add(r[0]);return W([...n])}function Dn(t){let e=t.trim();if(oe(e))return ae(e);let n=new Set,r=ce(e);r&&D(n,r.camelCase);for(let o of An(e))n.add(o);for(let o of e.matchAll(/\b[a-z][a-zA-Z0-9]{3,}\b/g)){let i=o[0];i!==i.toLowerCase()&&n.add(i)}return W([...n])}var I={pureApiSymbol:/^[A-Z][a-zA-Z0-9]+$/,stageModelExact:/^Stage\s*模型$/i,stageModelEnglishExact:/^stage\s+model$/i,stageModel:/Stage\s*模型/i,stageModelEntryPage:/Stage\s*模型.*EntryAbility.*(页面|新页面)/,declarePermissionBoost:/声明.*权限|应用权限.*声明|如何声明应用权限/,declarePermissionCatalog:/如何声明应用权限/,declarePermissionTokens:/如何声明应用权限|声明应用权限/,uiAbilityLifecycleBoost:/UIAbility.*生命周期|生命周期.*UIAbility|UIAblity/i,uiAbilityLifecycleCatalog:/UIAblity.*生命周期|UIAbility.*生命周期/i,entryAbilityPage:/EntryAbility.*(页面|启动|跳转|新页面)/,stateDecoratorBoost:/@State|@Prop|@Link|@Provide|@Consume/,stateDecoratorCatalog:/@State\s*装饰器|@Prop\s*装饰器|@Link\s*装饰器/,stateManagement:/状态管理原理/,routerRoute:/Router\s+路由/,dialogPopupExact:/^Dialog\s+弹窗$/,dialogPopupBoost:/Dialog\s+弹窗/};function Tn(t){return I.pureApiSymbol.test(t.trim())}function In(t){let e=t.trim();return I.stageModelExact.test(e)||I.stageModelEnglishExact.test(e)}var Wr=[{matches:t=>I.uiAbilityLifecycleBoost.test(t),weights:[{catalog:"harmonyos-guides",multiplier:1.85},{catalog:"harmonyos-references",multiplier:.65},{catalog:"harmonyos-faqs",multiplier:.82}]},{matches:t=>In(t),weights:[{catalog:"harmonyos-guides",multiplier:1.85},{catalog:"harmonyos-references",multiplier:.55},{catalog:"harmonyos-faqs",multiplier:.85}]},{matches:t=>!In(t)&&I.stageModel.test(t),weights:[{catalog:"harmonyos-guides",multiplier:1.65},{catalog:"harmonyos-references",multiplier:.65}]},{matches:t=>I.entryAbilityPage.test(t),weights:[{catalog:"harmonyos-guides",multiplier:1.75},{catalog:"harmonyos-references",multiplier:.48}]},{matches:t=>I.declarePermissionBoost.test(t),weights:[{catalog:"harmonyos-guides",multiplier:1.65},{catalog:"best-practices",multiplier:.68}]},{matches:t=>I.stateDecoratorBoost.test(t),weights:[{catalog:"harmonyos-guides",multiplier:1.75},{catalog:"harmonyos-references",multiplier:.42}]},{matches:t=>I.stateManagement.test(t),weights:[{catalog:"harmonyos-guides",multiplier:1.6},{catalog:"best-practices",multiplier:.78}]},{matches:t=>I.routerRoute.test(t),weights:[{catalog:"harmonyos-guides",multiplier:1.65},{catalog:"harmonyos-references",multiplier:1.4},{catalog:"harmonyos-faqs",multiplier:.72},{catalog:"best-practices",multiplier:.72}]},{matches:t=>I.dialogPopupBoost.test(t),weights:[{catalog:"harmonyos-guides",multiplier:1.65},{catalog:"harmonyos-faqs",multiplier:.72},{catalog:"best-practices",multiplier:.72}]}];function qr(t,e){for(let{catalog:n,multiplier:r}of e){let o=O[n];t.set(o,(t.get(o)??1)*r)}}function Cn(t,e){for(let n of Wr)n.matches(t)&&qr(e,n.weights)}import*as Rn from"os";function le(){return Qr().toLowerCase().includes("openharmony")}function Qr(){return Rn.platform()}import*as q from"fs";import*as Pn from"path";function z(t){process.env.DEVECO_CLI_DEBUG&&process.stderr.write(`[DEBUG] ${t}
|
|
2
|
+
`)}var Et=null,de=null,me=null;function Jr(){return q.existsSync(rt())}function Yr(t){let e=rt(),n={backend:"jieba-wasm",reason:"native-jieba-load-failed",message:t,createdAt:new Date().toISOString()};q.mkdirSync(Pn.dirname(e),{recursive:!0}),it(e),q.writeFileSync(e,JSON.stringify(n,null,2))}function Vr(){if(Et)return Et;let t=X("harmonyos-stopwords.txt");return Et=new Set(t.split(`
|
|
3
|
+
`).map(e=>e.trim()).filter(Boolean)),Et}function Kr(t){let e=[];for(let n=0;n<t.length;n++){let r=t[n]?.trim();if(!r)continue;let o=t[n+1]?.trim();if(r==="@"&&o&&/^[A-Z][a-zA-Z0-9]*$/.test(o)){e.push(`@${o}`),n+=1;continue}e.push(r)}return e}function to(t){let e=Vr(),n=[];for(let r of Kr(t)){let o=r.trim();!o||e.has(o)||(n.push(o.toLowerCase()),/[A-Z]/.test(o)&&/[a-zA-Z]/.test(o)&&n.push(o))}return n}async function On(t){let{dict:e}=await import("@node-rs/jieba/dict.js"),n=t.withDict(e),r=X("harmonyos-terms.txt");return n.loadDict(Buffer.from(r,"utf-8")),n}async function eo(){let{Jieba:t}=await import("@node-rs/jieba");return On(t)}async function Nn(){let{Jieba:t}=await import("@node-rs/jieba-wasm32-wasi");return On(t)}async function no(){let t=await import("jieba-wasm"),e=X("harmonyos-terms.txt");return t.with_dict(e),{cut:t.cut,cutForSearch:t.cut_for_search}}async function ro(){if(le())return no();if(Jr())return Nn();try{let e=await eo();return z("doc-index: using @node-rs/jieba backend"),e}catch(e){let n=e instanceof Error?e.message:String(e);Yr(n),z(`doc-index: @node-rs/jieba unavailable (${n}); falling back to wasm32-wasi`)}let t=await Nn();return z("doc-index: using @node-rs/jieba-wasm32-wasi backend"),t}async function Q(){return de||(me||(me=ro().then(t=>(de=t,t))),me)}async function oo(t){let e=await Q();return to(e.cutForSearch(t,!0))}async function _t(t,e){let n=t.trim();if(!n||e<=0)return"";let r=(await oo(n)).join(" ");return r.length<=e?r:r.slice(0,e)}async function io(t,e){let n=[];for(let o of t){let i=o.trim();i&&(n.push(i.toLowerCase()),/[A-Z]/.test(i)&&n.push(i))}let r=[...new Set(n)].join(" ");return r.length<=e?r:r.slice(0,e)}async function bt(t){let e=!!t.sectionTitle.trim(),n=t.titleTokens.trim(),r=e?ke:Pe,o=e?Fe:Le,i=e?await io(t.apiSymbols,o):await _t(t.apiSymbols.join(" "),o),a=(await Promise.all([_t(n,e?ve:Oe),Promise.resolve(i),_t(t.headingsText,e?ze:Be),_t(t.bodySample,e?He:Me)])).filter(Boolean).join(" ");return a.length<=r?a:a.slice(0,r)}var Ln=["harmonyos-releases","harmonyos-roadmap"],so=new Set(Ln.map(t=>O[t])),ja=Ln.map(t=>`${dt[t]}/`);function ao(t){return so.has(t)}function Bn(t){let e=[],n=[];for(let r of t)ao(r.catalog_id)?n.push(r):e.push(r);return[...e,...n]}var co=[{pattern:/@ohos\./i,catalog:"harmonyos-references",multiplier:1.5},{pattern:/@[A-Z][a-zA-Z]+/,catalog:"harmonyos-guides",multiplier:1.35},{pattern:/(如何|怎么|怎样|步骤)/,catalog:"harmonyos-guides",multiplier:1.45},{pattern:/(生命周期|原理|概述|什么是|模型|介绍)/,catalog:"harmonyos-guides",multiplier:1.35},{pattern:/(报错|失败|错误|异常|排查)/,catalog:"harmonyos-guides",multiplier:1.25},{pattern:/(报错|失败|FAQ)/i,catalog:"harmonyos-faqs",multiplier:1.2},{pattern:/(构建|签名|打包|发布|上架|应用市场|hvigor|ohpm)/i,catalog:"harmonyos-guides",multiplier:1.3},{pattern:/(行为变更|changelog|升级|适配|版本说明)/i,catalog:"harmonyos-releases",multiplier:1.3},{pattern:/(路由|弹窗|手势|页面|权限|装饰器)/,catalog:"harmonyos-guides",multiplier:1.25,skipForPureApiSymbol:!0}];function ct(t,e,n){let r=O[e];t.set(r,(t.get(r)??1)*n)}function uo(t,e){let n=t.trim(),r=/[\u4e00-\u9fff]/.test(n),o=/\b[A-Z][a-zA-Z0-9]{2,}\b/.test(n),i=/\b[a-z][a-zA-Z0-9]{3,}\b/.test(n);if(r&&(o||i)){ct(e,"harmonyos-guides",1.45),ct(e,"harmonyos-references",1.35);return}(o||i)&&ct(e,"harmonyos-references",1.55),/\b[A-Z][a-zA-Z]*(Gesture|Dialog|Sheet|Transition|Recognizer)\b/.test(n)&&ct(e,"harmonyos-references",1.75)}function Mn(t){let e=new Map,n=t.trim();if(!n)return e;let r=Tn(n);uo(n,e),Cn(n,e);for(let o of co)o.pattern.test(n)&&(o.skipForPureApiSymbol&&r||ct(e,o.catalog,o.multiplier));return e}import*as Y from"fs";import*as Zn from"path";var lo=[" ","\u3002","\uFF0C","\uFF1B","\u3001",".","!","?"];function kn(t,e){let n=-1;for(let r of lo){let o=t.lastIndexOf(r);o>n&&(n=o)}return n>=e?n:-1}function vn(t,e){let n=t.trim();if(n.length<=e)return{text:n,excerptTruncated:!1};let r=n.slice(0,e),o=kn(r,e-20),i=o>=0?o:e;return{text:n.slice(0,i).trimEnd(),excerptTruncated:!0}}function Fn(t,e,n={}){let{maxLen:r=Ze,contextChars:o=$e,excerptTruncated:i=!1}=n,s=t.replace(/\s+/g," ").trim();if(!s)return"";if(s.length<=r)return i?`${s}...`:s;let a=e.split(/\s+/).map(Lt=>Lt.trim()).filter(Boolean),c=0;for(let Lt of a){let we=s.toLowerCase().indexOf(Lt.toLowerCase());if(we>=0){c=we;break}}let f=Math.max(0,c-o),p=Math.min(s.length,f+r),d=s.slice(f,p),b=kn(d,r-25);b>=0&&(p=f+b);let S=s.slice(f,p).trim(),w=f>0?"...":"",yr=p<s.length||i?"...":"";return`${w}${S}${yr}`}var mo=`
|
|
4
|
+
SELECT d.document_id, d.doc_title, s.section_title, s.lead_text, s.excerpt_truncated,
|
|
5
|
+
d.catalog_id, bm25(segments_fts) AS bm25
|
|
6
|
+
FROM segments_fts
|
|
7
|
+
JOIN segments s ON s.id = segments_fts.rowid
|
|
8
|
+
JOIN documents d ON d.id = s.doc_id
|
|
9
|
+
WHERE segments_fts MATCH ?
|
|
10
|
+
ORDER BY bm25(segments_fts)
|
|
11
|
+
LIMIT ?
|
|
12
|
+
`,fo=`
|
|
13
|
+
SELECT d.document_id, d.doc_title, s.section_title, s.lead_text, s.excerpt_truncated,
|
|
14
|
+
d.catalog_id, bm25(segments_fts) AS bm25
|
|
15
|
+
FROM segments_fts
|
|
16
|
+
JOIN segments s ON s.id = segments_fts.rowid
|
|
17
|
+
JOIN documents d ON d.id = s.doc_id
|
|
18
|
+
WHERE segments_fts MATCH ? AND d.catalog_id = ?
|
|
19
|
+
ORDER BY bm25(segments_fts)
|
|
20
|
+
LIMIT ?
|
|
21
|
+
`,po=3.5,go=1.4,ho=4,So=1.8,yo=1.35,xo=3.5,Eo=1.8,_o=120,zn=6;function pe(t){return t.toLowerCase().replace(/[^\p{L}\p{N}@.]+/gu,"")}function bo(t){return t.split(/[^\p{L}\p{N}@.]+/u).map(pe).filter(e=>e.length>=2)}function wo(t,e){return e.length>1&&e.every(n=>t.includes(n))}function Ao(t){return/^[a-z0-9]{1,4}$/.test(t.trim().toLowerCase())}function Do(t,e){return t===e?xo:t.startsWith(e)||t.includes(`@ohos.${e}`)?Eo:1}function Io(t,e){let n=pe(e);if(n.length<2)return 1;let r=pe(t.doc_title);if(Ao(e))return Do(r,n);if(r.includes(n))return ho;if(n.length>=zn&&r.includes(n.slice(0,zn)))return So;let o=bo(e);return wo(r,o)?yo:1}function To(t,e){return e<=1?t:t<0?t*e:t/e}function wt(t,e,n,r){let o=t.bm25/(e.get(t.catalog_id)??1);return o=To(o,Io(t,n)),r&&ue(t.doc_title,t.section_title,r)&&(o/=po,t.catalog_id===O["harmonyos-references"]&&(o/=go)),o}function fe(t,e,n,r){return t.reduce((o,i)=>wt(i,e,n,r)<wt(o,e,n,r)?i:o)}function Co(t,e){return e.some(n=>t.section_title.includes(n)||t.doc_title.includes(n))}function Ro(t,e,n,r,o){if(o){let i=t.filter(s=>ue(s.doc_title,s.section_title,o));if(i.length>0)return fe(i,n,r,o)}if(e.length>0){let i=t.filter(s=>Co(s,e));if(i.length>0)return fe(i,n,r,o)}return fe(t,n,r,o)}function Hn(t,e,n,r,o){let i=Mn(e),s=Dn(e),c=wn(e)?.camelCase,f=new Map;for(let S of t){let w=f.get(S.document_id)??[];w.push(S),f.set(S.document_id,w)}let p=[];for(let S of f.values())p.push(Ro(S,s,i,n,c));let d=p.sort((S,w)=>wt(S,i,n,c)-wt(w,i,n,c));return(o?Bn(d):d).slice(0,r)}function At(t,e,n,r,o,i){let s=e?O[e]:void 0,a=Math.max(n,n*Ne,_o),c=s===void 0?t.all(mo,r,a):t.all(fo,r,s,a);return(s===void 0?Hn(c,i,o,n,!0):Hn(c,i,o,n,!1)).map(p=>({title:p.doc_title,documentId:p.document_id,sectionTitle:p.section_title||void 0,snippet:Fn(p.lead_text,o,{excerptTruncated:!!p.excerpt_truncated})}))}var Dt=`
|
|
22
|
+
CREATE TABLE documents (
|
|
23
|
+
id INTEGER PRIMARY KEY,
|
|
24
|
+
document_id TEXT NOT NULL UNIQUE,
|
|
25
|
+
catalog_id INTEGER NOT NULL,
|
|
26
|
+
doc_title TEXT NOT NULL
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
CREATE TABLE segments (
|
|
30
|
+
id INTEGER PRIMARY KEY,
|
|
31
|
+
doc_id INTEGER NOT NULL REFERENCES documents(id),
|
|
32
|
+
section_title TEXT NOT NULL DEFAULT '',
|
|
33
|
+
lead_text TEXT NOT NULL DEFAULT '',
|
|
34
|
+
search_text TEXT NOT NULL,
|
|
35
|
+
excerpt_truncated INTEGER NOT NULL DEFAULT 0
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
CREATE VIRTUAL TABLE segments_fts USING fts5(
|
|
39
|
+
search_text,
|
|
40
|
+
content='segments',
|
|
41
|
+
content_rowid='id',
|
|
42
|
+
tokenize='unicode61'
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
CREATE TRIGGER segments_ai AFTER INSERT ON segments BEGIN
|
|
46
|
+
INSERT INTO segments_fts(rowid, search_text) VALUES (new.id, new.search_text);
|
|
47
|
+
END;
|
|
48
|
+
|
|
49
|
+
CREATE TRIGGER segments_ad AFTER DELETE ON segments BEGIN
|
|
50
|
+
INSERT INTO segments_fts(segments_fts, rowid, search_text) VALUES('delete', old.id, old.search_text);
|
|
51
|
+
END;
|
|
52
|
+
|
|
53
|
+
CREATE TRIGGER segments_au AFTER UPDATE ON segments BEGIN
|
|
54
|
+
INSERT INTO segments_fts(segments_fts, rowid, search_text) VALUES('delete', old.id, old.search_text);
|
|
55
|
+
INSERT INTO segments_fts(rowid, search_text) VALUES (new.id, new.search_text);
|
|
56
|
+
END;
|
|
57
|
+
|
|
58
|
+
CREATE INDEX segments_doc_id_idx ON segments(doc_id);
|
|
59
|
+
`;var J=null,ge=null;function No(){J?.close(),J=null,ge=null}function Po(t,e){if(J&&ge===e)return J;J?.close();let n=new t(e,{readonly:!0,fileMustExist:!0});return J=n,ge=e,n.pragma("mmap_size = 268435456"),n.pragma("cache_size = -8000"),n.pragma("query_only = ON"),n}function Oo(t,e){let n=new t(e);return n.pragma("journal_mode = OFF"),n.pragma("synchronous = OFF"),n.pragma("temp_store = MEMORY"),n.exec(Dt),n}function Lo(t,e,n){let r=e.get(n.documentId);if(r!==void 0)return r;let i=t.prepare("SELECT id FROM documents WHERE document_id = ?").get(n.documentId);if(i)return e.set(n.documentId,i.id),i.id;let a=t.prepare(`
|
|
60
|
+
INSERT INTO documents(document_id, catalog_id, doc_title)
|
|
61
|
+
VALUES (?, ?, ?)
|
|
62
|
+
`).run(n.documentId,n.catalogId,n.docTitle),c=Number(a.lastInsertRowid);return e.set(n.documentId,c),c}async function Bo(t,e,n,r){await Q();let o=Oo(t,e),i=new Map,s=o.prepare(`
|
|
63
|
+
INSERT INTO segments(doc_id, section_title, lead_text, search_text, excerpt_truncated)
|
|
64
|
+
VALUES (?, ?, ?, ?, ?)
|
|
65
|
+
`),a=n.length;for(let c=0;c<a;c+=j){let f=n.slice(c,c+j),p=await Promise.all(f.map(async b=>({source:b,searchText:await bt(b)})));o.transaction(b=>{for(let S of b){let w=Lo(o,i,S.source);s.run(w,S.source.sectionTitle,S.source.leadText,S.searchText,S.source.excerptTruncated?1:0)}})(p),await r?.(Math.min(c+f.length,a),a)}o.exec("ANALYZE"),o.exec("VACUUM"),o.close()}function Mo(t,e,n,r,o,i,s){let a=Po(t,e);return At({all(c,...f){return a.prepare(c).all(...f)}},n,r,o,i,s)}async function jn(){let e=(await import("better-sqlite3")).default;return{kind:"better-sqlite3",resetCache:No,buildSearchIndex:(n,r,o)=>Bo(e,n,r,o),searchIndex:(n,r,o,i,s,a,c)=>Promise.resolve(Mo(e,i,r,o,s,a,c))}}import{readFile as ko,stat as vo,writeFile as Fo}from"fs/promises";var he=null,M=null;async function Se(){return he||(he=(async()=>{let t=(await import("@sqlite.org/sqlite-wasm")).default;return t()})()),he}function zo(t){return{all(e,...n){let r=t.prepare(e);n.length>0&&r.bind(n);let o=[];for(;r.step();)o.push(r.get({}));return r.finalize(),o}}}async function Ho(t){let e=await vo(t);if(M&&M.dbPath===t&&M.mtimeMs===e.mtimeMs)return M.db;M?.db.close();let n=await Se(),r=n.capi,o=n.wasm,i=new Uint8Array(await ko(t)),s=o.allocFromTypedArray(i),a=new n.oo1.DB(":memory:"),c=a.pointer;if(c===void 0)throw new Error("sqlite3_deserialize: database pointer is undefined");let f=r.SQLITE_DESERIALIZE_READONLY|r.SQLITE_DESERIALIZE_RESIZEABLE|r.SQLITE_DESERIALIZE_FREEONCLOSE;return r.sqlite3_deserialize(c,"main",s,i.byteLength,i.byteLength,f),M={dbPath:t,mtimeMs:e.mtimeMs,db:a},a}function Un(){M?.db.close(),M=null}async function jo(t,e,n,r){t.exec("BEGIN");for(let o of r){let i=n(o.source);e.bind([i,o.source.sectionTitle,o.source.leadText,o.searchText,o.source.excerptTruncated?1:0]),e.step(),e.reset()}t.exec("COMMIT")}function Uo(t,e,n){return r=>{let o=e.get(r.documentId);if(o!==void 0)return o;let i=t.selectValue("SELECT id FROM documents WHERE document_id = ?",[r.documentId]);if(i!=null){let a=Number(i);return e.set(r.documentId,a),a}n.bind([r.documentId,r.catalogId,r.docTitle]),n.step(),n.reset();let s=Number(t.selectValue("SELECT last_insert_rowid()"));return e.set(r.documentId,s),s}}async function Zo(t,e,n){await Q();let r=await Se(),o=new r.oo1.DB(":memory:","c");o.exec(Dt);let i=new Map,s=o.prepare("INSERT INTO documents(document_id, catalog_id, doc_title) VALUES (?, ?, ?)"),a=o.prepare("INSERT INTO segments(doc_id, section_title, lead_text, search_text, excerpt_truncated) VALUES (?, ?, ?, ?, ?)"),c=Uo(o,i,s),f=e.length;for(let d=0;d<f;d+=j){let b=e.slice(d,d+j),S=await Promise.all(b.map(async w=>({source:w,searchText:await bt(w)})));await jo(o,a,c,S),await n?.(Math.min(d+b.length,f),f)}o.exec("ANALYZE");let p=r.capi.sqlite3_js_db_export(o);await Fo(t,p),o.close(),Un()}async function $o(t,e,n,r,o,i){let s=await Ho(t);return At(zo(s),e,n,r,o,i)}async function ye(){return await Se(),{kind:"sqlite-wasm",resetCache:Un,buildSearchIndex:Zo,searchIndex:(t,e,n,r,o,i,s)=>$o(r,e,n,o,i,s)}}var It=null,xe=null;function Go(){return Y.existsSync(nt())}function Xo(t){let e=nt(),n={backend:"sqlite-wasm",reason:"better-sqlite3-load-failed",message:t,createdAt:new Date().toISOString()};Y.mkdirSync(Zn.dirname(e),{recursive:!0}),it(e),Y.writeFileSync(e,JSON.stringify(n,null,2))}async function Wo(){if(Go())return ye();try{let t=await jn();return z("doc-index: using better-sqlite3 SQLite backend"),t}catch(t){let e=t instanceof Error?t.message:String(t);Xo(e),z(`doc-index: better-sqlite3 unavailable (${e}); falling back to sqlite-wasm`)}return ye()}async function Ee(){return It||(It=Wo().then(t=>(xe=t,t))),It}function $n(){xe?.resetCache(),It=null,xe=null}function Tt(){$n()}async function Gn(t,e,n){await(await Ee()).buildSearchIndex(t,e,n)}import{unified as Kn}from"unified";import tr from"remark-parse";import er from"remark-gfm";import{toString as Rt}from"mdast-util-to-string";var qo=/^(.+?)(\d+\+)?(对象|枚举|错误码)说明$/,Qo=/^\[h2\]([A-Za-z][A-Za-z0-9]*)(\d+\+)?$/,Jo=/^(.{2,20}?)\s*[((]([A-Za-z][a-zA-Z0-9]{1,40})[))]\s*$/,Yo=/^([A-Za-z@][A-Za-z0-9@]*?)(\d+\+)?$/,Vo=/^(系统能力|元服务API|参数|返回值|说明|\*\*|表格|\|)/;function Ct(t){let e=t.trim(),n=e.match(Yo);return n?n[1]:e}function Ko(t){let e=t.match(qo);if(!e)return;let n=Ct(e[1].trim());return{displayTitle:t,symbolName:n,searchExtras:[n,e[3]]}}function ti(t){let e=Ct(t.replace(/\([^)]*\)$/,""));if(/^[A-Z][A-Za-z0-9]*$/.test(e))return{displayTitle:t,symbolName:e,searchExtras:[e]};if(/^[A-Z][A-Za-z0-9]*(\([^)]*\))?$/.test(t))return{displayTitle:t,symbolName:e,searchExtras:[e]}}function ut(t){let e=t.trim();return e?Ko(e)??(()=>{let n=e.match(Qo);if(n){let r=n[1];return{displayTitle:e,symbolName:r,searchExtras:[r]}}})()??(()=>{let n=e.match(Jo);if(!n)return;let r=n[1].trim(),o=n[2].trim();return{displayTitle:e,symbolName:o,searchExtras:[r,o]}})()??ti(e)??{displayTitle:e,searchExtras:[]}:{displayTitle:"",searchExtras:[]}}function ei(t){if(t.length<2||t.length>36||Vo.test(t))return!1;let e=[...t.replace(/\s/g,"")];return e.length===0?!1:e.filter(r=>new RegExp("\\p{Script=Han}","u").test(r)).length/e.length>=.4}function Xn(t){for(let e of t){let n=e.trim().replace(/[。.!!??;;]+$/u,"").trim();if(ei(n))return n}return""}function Wn(t,e,n){let r=[t,...n.searchExtras,e].filter(Boolean);return[...new Set(r)].join(" ")}var ni=/[A-Z][a-zA-Z0-9]+(?:\.[a-zA-Z][a-zA-Z0-9]+)*/g,lt=/@[A-Z][a-zA-Z]+/g,ri=/^[A-Z][A-Za-z0-9]*\.[A-Za-z][A-Za-z0-9]+/,oi=/^[A-Z][A-Za-z0-9]+(?:\([^)]*\))?$/,ii=/^[a-z0-9]+(?:[-_][a-z0-9]+)+$/,si=new Set(["API","Action","Code","Connect","Connection","Context","Direction","Element","Elements","Entry","Focused","Module","Modules","Name","Names","Stage","Type","Types","Value","Values","Rect","Error"]),ai=new Set(["HAP","HSP","HAR","NAPI","CAPI","NDK","ArkTS","ArkUI","OHPM"]),ci=new Set(["JSON","Object","Array","Promise","console","Math","Date","String","Number","Boolean","Error","Function","Map","Set","RegExp"]);function nr(t,e){let n=new Set,r=[t,...e];for(let o of r){for(let i of ie(o)){D(n,i);let s=xt(i);s&&D(n,s)}for(let i of se(o))D(n,i);for(let i of o.matchAll(ni)){let s=i[0];ui(s)&&n.add(s)}for(let i of o.matchAll(lt))n.add(i[0])}return W([...n])}function ui(t){let e=t.trim();if(!e||lt.test(e))return!!e;if(e.includes(".")){let n=e.split(".")[0]??"";return ci.has(n)?!1:/^[A-Z]/.test(n)}return si.has(e)?!1:ai.has(e)?!0:e.length<=3?!1:/^[A-Z][a-z]+[A-Z]/.test(e)?!0:e.length>=6&&/^[A-Z][A-Za-z0-9]+$/.test(e)}function qn(t){let e=t.trim();return!!(!e||ii.test(e)||e.length>28&&!/[A-Z\u4e00-\u9fff]/.test(e)&&/^[a-z0-9_-]+$/.test(e))}function rr(t,e){let n=e.jsonTitle?.trim(),r=fi(t,"").trim(),o=e.fileName.trim();return n&&!qn(n)?n:r&&!qn(r)?r:n||r||o}function or(t){return ri.test(t.trim())}function _e(t){let e=t.trim().replace(/\([^)]*\)$/,""),n=Ct(e);return oi.test(n)}function Nt(t){let e=t.trim();return e?lt.test(e)||or(e)||_e(e)?!0:!!ut(e).symbolName:!1}function li(t){let e=t.trim();return!(!e||or(e)||_e(e))}function di(t){let e=new Set,n=[];for(let r of t){let o=r.trim();!li(o)||e.has(o)||(e.add(o),n.push(o))}return n}function Qn(t){if(!t.includes("."))return 0;let e=t.split(".").pop()??"";return/^[a-z]/.test(e)?1:2}function mi(t,e){let n=Qn(t)-Qn(e);return n!==0?n:t.localeCompare(e)}function ir(t,e=[]){let n=[...new Set(e.map(i=>i.trim()).filter(Boolean))],r=new Set(n),o=[...new Set(t.map(i=>i.trim()).filter(Boolean))].filter(i=>!r.has(i));return o.sort(mi),[...n,...o].slice(0,je)}function Pt(t){return t.replace(/\s+/g," ").trim()}function Jn(t){return t.replace(/\\([\\`*_{}[\]()#+.!-])/g,"$1")}function fi(t,e=""){let n=t.split(/\r?\n/),r=0;for(;r<n.length&&!n[r].trim();)r+=1;if(r>=n.length)return e;let o=Jn(n[r].trim()),i=o.match(/^#+\s+(.+)$/);if(i)return Jn(i[1].trim());if(r+1<n.length){let s=n[r+1].trim();if(/^=+$/.test(s)||/^-+$/.test(s))return o}return o||e}function sr(t){let e=Pt(t.join(" "));if(e.length<=mt)return e;let n=e.slice(0,mt);return e.length<=mt+kt?n:`${n} ${e.slice(-kt)}`}function pi(t){let e=di(t).join(" ");return e.length<=vt?e:e.slice(0,vt)}function ar(t){let e=Pt(t),{text:n,excerptTruncated:r}=vn(e,Ue);return{leadText:n,excerptTruncated:r}}function gi(t,e){let{leadText:n,excerptTruncated:r}=ar(t);return{leadText:n,excerptTruncated:r||!!e.trim()}}function cr(t,e){if(t.type==="code"){e.codeBlocks.push(t.value??"");return}if("children"in t&&Array.isArray(t.children)){for(let r of t.children)cr(r,e);return}let n=Pt(Rt(t));n&&e.bodyParts.push(n)}function hi(t){let e=Kn().use(tr).use(er).parse(t),n=[],r=null,o=()=>{r&&((r.sectionTitle||r.bodyParts.length||r.codeBlocks.length)&&n.push(r),r=null)},i=()=>{r||(r={sectionTitle:"",bodyParts:[],codeBlocks:[]})};for(let s of e.children){if(s.type==="heading"){let a=s,c=Rt(a).trim();if(a.depth>=4&&c&&Nt(c)){o(),r={sectionTitle:c,bodyParts:[],codeBlocks:[]};continue}i(),c&&r.bodyParts.push(c);continue}i(),cr(s,r)}return o(),n.length===0?[{sectionTitle:"",bodyParts:[],codeBlocks:[]}]:n}function Si(t){return Re.test(t)}function yi(t){return t.filter(e=>e.sectionTitle&&Nt(e.sectionTitle)).length}function xi(t){return{sectionTitle:t.map(e=>e.sectionTitle.trim()).join(" | "),bodyParts:t.flatMap(e=>e.bodyParts).slice(0,40),codeBlocks:t.flatMap(e=>e.codeBlocks).slice(0,8)}}function Yn(t){let e=t.trim();return!e||lt.test(e)?lt.test(e):/对象说明$|枚举说明$/.test(e)?!0:_e(e)}function Ei(t){let e=t.filter(d=>!d.sectionTitle||!Nt(d.sectionTitle)),n=t.filter(d=>d.sectionTitle&&Nt(d.sectionTitle)),r=n.filter(d=>Yn(d.sectionTitle)),o=n.filter(d=>!Yn(d.sectionTitle)),i=Math.max(0,Ce-r.length),s=o.slice(0,i),a=o.slice(i),c=a.filter(d=>Vn(d.sectionTitle)),f=a.filter(d=>!Vn(d.sectionTitle)),p=[];for(let d=0;d<f.length;d+=Mt)p.push(xi(f.slice(d,d+Mt)));return[...e,...r,...s,...c,...p]}function _i(t,e,n){let r=t.split(/\r?\n/).length,o=yi(e);return o===0?!1:Si(n)?r>=Ie&&o>=Te:r>=Ae&&o>=De}var bi=/^\[h2\][A-Za-z]/;function Vn(t){return bi.test(t.trim())}function ur(t){if(!t.includes(" | ")){let n=ut(t);return n.symbolName?[n.symbolName]:[]}let e=[];for(let n of t.split(" | ")){let r=ut(n.trim()).symbolName;r&&e.push(r)}return e}function wi(t,e,n,r){let o=ur(t),i=nr(n,r);return e.symbolName&&i.push(e.symbolName),ir([...o,...i],o)}function Ai(t,e){let n=sr(t.bodyParts),r=t.sectionTitle.trim(),o=ut(r),i=Xn(t.bodyParts),s=Wn(r,i,o),a=ur(r),c=r?a.length>0?`${e.docTitle} ${a.join(" ")}`:`${e.docTitle} ${o.symbolName??r}`:e.docTitle,f=[e.docTitle,s,...t.bodyParts].join(" "),{leadText:p,excerptTruncated:d}=gi(n,r);return{documentId:e.documentId,catalogId:e.catalogId,docTitle:e.docTitle,sectionTitle:r,titleTokens:c,headingsText:s,apiSymbols:wi(r,o,f,t.codeBlocks),bodySample:n,leadText:p,excerptTruncated:d}}function lr(t,e){for(let n of t){if(n.type==="heading"){let o=Rt(n).trim();o&&e.headings.push(o);continue}if(n.type==="code"){e.codeBlocks.push(n.value??"");continue}if("children"in n&&Array.isArray(n.children)){lr(n.children,e);continue}let r=Pt(Rt(n));r&&e.bodyParts.push(r)}}function Di(t){let e=Kn().use(tr).use(er).parse(t),n={headings:[],bodyParts:[],codeBlocks:[]};return lr(e.children,n),n}function Ii(t,e){let n=Di(t),r=e.docTitle?.trim()||e.documentId,o=sr(n.bodyParts),i=[r,...n.headings,o].join(" "),{leadText:s,excerptTruncated:a}=ar(o);return{documentId:e.documentId,catalogId:e.catalogId,docTitle:r,sectionTitle:"",titleTokens:r,headingsText:pi(n.headings),apiSymbols:ir(nr(i,n.codeBlocks)),bodySample:o,leadText:s,excerptTruncated:a}}function dr(t,e){let n=e.docTitle?.trim()||e.documentId,r=hi(t);return _i(t,r,e.documentId)?Ei(r).filter(o=>o.sectionTitle||o.bodyParts.length>0||o.codeBlocks.length>0).map(o=>Ai(o,{...e,docTitle:n})):[Ii(t,{...e,docTitle:n})]}async function Ti(t){let e=[];async function n(r){let o=await x.promises.readdir(r,{withFileTypes:!0});for(let i of o){if(i.name.startsWith("."))continue;let s=_.join(r,i.name);i.isDirectory()?await n(s):i.isFile()&&i.name.endsWith(".md")&&e.push(s)}}return await n(t),e}function Ci(t,e){let n=_.relative(e,t).split(_.sep).join("/").split("/");if(n[0]==="docs"&&(n=n.slice(1)),n.length<2)return null;let r=n[0],o=Ge[r];if(o===void 0)return null;let i=n[n.length-1].replace(/\.md$/,"");return n[n.length-1]=i,{documentId:n.join("/"),catalogId:o,docTitle:i}}async function Ri(t){let e=t.replace(/\.md$/,".json");try{let n=await x.promises.readFile(e,"utf-8");return JSON.parse(n).title?.trim()||void 0}catch{return}}async function Ni(t,e){let n=Ci(t,e);if(!n)return[];let r=await x.promises.readFile(t,"utf-8"),o=rr(r,{jsonTitle:await Ri(t),fileName:n.docTitle});return dr(r,{...n,docTitle:o})}async function Pi(t,e,n){let r=_.join(e,"search.db");return await Gn(r,t,async(o,i)=>{await n?.({current:o,total:i,message:`Building search index\u2026 ${o.toLocaleString()} / ${i.toLocaleString()} segments`})}),t.length}async function Oi(t){let e=await Ti(t),n=[];for(let r of e){let o=await Ni(r,t);n.push(...o)}return n}function Li(t,e){return{indexVersion:H,docsZipSha256:t.docsZipSha256,termsHash:t.termsHash,synonymsHash:t.synonymsHash,segmentCount:e,builtAt:Date.now(),builtBy:t.builtBy}}async function fr(t){t.lexiconDir&&$t(t.lexiconDir);try{let e=await Oi(t.docsDir);await t.onProgress?.({current:0,total:e.length,message:`Building search index\u2026 0 / ${e.length.toLocaleString()} segments`}),await x.promises.mkdir(t.tmpDir,{recursive:!0});let n=await Pi(e,t.tmpDir,t.onProgress),r=Li(t,n);return await x.promises.writeFile(_.join(t.tmpDir,"build-meta.json"),JSON.stringify(r,null,2)),await sn(t.tmpDir),r}finally{t.lexiconDir&&$t(null)}}async function pr(){return x.promises.mkdtemp(_.join(mr.tmpdir(),"deveco-docs-"))}async function Bi(t,e){try{await x.promises.rename(t,e)}catch(n){let r=n.code;if(r!=="EPERM"&&r!=="EXDEV")throw n;await x.promises.cp(t,e,{recursive:!0}),await x.promises.rm(t,{recursive:!0,force:!0})}}async function gr(t){let e=_.join(t,"docs");try{await x.promises.access(e)}catch{return}let n=new Set(["docs","docs.zip"]);for(let r of await x.promises.readdir(e,{withFileTypes:!0})){if(n.has(r.name))continue;let o=_.join(e,r.name),i=_.join(t,r.name);await x.promises.rm(i,{recursive:!0,force:!0}),await Bi(o,i)}await x.promises.rm(_.join(e,"docs"),{recursive:!0,force:!0}),await x.promises.rm(_.join(e,"docs.zip"),{force:!0}),await x.promises.rm(e,{recursive:!0,force:!0})}async function Sr(t){let e=Ht();await h.promises.mkdir(T.dirname(e),{recursive:!0}),await h.promises.appendFile(e,`${new Date().toISOString()} ${t}
|
|
66
|
+
`)}async function Fi(t){let e=v();if(!e)throw new Error("docs.zip not found");await h.promises.rm(t,{recursive:!0,force:!0}),await h.promises.mkdir(t,{recursive:!0});let n=T.resolve(t),r=new Mi(e);for(let o of r.getEntries()){let i=T.resolve(n,o.entryName);if(!V(i,n))throw new Error(`Unsafe docs.zip entry path: ${o.entryName}`);if(o.isDirectory){await h.promises.mkdir(i,{recursive:!0});continue}await h.promises.mkdir(T.dirname(i),{recursive:!0}),await h.promises.writeFile(i,o.getData())}await gr(t)}async function zi(){await st({mode:"write"});let t=g(),e=C(),n=await h.promises.readdir(e);for(let r of n){let o=T.join(t,r);await h.promises.rm(o,{force:!0}),await h.promises.rename(T.join(e,r),o)}await h.promises.rm(e,{recursive:!0,force:!0}),await h.promises.rm(T.join(t,"orama.dpack"),{force:!0})}async function hr(t,e,n){e?.start(n),await B({state:"installing",phase:1,phaseLabel:"Installing index",message:n}),await ln(t),Tt(),e&&(e.text="Documentation index installed.")}async function Hi(t,e){try{return await hr(t,e,"Installing documentation index\u2026"),await be(e),!0}catch(n){if(Qt(n))throw n}try{return await dn(),Tt(),await hr(t,e,"Retrying documentation index install\u2026"),await be(e),!0}catch(n){if(Qt(n))throw n;let r=n instanceof Error?n.message:String(n);return await Sr(`Bundled index install failed; falling back to local rebuild: ${r}`),!1}}async function ji(t,e,n){let r=C(),o=await pr();await h.promises.mkdir(g(),{recursive:!0}),await h.promises.rm(r,{recursive:!0,force:!0}),n?.start("Building search index\u2026"),await B({state:"indexing",phase:2,phaseLabel:"Building search index",message:"Building search index\u2026"});try{await Fi(o),await fr({docsDir:o,tmpDir:r,docsZipSha256:e,termsHash:yt(),synonymsHash:St(),builtBy:t.builtBy??"doc-init",onProgress:async i=>{n&&(n.text=i.message),await B({state:"indexing",current:i.current,total:i.total,message:i.message})}})}finally{await h.promises.rm(o,{recursive:!0,force:!0})}await B({state:"persisting",phase:3,phaseLabel:"Persisting index",message:"Persisting index\u2026"}),await zi(),Tt()}async function be(t){await B({state:"done",phase:3,phaseLabel:"Done",message:"Documentation ready.",error:null}),t?.succeed("Documentation ready.")}async function Ui(t){let e=await te(),n=e?`Documentation already up to date. Documents: ${e.segmentCount.toLocaleString()}`:"Documentation already up to date.";t?.succeed(n),await B({state:"done",message:n,error:null})}async function Zi(t,e){let n=t instanceof Error?t.message:String(t);throw await B({state:"error",error:n}),await Sr(`ERROR: ${n}`),e?.fail(n),t}async function $i(){let t=g();await h.promises.mkdir(t,{recursive:!0});let e=ft();return h.existsSync(e)||await h.promises.writeFile(e,"","utf-8"),e}async function Gi(){let t=await $i();return ki.lock(t,{stale:1800*1e3})}async function Xi(){let t=v(),e=(t?await ht(t):null)??await Kt();if(!e)throw new Error("docs.zip not found");return e}async function Wi(t,e){let n=await Xi(),r=t.force||await yn(t.force),o=await ee(t.force);if(!r&&!o&&ne()){await Ui(e);return}!t.force&&un(n)&&await Hi(n,e)||(await ji(t,n,e),await be(e))}var Ot=class{static async run(e={}){let n=e.background??!1,o=e.quiet??n?void 0:vi({text:"Checking documentation\u2026",color:"cyan"}),i;try{e.assumeStorageSafe||await st({mode:"write"}),i=await Gi(),await Vt(Sn("Starting documentation setup\u2026")),await Wi(e,o)}catch(s){throw i&&await Zi(s,o),s}finally{i&&await i()}}};var qi=process.env.DEVECO_CLI_POSTINSTALL?"postinstall":"doc-init";Ot.run({background:!0,builtBy:qi}).then(()=>{process.exit(0)}).catch(()=>{process.exit(1)});
|
package/docs.zip
ADDED
package/index.zip
ADDED
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@deveco-test/deveco-cli-openharmony-arm64",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "HarmonyOS application development command line tool",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"devecocli": "dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"scripts/postinstall.mjs",
|
|
13
|
+
"scripts/install-better-sqlite3.mjs",
|
|
14
|
+
"scripts/install-jieba-wasm.mjs",
|
|
15
|
+
"scripts/lib/better-sqlite3-vendor.mjs",
|
|
16
|
+
"scripts/lib/jieba-wasm-vendor.mjs",
|
|
17
|
+
"scripts/lib/cli-data-dir.mjs",
|
|
18
|
+
"scripts/lib/doc-init-log-path.mjs",
|
|
19
|
+
"templates",
|
|
20
|
+
"src/resources",
|
|
21
|
+
"THIRD-PARTY-LICENSES",
|
|
22
|
+
"SKILL.md",
|
|
23
|
+
"docs.zip",
|
|
24
|
+
"index.zip"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"prepare": "husky",
|
|
28
|
+
"postinstall": "node scripts/postinstall.mjs",
|
|
29
|
+
"build": "tsup",
|
|
30
|
+
"build:index": "tsx index/build-index-bundle.ts",
|
|
31
|
+
"dev": "tsx watch src/cli.ts",
|
|
32
|
+
"start": "tsx src/cli.ts",
|
|
33
|
+
"lint": "eslint src",
|
|
34
|
+
"lint:fix": "eslint src --fix",
|
|
35
|
+
"format": "prettier --write src",
|
|
36
|
+
"license": "generate-license-file --input package.json --output THIRD-PARTY-LICENSES --overwrite --ci",
|
|
37
|
+
"prepublishOnly": "npm run lint && npm run license && npm run build"
|
|
38
|
+
},
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=18"
|
|
41
|
+
},
|
|
42
|
+
"os": [
|
|
43
|
+
"openharmony"
|
|
44
|
+
],
|
|
45
|
+
"cpu": [
|
|
46
|
+
"arm64"
|
|
47
|
+
],
|
|
48
|
+
"keywords": [
|
|
49
|
+
"harmonyos",
|
|
50
|
+
"deveco",
|
|
51
|
+
"cli"
|
|
52
|
+
],
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@eslint/js": "^10.0.1",
|
|
55
|
+
"@types/adm-zip": "^0.5.8",
|
|
56
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
57
|
+
"@types/fs-extra": "^11.0.4",
|
|
58
|
+
"@types/global-agent": "^3.0.0",
|
|
59
|
+
"@types/node": "^25.6.0",
|
|
60
|
+
"@types/turndown": "^5.0.5",
|
|
61
|
+
"@types/yauzl": "^2.10.3",
|
|
62
|
+
"eslint": "^10.2.1",
|
|
63
|
+
"generate-license-file": "^4.2.1",
|
|
64
|
+
"husky": "^9.1.7",
|
|
65
|
+
"prettier": "^3.8.3",
|
|
66
|
+
"tsup": "^8.5.1",
|
|
67
|
+
"tsx": "^4.21.0",
|
|
68
|
+
"turndown": "^7.2.4",
|
|
69
|
+
"typescript": "^6.0.3",
|
|
70
|
+
"typescript-eslint": "^8.59.1"
|
|
71
|
+
},
|
|
72
|
+
"dependencies": {
|
|
73
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
74
|
+
"@sqlite.org/sqlite-wasm": "3.53.4-build1",
|
|
75
|
+
"adm-zip": "^0.6.1",
|
|
76
|
+
"axios": "1.19.0",
|
|
77
|
+
"colorette": "^2.0.20",
|
|
78
|
+
"commander": "^13.1.0",
|
|
79
|
+
"execa": "^9.6.1",
|
|
80
|
+
"fs-extra": "^11.3.4",
|
|
81
|
+
"global-agent": "^4.1.3",
|
|
82
|
+
"jieba-wasm": "^2.4.0",
|
|
83
|
+
"json5": "^2.2.3",
|
|
84
|
+
"mdast-util-to-string": "^4.0.0",
|
|
85
|
+
"ora": "^8.2.0",
|
|
86
|
+
"pkijs": "^3.4.0",
|
|
87
|
+
"p-limit": "^5.0.0",
|
|
88
|
+
"proper-lockfile": "^4.1.2",
|
|
89
|
+
"proxy-from-env": "^2.1.0",
|
|
90
|
+
"regedit": "^5.1.4",
|
|
91
|
+
"remark-gfm": "^4.0.1",
|
|
92
|
+
"remark-parse": "^11.0.0",
|
|
93
|
+
"smol-toml": "^1.6.1",
|
|
94
|
+
"socket.io-client": "^4.7.5",
|
|
95
|
+
"unified": "^11.0.5",
|
|
96
|
+
"xdg-basedir": "^5.1.0",
|
|
97
|
+
"yauzl": "^3.2.0",
|
|
98
|
+
"zod": "^4.4.3"
|
|
99
|
+
},
|
|
100
|
+
"optionalDependencies": {
|
|
101
|
+
"@node-rs/jieba": "^2.0.1",
|
|
102
|
+
"@node-rs/jieba-wasm32-wasi": "2.0.1",
|
|
103
|
+
"better-sqlite3": "^12.11.1"
|
|
104
|
+
},
|
|
105
|
+
"overrides": {
|
|
106
|
+
"dotenv": "16.4.7"
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Huawei Device Co., Ltd.
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { appendFile, mkdir } from 'fs/promises';
|
|
7
|
+
import { dirname } from 'path';
|
|
8
|
+
import { getDocInitLogPath } from './lib/doc-init-log-path.mjs';
|
|
9
|
+
import {
|
|
10
|
+
installBetterSqlite3ViaNpm,
|
|
11
|
+
isBetterSqlite3Loadable,
|
|
12
|
+
resolveTargetVersion,
|
|
13
|
+
} from './lib/better-sqlite3-vendor.mjs';
|
|
14
|
+
|
|
15
|
+
async function appendInstallLog(message) {
|
|
16
|
+
try {
|
|
17
|
+
const logPath = getDocInitLogPath();
|
|
18
|
+
await mkdir(dirname(logPath), { recursive: true });
|
|
19
|
+
await appendFile(
|
|
20
|
+
logPath,
|
|
21
|
+
`${new Date().toISOString()} [better-sqlite3] ${message}\n`
|
|
22
|
+
);
|
|
23
|
+
} catch {
|
|
24
|
+
// ignore logging failures
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** @deprecated Use installBetterSqlite3ViaNpm */
|
|
29
|
+
export const ensureBetterSqlite3NativeBinary = installBetterSqlite3ViaNpm;
|
|
30
|
+
|
|
31
|
+
export async function ensureBetterSqlite3ForDocs() {
|
|
32
|
+
const targetVersion = resolveTargetVersion();
|
|
33
|
+
await appendInstallLog(
|
|
34
|
+
`ensure better-sqlite3@${targetVersion} for Node ${process.version} via npm install`
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
if (await isBetterSqlite3Loadable()) {
|
|
38
|
+
await appendInstallLog('skip: better-sqlite3 already loadable');
|
|
39
|
+
return { ok: true, skipped: true, reason: 'already-installed' };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const result = await installBetterSqlite3ViaNpm();
|
|
43
|
+
if (result.ok) {
|
|
44
|
+
await appendInstallLog(`installed better-sqlite3@${targetVersion} via npm`);
|
|
45
|
+
} else {
|
|
46
|
+
await appendInstallLog(
|
|
47
|
+
`npm install failed (${result.reason}): ${result.error ?? 'unknown error'}`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Huawei Device Co., Ltd.
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { appendFile, mkdir } from 'fs/promises';
|
|
7
|
+
import { dirname } from 'path';
|
|
8
|
+
import { getDocInitLogPath } from './lib/doc-init-log-path.mjs';
|
|
9
|
+
import { installJiebaWasmViaNpm } from './lib/jieba-wasm-vendor.mjs';
|
|
10
|
+
|
|
11
|
+
async function appendInstallLog(message) {
|
|
12
|
+
try {
|
|
13
|
+
const logPath = getDocInitLogPath();
|
|
14
|
+
await mkdir(dirname(logPath), { recursive: true });
|
|
15
|
+
await appendFile(
|
|
16
|
+
logPath,
|
|
17
|
+
`${new Date().toISOString()} [jieba-wasm] ${message}\n`
|
|
18
|
+
);
|
|
19
|
+
} catch {
|
|
20
|
+
// ignore logging failures
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function ensureJiebaWasmForDocs() {
|
|
25
|
+
await appendInstallLog(
|
|
26
|
+
`ensure @node-rs/jieba-wasm32-wasi@2.0.1 for Node ${process.version}`
|
|
27
|
+
);
|
|
28
|
+
const result = await installJiebaWasmViaNpm();
|
|
29
|
+
if (result.skipped) {
|
|
30
|
+
if (result.reason === 'already-installed') {
|
|
31
|
+
await appendInstallLog('skip: jieba wasm32-wasi already loadable');
|
|
32
|
+
} else if (result.reason === 'native-available') {
|
|
33
|
+
await appendInstallLog('skip: jieba native already loadable');
|
|
34
|
+
} else {
|
|
35
|
+
await appendInstallLog(`skip: ${result.reason}`);
|
|
36
|
+
}
|
|
37
|
+
} else if (result.ok) {
|
|
38
|
+
await appendInstallLog(
|
|
39
|
+
'installed @node-rs/jieba-wasm32-wasi@2.0.1 via npm'
|
|
40
|
+
);
|
|
41
|
+
} else {
|
|
42
|
+
await appendInstallLog(
|
|
43
|
+
`npm install failed (${result.reason}): ${result.error ?? 'unknown error'}`
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Huawei Device Co., Ltd.
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { dirname, join } from 'path';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
import { existsSync } from 'fs';
|
|
9
|
+
import { spawnSync } from 'child_process';
|
|
10
|
+
|
|
11
|
+
export const BETTER_SQLITE3_VERSION_LEGACY = '11.10.0';
|
|
12
|
+
export const BETTER_SQLITE3_VERSION_NODE20 = '12.9.0';
|
|
13
|
+
export const BETTER_SQLITE3_VERSION_NODE21 = '9.6.0';
|
|
14
|
+
export const BETTER_SQLITE3_VERSION_LATEST = '12.11.1';
|
|
15
|
+
|
|
16
|
+
const scriptDir = dirname(fileURLToPath(import.meta.url));
|
|
17
|
+
export const packageRoot = join(scriptDir, '..', '..');
|
|
18
|
+
|
|
19
|
+
export function resolveTargetVersion(nodeVersion = process.version) {
|
|
20
|
+
const major = Number(nodeVersion.slice(1).split('.')[0]);
|
|
21
|
+
if (major === 18) {
|
|
22
|
+
return BETTER_SQLITE3_VERSION_LEGACY;
|
|
23
|
+
}
|
|
24
|
+
if (major === 20 || major === 23) {
|
|
25
|
+
return BETTER_SQLITE3_VERSION_NODE20;
|
|
26
|
+
}
|
|
27
|
+
if (major === 21) {
|
|
28
|
+
return BETTER_SQLITE3_VERSION_NODE21;
|
|
29
|
+
}
|
|
30
|
+
return BETTER_SQLITE3_VERSION_LATEST;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function isUnsupportedNodeVersion(nodeVersion = process.version) {
|
|
34
|
+
return Number(nodeVersion.slice(1).split('.')[0]) === 19;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function resolveNpmCliPath() {
|
|
38
|
+
const nodeDir = dirname(process.execPath);
|
|
39
|
+
const candidates = [
|
|
40
|
+
join(nodeDir, 'node_modules', 'npm', 'bin', 'npm-cli.js'),
|
|
41
|
+
join(nodeDir, '..', 'lib', 'node_modules', 'npm', 'bin', 'npm-cli.js'),
|
|
42
|
+
];
|
|
43
|
+
return candidates.find((candidate) => existsSync(candidate)) ?? null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function quoteWindowsCmdArg(arg) {
|
|
47
|
+
return /\s/.test(arg) ? `"${arg.replace(/"/g, '\\"')}"` : arg;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function spawnDetail(result) {
|
|
51
|
+
return [result.stderr, result.stdout, result.error?.message]
|
|
52
|
+
.filter(Boolean)
|
|
53
|
+
.join('\n')
|
|
54
|
+
.trim();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function runNpmInstallBetterSqlite3(targetVersion) {
|
|
58
|
+
const args = ['install', `better-sqlite3@${targetVersion}`, '--no-save'];
|
|
59
|
+
const npmCli = resolveNpmCliPath();
|
|
60
|
+
if (npmCli) {
|
|
61
|
+
return spawnSync(process.execPath, [npmCli, ...args], {
|
|
62
|
+
cwd: packageRoot,
|
|
63
|
+
stdio: 'pipe',
|
|
64
|
+
encoding: 'utf-8',
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (process.platform === 'win32') {
|
|
69
|
+
const command = ['npm', ...args].map(quoteWindowsCmdArg).join(' ');
|
|
70
|
+
return spawnSync(command, {
|
|
71
|
+
cwd: packageRoot,
|
|
72
|
+
stdio: 'pipe',
|
|
73
|
+
encoding: 'utf-8',
|
|
74
|
+
shell: true,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return spawnSync('npm', args, {
|
|
79
|
+
cwd: packageRoot,
|
|
80
|
+
stdio: 'pipe',
|
|
81
|
+
encoding: 'utf-8',
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export async function isBetterSqlite3Loadable() {
|
|
86
|
+
try {
|
|
87
|
+
await import('better-sqlite3');
|
|
88
|
+
return true;
|
|
89
|
+
} catch {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export async function installBetterSqlite3ViaNpm(nodeVersion = process.version) {
|
|
95
|
+
if (isUnsupportedNodeVersion(nodeVersion)) {
|
|
96
|
+
return {
|
|
97
|
+
ok: false,
|
|
98
|
+
reason: 'unsupported-node',
|
|
99
|
+
error: 'Node.js 19 is not supported for better-sqlite3',
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (await isBetterSqlite3Loadable()) {
|
|
104
|
+
return { ok: true, skipped: true, reason: 'already-installed' };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const targetVersion = resolveTargetVersion(nodeVersion);
|
|
108
|
+
const result = runNpmInstallBetterSqlite3(targetVersion);
|
|
109
|
+
if (result.status !== 0) {
|
|
110
|
+
return {
|
|
111
|
+
ok: false,
|
|
112
|
+
reason: 'npm-install-failed',
|
|
113
|
+
version: targetVersion,
|
|
114
|
+
error: spawnDetail(result) || `exit ${result.status ?? 'null'}`,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (!(await isBetterSqlite3Loadable())) {
|
|
119
|
+
return {
|
|
120
|
+
ok: false,
|
|
121
|
+
reason: 'load-failed',
|
|
122
|
+
version: targetVersion,
|
|
123
|
+
error: 'npm install finished but better-sqlite3 still cannot be imported',
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return { ok: true, version: targetVersion, method: 'npm' };
|
|
128
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Huawei Device Co., Ltd.
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*
|
|
5
|
+
* Keep in sync with src/utils/cli-data-dir.ts
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { homedir } from 'os';
|
|
9
|
+
import { join, resolve } from 'path';
|
|
10
|
+
|
|
11
|
+
const APP_NAME = 'deveco-cli';
|
|
12
|
+
|
|
13
|
+
/** Strip quotes from cmd.exe `set VAR="path"` (quotes become part of the value). */
|
|
14
|
+
function normalizeEnvDataDir(value) {
|
|
15
|
+
let normalized = value.trim();
|
|
16
|
+
if (
|
|
17
|
+
(normalized.startsWith('"') && normalized.endsWith('"')) ||
|
|
18
|
+
(normalized.startsWith("'") && normalized.endsWith("'"))
|
|
19
|
+
) {
|
|
20
|
+
normalized = normalized.slice(1, -1).trim();
|
|
21
|
+
}
|
|
22
|
+
return normalized;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function isCliDataDirConfigured() {
|
|
26
|
+
const raw = process.env.DEVECO_CLI_DATA_DIR;
|
|
27
|
+
return raw !== undefined && normalizeEnvDataDir(raw) !== '';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function getDefaultCliDataDir() {
|
|
31
|
+
return join(homedir(), '.local', 'share', APP_NAME);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function getCliDataDir() {
|
|
35
|
+
const raw = process.env.DEVECO_CLI_DATA_DIR;
|
|
36
|
+
if (raw === undefined || raw === '') {
|
|
37
|
+
return getDefaultCliDataDir();
|
|
38
|
+
}
|
|
39
|
+
const envDir = normalizeEnvDataDir(raw);
|
|
40
|
+
if (!envDir) {
|
|
41
|
+
return getDefaultCliDataDir();
|
|
42
|
+
}
|
|
43
|
+
return resolve(envDir);
|
|
44
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Huawei Device Co., Ltd.
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { join } from 'path';
|
|
7
|
+
import { getCliDataDir } from './cli-data-dir.mjs';
|
|
8
|
+
|
|
9
|
+
export function getDocInitLogDir() {
|
|
10
|
+
return join(getCliDataDir(), 'logs');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function getDocInitLogPath() {
|
|
14
|
+
return join(getDocInitLogDir(), 'doc-init.log');
|
|
15
|
+
}
|