Files

1 line
14 KiB
JavaScript
Raw Permalink Normal View History

2025-01-04 00:34:03 +01:00
import crypto from"node:crypto";import fs from"node:fs";import path from"node:path";import{PACKAGE_AVAILABILITY_CODES,TIMEOUTS}from"../../common/constants.mjs";import{isNewerVersion,isEmpty,fetchWithTimeout,fetchJsonWithTimeout,mergeObject,deepClone}from"../../common/utils/module.mjs";import{PACKAGE_TYPE_MAPPING}from"./_module.mjs";import*as fields from"../../common/data/fields.mjs";import{cleanHTML,stripTags}from"../database/validators.mjs";import{handleCustomSocket}from"../server/sockets.mjs";import Files from"../files/files.mjs";import PackageInstaller from"./installer.mjs";import FileDownloader from"../files/downloader.mjs";import Collection from"../../common/utils/collection.mjs";import{ReleaseData}from"../../common/config.mjs";class PackageAssetField extends fields.StringField{constructor(e={}){super(e)}static get _defaults(){return mergeObject(super._defaults,{required:!0,blank:!1,mustExist:!0,allowHTTP:!0,relativeToPackage:!0,allowedPublicDir:null})}_cast(e){return this.allowHTTP&&URL.parseSafe(e)?e:Files.standardizePath(e)}initialize(e,t,i={}){if(!t.installed||!e)return e;if(this.allowHTTP&&URL.parseSafe(e))return e;const s=t._source.id,a=global.paths,r=this.relativeToPackage?path.join(t.constructor.collection,s):"",o=[{root:a.data,directory:r}];this.allowedPublicDir&&o.push({root:a.public,directory:this.allowedPublicDir});const n=Files.resolveClientPaths(e,o,{allowHTTP:this.allowHTTP});if(!n.some((({exists:e})=>e))&&this.mustExist)throw new Error(`The file "${e}" included by ${t.constructor.type} ${s} does not exist`);return n.find((({exists:e})=>e))?.clientPath??n[0]?.clientPath}}const ServerPackageMixin=e=>{const t=class extends e{constructor(e={},i={}){super(e,i),this.locked=t.#e(this.path,this.id)}static name="ServerPackageMixin";static defineSchema(){const e=super.defineSchema();e.scripts=new fields.SetField(new PackageAssetField({allowedPublicDir:"scripts"})),e.esmodules=new fields.SetField(new PackageAssetField({allowedPublicDir:"scripts"})),e.styles=new fields.SetField(new PackageAssetField);const t=e.packs.element;t.fields.path=new PackageAssetField({required:!1,allowHTTP:!1,mustExist:!1}),Object.assign(t.fields.path,{name:"path",parent:t});const i=e.languages.element;return i.fields.path=new PackageAssetField,Object.assign(i.fields.path,{name:"path",parent:i}),e}_initializeSource(e,{installed:t=!0}={}){const{logger:i}=global;try{this.constructor.migrateData(e,{installed:t})}catch(e){e.message=`Failed data migration for ${this.name}: ${e.message}`,i.warn(e)}return this.constructor.cleanData(e,{installed:t}),this.constructor.shimData(e)}static manifestMetadataFields=["title","author","authors","url","license","readme","bugs","changelog","manifest","download","compatibility"];installed=this.installed;get path(){return path.join(this.constructor.baseDir,this.id)}static get baseDir(){return path.join(global.paths.data,this.collection)}static get manifestFile(){return`${this.type}.json`}static cleanData(e={},t={}){const i=super.cleanData(e,t);return"string"==typeof i.title&&(i.title=stripTags(i.title)),"string"==typeof i.description&&(i.description=cleanHTML(i.description)),i}_configure({installed:e=!0,...t}={}){this.installed=e,super._configure(t)}_initialize(e={}){super._initialize(e);for(const e of this.packs)e.absPath=path.join(global.paths.data,e.path)}static reevaluateAvailabilities(){this.packages||this.getPackages();for(const e of this.packages.values())e.availability=e.constructor.testAvailability(e)}static#e(e,t){const i=path.join(e,`${t}.lock`);return fs.existsSync(i)}vend(){const e=super.toObject(!1);return e.availability=this.availability,e.locked=this.locked,e.exclusive=this.exclusive,e.owned=this.owned,e.tags=this.tags,e.hasStorage=this.persistentStorage&&Files.getDirectorySizeSync(this.path+"/storage")>0,e}static packages;static get(e,{strict:t=!1}={}){this.packages||this.getPackages();const i=this.packages.get(e);if(!i){if(t)throw new Error(`The requested ${this.type} ${e} does not exist!`);return null}if(i.unavailable&&t)throw new Error(`The requested package ${e} is not available for use