laster 0.0.1

This commit is contained in:
2026-05-25 15:49:42 +07:00
parent 14d3a3152a
commit e2c4881bb7
22 changed files with 1139 additions and 158 deletions

View File

@@ -262,11 +262,28 @@ function mapApplicationPackageRow(row) {
};
}
function isLoopbackHost(hostname) {
const host = String(hostname || '').toLowerCase();
return host === 'localhost' || host === '127.0.0.1' || host === '::1';
}
function toAbsoluteUrl(baseUrl, filePath) {
if (!filePath) return '';
if (/^https?:\/\//i.test(filePath)) return filePath;
const normalizedBaseUrl = String(baseUrl || '').replace(/\/+$/, '');
if (/^https?:\/\//i.test(filePath)) {
try {
const parsed = new URL(filePath);
if (isLoopbackHost(parsed.hostname) && parsed.pathname.startsWith('/uploads/')) {
return `${normalizedBaseUrl}${parsed.pathname}${parsed.search}`;
}
} catch {
return filePath;
}
return filePath;
}
const normalizedPath = String(filePath).startsWith('/') ? filePath : `/${filePath}`;
return `${normalizedBaseUrl}${normalizedPath}`;
@@ -824,7 +841,7 @@ async function getApplicationManifest(appCode, version, baseUrl) {
.query(`
SELECT TOP (1) Id, AppCode, AppName, AppVersion
FROM dbo.Applications
WHERE AppCode = @AppCode
WHERE (CONVERT(NVARCHAR(36), Id) = @AppCode OR AppCode = @AppCode)
AND AppVersion = @AppVersion
AND Status = N'Released';
`);
@@ -840,6 +857,7 @@ async function getApplicationManifest(appCode, version, baseUrl) {
p.PackageCode,
p.PackageName,
p.PackageType,
COALESCE(selected_version.Id, latest_version.Id) AS PackageVersionId,
COALESCE(selected_version.Version, latest_version.Version) AS Version,
COALESCE(selected_version.FilePath, latest_version.FilePath) AS FilePath,
COALESCE(selected_version.DockerImage, latest_version.DockerImage) AS DockerImage,
@@ -883,14 +901,14 @@ async function getApplicationManifest(appCode, version, baseUrl) {
required: true,
packageName: row.PackageCode,
version: row.Version || '',
downloadUrl: toAbsoluteUrl(baseUrl, row.FilePath),
downloadUrl: `${String(baseUrl || '').replace(/\/+$/, '')}/api/package-versions/${encodeURIComponent(String(row.PackageVersionId))}/download`,
sha256: row.FileChecksumSha256 || ''
};
});
return {
schemaVersion: '1.0',
appId: appRow.AppCode,
appId: String(appRow.Id),
appName: appRow.AppName,
version: appRow.AppVersion,
architecture: 'amd64',
@@ -943,6 +961,43 @@ async function getActivity() {
}));
}
async function getPackageVersionDownload(packageVersionId) {
const pool = await getPool();
const result = await pool.request()
.input('Id', sql.NVarChar(100), String(packageVersionId || '').trim())
.query(`
SELECT TOP (1)
pv.Id,
pv.PackageId,
pv.Version,
pv.FilePath,
pv.FileChecksumSha256,
pv.FileSizeBytes,
p.PackageCode,
p.PackageName,
p.PackageType
FROM dbo.PackageVersions AS pv
INNER JOIN dbo.Packages AS p
ON p.Id = pv.PackageId
WHERE CONVERT(NVARCHAR(36), pv.Id) = @Id;
`);
const row = result.recordset[0];
if (!row) return null;
return {
id: String(row.Id),
packageId: String(row.PackageId),
packageCode: row.PackageCode,
packageName: row.PackageName,
packageType: row.PackageType,
version: row.Version,
filePath: row.FilePath || '',
checksum: row.FileChecksumSha256 || '',
fileSizeBytes: Number(row.FileSizeBytes || 0)
};
}
async function createPackageWithVersion(input) {
const pool = await getPool();
const transaction = new sql.Transaction(pool);
@@ -1309,6 +1364,7 @@ module.exports = {
listPackages,
listApplications,
getApplicationManifest,
getPackageVersionDownload,
getPackageById,
getApplicationById,
createPackageWithVersion,