rewrite API #3
@ -1,8 +1,8 @@
|
||||
FROM debian:latest
|
||||
ARG DEBIAN_FRONTEND="noninteractive"
|
||||
RUN apt update && \
|
||||
cd /tmp && mkdir debs && cd debs && \
|
||||
apt-cache depends --recurse --no-recommends --no-suggests --no-conflicts --no-breaks --no-replaces --no-enhances curl wget | grep "^\w" | sort -u | xargs apt download
|
||||
RUN apt update && apt install -y jq curl
|
||||
WORKDIR /tmp/debs
|
||||
RUN curl -Ssq https://api.github.com/repos/cli/cli/releases | grep "browser_download_url.*deb" | cut -d '"' -f 4 | xargs -n 1 curl -SsL -O
|
||||
|
||||
FROM scratch
|
||||
COPY --from=0 /tmp/debs/*.deb /
|
@ -1,7 +1,7 @@
|
||||
version: 1
|
||||
repos:
|
||||
- repo: ghcr.io/sirherobrine23/nodeaptexample:sha256:c7b3eb9435f67aa08a2e98fdaa5c4548bb8e410fc804ed352bb03dcb212dde96
|
||||
from: oci
|
||||
repos: []
|
||||
# - repo: ghcr.io/sirherobrine23/nodeaptexample:sha256:c7b3eb9435f67aa08a2e98fdaa5c4548bb8e410fc804ed352bb03dcb212dde96
|
||||
# from: oci
|
||||
|
||||
# - repo: Sirherobrine23/ghcrAptRepository
|
||||
# from: release
|
||||
|
@ -3,6 +3,7 @@ import { extendsCrypto } from "@sirherobrine23/coreutils";
|
||||
import { PassThrough, Readable } from "node:stream";
|
||||
import { format } from "node:util";
|
||||
import { Compressor as lzmaCompress } from "lzma-native";
|
||||
import { backendConfig } from "./repoConfig.js";
|
||||
import express from "express";
|
||||
import zlib from "node:zlib";
|
||||
|
||||
@ -14,7 +15,7 @@ type registerOobject = {
|
||||
}[]
|
||||
};
|
||||
|
||||
export function packageManeger(RootOptions?: {origin?: string, lebel?: string}) {
|
||||
export function packageManeger(RootOptions?: backendConfig) {
|
||||
const localRegister: registerOobject = {};
|
||||
function pushPackage(control: packageControl, getStream: () => Promise<Readable>, from?: string) {
|
||||
if (!localRegister[control.Package]) localRegister[control.Package] = [];
|
||||
@ -121,13 +122,12 @@ export function packageManeger(RootOptions?: {origin?: string, lebel?: string})
|
||||
});
|
||||
}
|
||||
|
||||
async function createRelease(options?: {packageName?: string, Arch?: string, includesHashs?: boolean}) {
|
||||
const textLines = [
|
||||
`Lebel: ${RootOptions?.lebel||"node-apt"}`,
|
||||
`Date: ${new Date().toUTCString()}`
|
||||
];
|
||||
|
||||
const components = ["main"];
|
||||
async function createRelease(options?: {packageName?: string, Arch?: string, includesHashs?: boolean, component?: string[], archive?: string}) {
|
||||
const textLines = [];
|
||||
if (RootOptions?.aptConfig?.origin) textLines.push(`Origin: ${RootOptions.aptConfig.origin}`);
|
||||
if (options?.archive) textLines.push(`Archive: ${options?.archive}`);
|
||||
else textLines.push(`Lebel: ${RootOptions?.aptConfig?.label||"node-apt"}`, `Date: ${new Date().toUTCString()}`);
|
||||
const components = options?.component ?? ["main"];
|
||||
const archs: string[] = [];
|
||||
|
||||
if (options?.packageName) {
|
||||
@ -141,20 +141,36 @@ export function packageManeger(RootOptions?: {origin?: string, lebel?: string})
|
||||
textLines.push("Suite: all");
|
||||
}
|
||||
|
||||
textLines.push(`Components: ${components.join(" ")}`, `Architectures: ${archs.join(" ")}`);
|
||||
if (options?.includesHashs) {
|
||||
const DataHashs = await Promise.all(archs.map(async (arch) => ({arch, hash: await packageHASH({Arch: arch})})));
|
||||
textLines.push(`Components: ${options?.archive ? components[0] : components.join(" ")}`, `Architectures: ${archs.join(" ")}`);
|
||||
if (options?.includesHashs && !options?.archive) {
|
||||
const arrayComponents = [];
|
||||
for (const component of components) {
|
||||
for (const arch of archs) {
|
||||
arrayComponents.push({
|
||||
component,
|
||||
arch,
|
||||
});
|
||||
}
|
||||
}
|
||||
const DataHashs = await Promise.all(arrayComponents.map(async (data) => {
|
||||
return {
|
||||
...data,
|
||||
hash: await packageHASH({
|
||||
packageName: options?.packageName,
|
||||
})
|
||||
};
|
||||
}));
|
||||
textLines.push(`MD5Sum:`);
|
||||
DataHashs.forEach(data => {
|
||||
textLines.push(` ${data.hash.raw.md5} ${data.hash.raw.size} ${data.arch}/binary-${data.arch}/Packages`);
|
||||
textLines.push(` ${data.hash.gz.md5} ${data.hash.gz.size} ${data.arch}/binary-${data.arch}/Packages.gz`);
|
||||
textLines.push(` ${data.hash.xz.md5} ${data.hash.xz.size} ${data.arch}/binary-${data.arch}/Packages.xz`);
|
||||
textLines.push(` ${data.hash.raw.md5} ${data.hash.raw.size} ${data.component}/binary-${data.arch}/Packages`);
|
||||
textLines.push(` ${data.hash.gz.md5} ${data.hash.gz.size} ${data.component}/binary-${data.arch}/Packages.gz`);
|
||||
textLines.push(` ${data.hash.xz.md5} ${data.hash.xz.size} ${data.component}/binary-${data.arch}/Packages.xz`);
|
||||
});
|
||||
textLines.push(`SHA256:`);
|
||||
DataHashs.forEach(data => {
|
||||
textLines.push(` ${data.hash.raw.sha256} ${data.hash.raw.size} ${data.arch}/binary-${data.arch}/Packages`);
|
||||
textLines.push(` ${data.hash.gz.sha256} ${data.hash.gz.size} ${data.arch}/binary-${data.arch}/Packages.gz`);
|
||||
textLines.push(` ${data.hash.xz.sha256} ${data.hash.xz.size} ${data.arch}/binary-${data.arch}/Packages.xz`);
|
||||
textLines.push(` ${data.hash.raw.sha256} ${data.hash.raw.size} ${data.component}/binary-${data.arch}/Packages`);
|
||||
textLines.push(` ${data.hash.gz.sha256} ${data.hash.gz.size} ${data.component}/binary-${data.arch}/Packages.gz`);
|
||||
textLines.push(` ${data.hash.xz.sha256} ${data.hash.xz.size} ${data.component}/binary-${data.arch}/Packages.xz`);
|
||||
});
|
||||
}
|
||||
textLines.push("");
|
||||
@ -170,7 +186,7 @@ export function packageManeger(RootOptions?: {origin?: string, lebel?: string})
|
||||
};
|
||||
}
|
||||
|
||||
export default async function repo(aptConfig: {}) {
|
||||
export default async function repo(aptConfig?: backendConfig) {
|
||||
const app = express();
|
||||
const registry = packageManeger();
|
||||
app.disable("x-powered-by").disable("etag").use(express.json()).use(express.urlencoded({extended: true})).use((_req, res, next) => {
|
||||
@ -182,16 +198,32 @@ export default async function repo(aptConfig: {}) {
|
||||
});
|
||||
|
||||
app.get("/", (_req, res) => res.json(registry.getPackages()));
|
||||
app.get("/pool/:package/:arch/:version.deb", async (req, res) => {
|
||||
const { package: packageName, arch, version } = req.params;
|
||||
const packageData = registry.getPackages()[packageName];
|
||||
if (!packageData) return res.status(404).json({error: "Package not found"});
|
||||
const packageArch = packageData.filter((p) => p.control.Architecture === arch);
|
||||
if (packageArch.length === 0) return res.status(404).json({error: "Package not found with the arch"});
|
||||
const versionData = packageArch.find((p) => p.control.Version === version);
|
||||
if (!versionData) return res.status(404).json({error: "Package not found with the version"});
|
||||
if (!req.path.endsWith(".deb")) return res.json(versionData);
|
||||
const stream = await versionData.getStream();
|
||||
return stream.pipe(res.writeHead(200, {
|
||||
"Content-Type": "application/octet-stream",
|
||||
"Content-Length": versionData.control.Size,
|
||||
}));
|
||||
});
|
||||
|
||||
app.get("/sources.list", (req, res) => {
|
||||
const host = (req.socket.localPort && req.hostname) ? req.hostname+":"+req.socket.localPort : req.query.host||req.headers["x-forwarded-host"]||req.headers.host;
|
||||
let Targets = ((req.query.t||req.query.targets) ?? ["all"]) as string[]|string;
|
||||
if (typeof Targets === "string") Targets = Targets.split(",");
|
||||
if (Targets?.length === 0) Targets = ["all"];
|
||||
if (Targets?.includes("all")||Targets.some(a => a.toLowerCase().trim() === "all")) Targets = ["all"];
|
||||
if (!Targets) Targets = ["all"];
|
||||
res.setHeader("Content-type", "text/plain");
|
||||
let config = "";
|
||||
if (req.query.all) config += format("deb [trusted=yes] %s://%s %s main\n", req.protocol, req.headers.host, "all");
|
||||
else {
|
||||
for (const suite of Object.keys(registry.getPackages())) {
|
||||
config += format("deb [trusted=yes] %s://%s %s main\n", req.protocol, req.headers.host, suite);
|
||||
}
|
||||
}
|
||||
for (const target of Targets) config += format(aptConfig?.aptConfig?.sourcesList ?? "deb [trusted=yes] %s://%s %s main\n", req.protocol, host, target);
|
||||
res.send(config+"\n");
|
||||
});
|
||||
|
||||
@ -201,10 +233,24 @@ export default async function repo(aptConfig: {}) {
|
||||
app.get("/dists/:suite/Release", (req, res, next) => {
|
||||
const { suite } = req.params;
|
||||
res.setHeader("Content-Type", "text/plain");
|
||||
return registry.createRelease({packageName: suite === "all"?undefined:suite, includesHashs: true}).then((release) => res.send(release)).catch(next);
|
||||
return registry.createRelease({
|
||||
includesHashs: true,
|
||||
packageName: suite === "all"?undefined:suite,
|
||||
}).then((release) => res.send(release)).catch(next);
|
||||
});
|
||||
|
||||
// Components
|
||||
app.get("/dists/:suite/:component/binary-:arch/Release", (req, res, next) => {
|
||||
const { suite, arch } = req.params;
|
||||
res.setHeader("Content-Type", "text/plain");
|
||||
return registry.createRelease({
|
||||
includesHashs: aptConfig?.aptConfig?.enableHash ?? true,
|
||||
Arch: arch,
|
||||
packageName: suite === "all" ? undefined : suite,
|
||||
component: [req.params.component],
|
||||
archive: req.params.component,
|
||||
}).then((release) => res.send(release)).catch(next);
|
||||
});
|
||||
app.get("/dists/:suite/:component/binary-:arch/Packages(.(gz|xz)|)", (req, res, next) => {
|
||||
const {suite, arch} = req.params;
|
||||
const streams = registry.createPackages({packageName: suite, Arch: arch});
|
||||
|
@ -12,7 +12,7 @@ yargs(process.argv.slice(2)).wrap(null).strict().help().option("cofig-path", {
|
||||
type: "number",
|
||||
default: 3000,
|
||||
}).parseAsync().then(async options => {
|
||||
const { app, registry } = await repo({});
|
||||
const { app, registry } = await repo();
|
||||
app.listen(options.port, () => {
|
||||
console.log(`Server listening on port ${options.port}`);
|
||||
});
|
||||
|
@ -22,6 +22,19 @@ export type configV1 = {
|
||||
})[]
|
||||
};
|
||||
|
||||
export type backendConfig = {
|
||||
aptConfig?: {
|
||||
origin?: string,
|
||||
label?: string,
|
||||
enableHash?: boolean,
|
||||
sourcesList?: string
|
||||
},
|
||||
repositorys: {
|
||||
target: "oci_registry"|"github_release",
|
||||
repo: string,
|
||||
}[]
|
||||
};
|
||||
|
||||
export async function getConfig(filePath: string): Promise<configV1> {
|
||||
if (!await coreUtils.extendFs.exists(filePath)) throw new Error("file not exists");
|
||||
const configData: configV1 = yaml.parse(await fs.readFile(filePath, "utf8"));
|
||||
|
@ -96,5 +96,103 @@
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "d22e6c9a-65a2-42c5-8d9f-f5f593d82dd5",
|
||||
"colId": "history",
|
||||
"containerId": "",
|
||||
"name": "http://localhost:3000/pool/",
|
||||
"url": "http://localhost:3000/pool/",
|
||||
"method": "GET",
|
||||
"sortNum": 0,
|
||||
"created": "2022-12-18T23:11:34.556Z",
|
||||
"modified": "2022-12-18T23:11:34.556Z",
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "091394e2-824e-40a0-a4ee-435c940186df",
|
||||
"colId": "history",
|
||||
"containerId": "",
|
||||
"name": "http://localhost:3000/pool/a",
|
||||
"url": "http://localhost:3000/pool/a",
|
||||
"method": "GET",
|
||||
"sortNum": 0,
|
||||
"created": "2022-12-18T23:11:43.135Z",
|
||||
"modified": "2022-12-18T23:11:43.135Z",
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "d9daac8a-8c88-42e5-bed1-fe140c911c8a",
|
||||
"colId": "history",
|
||||
"containerId": "",
|
||||
"name": "http://localhost:3000/pool/a/b",
|
||||
"url": "http://localhost:3000/pool/a/b",
|
||||
"method": "GET",
|
||||
"sortNum": 0,
|
||||
"created": "2022-12-18T23:13:15.489Z",
|
||||
"modified": "2022-12-18T23:13:15.489Z",
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "7a618a4f-2f2e-4943-9120-ab1bebd6ebc9",
|
||||
"colId": "history",
|
||||
"containerId": "",
|
||||
"name": "http://localhost:3000/pool/gh",
|
||||
"url": "http://localhost:3000/pool/gh",
|
||||
"method": "GET",
|
||||
"sortNum": 0,
|
||||
"created": "2022-12-18T23:18:38.398Z",
|
||||
"modified": "2022-12-18T23:18:38.398Z",
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "453956ca-3122-4220-99ec-7a7533bfcd70",
|
||||
"colId": "history",
|
||||
"containerId": "",
|
||||
"name": "http://localhost:3000/pool/gh/2.10.0",
|
||||
"url": "http://localhost:3000/pool/gh/2.10.0",
|
||||
"method": "GET",
|
||||
"sortNum": 0,
|
||||
"created": "2022-12-18T23:20:15.271Z",
|
||||
"modified": "2022-12-18T23:20:15.271Z",
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "37a29f1f-25cf-4f9e-9246-71056ec87e1d",
|
||||
"colId": "history",
|
||||
"containerId": "",
|
||||
"name": "http://localhost:3000/pool/gh/2.10.0.deb",
|
||||
"url": "http://localhost:3000/pool/gh/2.10.0.deb",
|
||||
"method": "GET",
|
||||
"sortNum": 0,
|
||||
"created": "2022-12-18T23:20:21.809Z",
|
||||
"modified": "2022-12-18T23:20:21.809Z",
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"tests": []
|
||||
},
|
||||
{
|
||||
"_id": "85562af1-6352-46ee-9b7f-10efed2e0782",
|
||||
"colId": "history",
|
||||
"containerId": "",
|
||||
"name": "http://localhost:3000/pool/gh/amd64/2.10.0.deb",
|
||||
"url": "http://localhost:3000/pool/gh/amd64/2.10.0.deb",
|
||||
"method": "GET",
|
||||
"sortNum": 0,
|
||||
"created": "2022-12-18T23:23:22.999Z",
|
||||
"modified": "2022-12-18T23:23:22.999Z",
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"tests": []
|
||||
}
|
||||
]
|
Reference in New Issue
Block a user