import { Zip } from "./zip.ts";
import { Permission } from "./permissions.ts";
import type { VP_Request } from "./vp_request.ts";
import { IsSameVersionNumber, LatestVersionNumber, SerializeVersionNumber } from "../utils/version_helpers.ts";
import { Fail } from "./pak_responses/fail.ts";
import { Package, ValidateNamespacedString } from "../classes/package.ts";
import { existsSync } from "jsr:@std/fs/exists";
import { join } from "$std/path/mod.ts";
import { Sort } from "../utils/sort_utils.ts";
import { User } from "$classes/user.ts";
import { Token } from "$classes/token.ts";
export const HandlePublish = async (request: VP_Request) => {
if(!request.permissions.can(Permission.UPDATE_PACKAGES)) return 403;
if(!request.body) return 400;
if(!request.token) return 401;
const user = await User.findOne({
$relationship: {
via: Token,
match: { uuid: request.token },
select: 'user_id'
}
});
if(!user) return 401;
const location = request.pathname.replace('/publish', '').replace(/^\/+/, '');
if(!ValidateNamespacedString(location)) return 400;
const {package: { version }} = Package.BreakLocation(location)!;
if(!version) return 400;
let _package: Package;
const find_result = await Package.FindByPath(location);
const tags = JSON.parse(request.headers.get('X-Tags') || '[]') as string[];
if(find_result) {
_package = find_result;
_package.versions.current = version;
_package.tags = tags;
} else {
const { namespace, package: { name } } = Package.BreakLocation(location)!;
_package = new Package({
namespace,
name,
deprecated: false,
tags,
events: [
{
event: "create",
timestamp: Date.now(),
token: request.token,
version
},
{
event: `publish @${version}`,
timestamp: Date.now() + 10,
token: request.token,
version
},
],
versions: {
all: [version],
latest: version,
current: null
},
});
try {
await Zip.Unzip(request.body, join(_package.root_path, version));
} catch(_) {
return 400;
}
await _package.save();
return 200;
}
const FORCE = request.headers.has('X-Force');
let force_required = false;
const version_exists = _package?.versions.all.map(SerializeVersionNumber).includes(SerializeVersionNumber(_package.versions.current!));
if(version_exists ||
(
_package.versions.latest &&
LatestVersionNumber([_package.versions.latest!, version]) == _package.versions.latest!
)
) force_required = true;
if(force_required && !request.permissions.can(Permission.OVERWRITE_PACKAGES)) return 403;
if(version_exists && !FORCE) {
if(IsSameVersionNumber(_package.versions.latest, version)) return Fail(`Version [${version}] already exists. Please update your version number, or use --force if you have the right permissions.`, 400);
}
if(_package.versions.latest && !FORCE) {
if(LatestVersionNumber([_package.versions.latest, version]) == _package.versions.latest) return Fail(`Version [${_package.versions.latest}] is newer than the provided version [${version}]. Please update your version number, or use --force if you have the right permissions.`, 400);
}
if(existsSync(_package.path!)) {
Deno.removeSync(_package.path!, {
recursive: true
})
}
try {
await Zip.Unzip(request.body, _package.path!);
} catch(_) {
return 400;
}
if(!version_exists) {
_package.versions.all.push(version);
}
if(!_package.versions.latest || [version, _package.versions.latest].sort(Sort.Version.Descending)[0] == version) {
_package.versions.latest = version;
}
if(version_exists && FORCE) {
_package.addEvent(request.token, `overwrite @${version}`);
} else {
_package.addEvent(request.token, `publish @${version}`);
}
if(_package.namespace == '@viapak' && _package.name == 'viapak') {
console.log(`VIAPAK UPGRADE DETECTED. SELF DESTRUCT INITIATED!`);
setTimeout(() => {
Deno.exit(0);
}, 5);
}
return 200;
}