Merge branch 'main' of https://git.prelude.duckdns.org/monoid/simple-deno-import-gitea
This commit is contained in:
commit
8a67f4fbdb
59
app.ts
59
app.ts
@ -2,18 +2,27 @@ import { Application, Router, isHttpError } from "https://deno.land/x/oak@v12.1.
|
|||||||
import {
|
import {
|
||||||
searchRepositoryWithTopic,
|
searchRepositoryWithTopic,
|
||||||
getRepositoryTags,
|
getRepositoryTags,
|
||||||
getRepositoryContent
|
getRepositoryContent,
|
||||||
|
GiteaOption
|
||||||
} from "./gitea.ts";
|
} from "./gitea.ts";
|
||||||
import { ContentsResponse } from "./gitea_api.d.ts";
|
import { ContentsResponse } from "./gitea_api.d.ts";
|
||||||
import { Command } from "https://deno.land/x/cliffy@v0.25.7/mod.ts";
|
import { Command } from "https://deno.land/x/cliffy@v0.25.7/mod.ts";
|
||||||
|
|
||||||
// import { load } from "https://deno.land/std@0.181.0/dotenv/mod.ts";
|
import { load } from "https://deno.land/std@0.191.0/dotenv/mod.ts";
|
||||||
// const env = await load();
|
const env = await load();
|
||||||
|
|
||||||
|
function getGiteaOptions(): GiteaOption | undefined {
|
||||||
|
const token = env.TOKEN;
|
||||||
|
if (token === undefined) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
return { token: token };
|
||||||
|
}
|
||||||
|
|
||||||
const app = new Application();
|
const app = new Application();
|
||||||
const router = new Router();
|
const router = new Router();
|
||||||
|
|
||||||
const RelativeTopic = "denolib";
|
const RelativeTopic = env.tag ?? "denolib";
|
||||||
|
|
||||||
export interface CompletionList {
|
export interface CompletionList {
|
||||||
/** The list (or partial list) of completion items. */
|
/** The list (or partial list) of completion items. */
|
||||||
@ -37,7 +46,7 @@ router.get("/.well-known/deno-import-intellisense.json", (ctx) => {
|
|||||||
"variables": [
|
"variables": [
|
||||||
{
|
{
|
||||||
"key": "package",
|
"key": "package",
|
||||||
// "documentation": "/docs/packages/${package}",
|
// "documentation": "/docs/packages/${package}",
|
||||||
"url": "/packages/${package}"
|
"url": "/packages/${package}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -46,7 +55,7 @@ router.get("/.well-known/deno-import-intellisense.json", (ctx) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "path",
|
"key": "path",
|
||||||
// "documentation": "/docs/packages/${package}/${{version}}/paths/${path}",
|
// "documentation": "/docs/packages/${package}/${{version}}/paths/${path}",
|
||||||
"url": "/packages/${package}/${{version}}/paths/${path}"
|
"url": "/packages/${package}/${{version}}/paths/${path}"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -58,10 +67,11 @@ router.get("/.well-known/deno-import-intellisense.json", (ctx) => {
|
|||||||
router.get("/packages/:package", async (ctx) => {
|
router.get("/packages/:package", async (ctx) => {
|
||||||
const packageName = ctx.params.package;
|
const packageName = ctx.params.package;
|
||||||
console.log(`searchRepositoryWithTopic: ${packageName}`);
|
console.log(`searchRepositoryWithTopic: ${packageName}`);
|
||||||
const repositories = await searchRepositoryWithTopic(RelativeTopic);
|
const options = getGiteaOptions();
|
||||||
|
const repositories = await searchRepositoryWithTopic(RelativeTopic, options);
|
||||||
const repo_name = repositories.data?.map((repo) => repo.full_name)
|
const repo_name = repositories.data?.map((repo) => repo.full_name)
|
||||||
.filter(x => x !== undefined)
|
.filter(x => x !== undefined)
|
||||||
.map(x=> x?.replace("/","@")) ?? [];
|
.map(x => x?.replace("/", "@")) ?? [];
|
||||||
const completionList: CompletionList = {
|
const completionList: CompletionList = {
|
||||||
items: repo_name as string[],
|
items: repo_name as string[],
|
||||||
isIncomplete: true, // TODO: check if there are more than max results
|
isIncomplete: true, // TODO: check if there are more than max results
|
||||||
@ -75,7 +85,8 @@ router.get("/packages/:package/versions", async (ctx) => {
|
|||||||
const packageName = ctx.params.package;
|
const packageName = ctx.params.package;
|
||||||
const [owner, repo] = packageName.split("@");
|
const [owner, repo] = packageName.split("@");
|
||||||
console.log(`getTags: owner: ${owner}, repo: ${repo}`);
|
console.log(`getTags: owner: ${owner}, repo: ${repo}`);
|
||||||
const tags = await getRepositoryTags(owner, repo);
|
const options = getGiteaOptions();
|
||||||
|
const tags = await getRepositoryTags(owner, repo, options);
|
||||||
const candidate = ["main", ...tags.map((tag) => tag.name) as string[]]
|
const candidate = ["main", ...tags.map((tag) => tag.name) as string[]]
|
||||||
const completionList: CompletionList = {
|
const completionList: CompletionList = {
|
||||||
items: candidate,
|
items: candidate,
|
||||||
@ -92,7 +103,8 @@ router.get("/packages/:package/:version/paths/:path*", async (ctx) => {
|
|||||||
const path = ctx.params.path;
|
const path = ctx.params.path;
|
||||||
const [owner, repo] = packageName.split("@");
|
const [owner, repo] = packageName.split("@");
|
||||||
console.log(`getFilesEntry: owner: ${owner}, repo: ${repo}, path: ${path}, version: ${version}`);
|
console.log(`getFilesEntry: owner: ${owner}, repo: ${repo}, path: ${path}, version: ${version}`);
|
||||||
const entries = await getRepositoryContent(owner, repo, path ?? "", version) as ContentsResponse[];
|
const options = getGiteaOptions();
|
||||||
|
const entries = await getRepositoryContent(owner, repo, path ?? "", version, options) as ContentsResponse[];
|
||||||
const completionList: CompletionList = {
|
const completionList: CompletionList = {
|
||||||
items: entries.map((entry) => entry.name) as string[],
|
items: entries.map((entry) => entry.name) as string[],
|
||||||
isIncomplete: false,
|
isIncomplete: false,
|
||||||
@ -108,13 +120,14 @@ router.get("/:package([a-z0-9_]*@[a-z0-9_]*)/:version?/:path*", async (ctx) => {
|
|||||||
const version = ctx.params.version;
|
const version = ctx.params.version;
|
||||||
const path = ctx.params.path;
|
const path = ctx.params.path;
|
||||||
console.log(`getFiles: owner: ${owner}, repo: ${repo}, path: ${path}, version: ${version}`);
|
console.log(`getFiles: owner: ${owner}, repo: ${repo}, path: ${path}, version: ${version}`);
|
||||||
const entries = await getRepositoryContent(owner, repo, path ?? "", version);
|
const options = getGiteaOptions();
|
||||||
|
const entries = await getRepositoryContent(owner, repo, path ?? "", version, options);
|
||||||
if (entries instanceof Array) {
|
if (entries instanceof Array) {
|
||||||
ctx.response.type = "application/json";
|
ctx.response.type = "application/json";
|
||||||
ctx.response.body = entries;
|
ctx.response.body = entries;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ("errors" in entries){
|
if ("errors" in entries) {
|
||||||
ctx.throw(404);
|
ctx.throw(404);
|
||||||
}
|
}
|
||||||
// TODO: check if the file is text file or not (e.g. image)
|
// TODO: check if the file is text file or not (e.g. image)
|
||||||
@ -123,11 +136,28 @@ router.get("/:package([a-z0-9_]*@[a-z0-9_]*)/:version?/:path*", async (ctx) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
app.use(async (ctx, next) => {
|
||||||
|
try {
|
||||||
|
await next();
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
if (isHttpError(err)) {
|
||||||
|
console.log(err);
|
||||||
|
ctx.response.status = err.status;
|
||||||
|
const { message, status, stack } = err;
|
||||||
|
ctx.response.body = { message, status, stack };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
app.use(router.routes());
|
app.use(router.routes());
|
||||||
app.use(router.allowedMethods());
|
app.use(router.allowedMethods());
|
||||||
|
|
||||||
app.use(async (ctx, next) => {
|
app.use(async (ctx, next) => {
|
||||||
try{
|
try {
|
||||||
await next();
|
await next();
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
@ -137,7 +167,8 @@ app.use(async (ctx, next) => {
|
|||||||
const { message, status, stack } = err;
|
const { message, status, stack } = err;
|
||||||
ctx.response.body = { message, status, stack };
|
ctx.response.body = { message, status, stack };
|
||||||
}
|
}
|
||||||
else { throw err;
|
else {
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
32
gitea.ts
32
gitea.ts
@ -2,29 +2,43 @@ import { SearchResults, Tag, ContentsResponse } from "./gitea_api.d.ts";
|
|||||||
|
|
||||||
const ENDPOINT_URL = "https://git.prelude.duckdns.org/api/v1/";
|
const ENDPOINT_URL = "https://git.prelude.duckdns.org/api/v1/";
|
||||||
|
|
||||||
export async function searchRepositoryWithTopic(topic: string): Promise<SearchResults> {
|
export interface GiteaOption{
|
||||||
|
token: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchFromGitea(url: string | URL, giteaOption? :GiteaOption): Promise<any> {
|
||||||
|
const headers = new Headers();
|
||||||
|
if (giteaOption) {
|
||||||
|
headers.append("Authorization", "token " + giteaOption.token);
|
||||||
|
}
|
||||||
|
const response = await fetch(url, {
|
||||||
|
headers: headers
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const data = await response.json();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function searchRepositoryWithTopic(topic: string, giteaOption? :GiteaOption): Promise<SearchResults> {
|
||||||
const url = new URL(ENDPOINT_URL+ "repos/search");
|
const url = new URL(ENDPOINT_URL+ "repos/search");
|
||||||
url.searchParams.append("q", topic);
|
url.searchParams.append("q", topic);
|
||||||
url.searchParams.append("topic", "true");
|
url.searchParams.append("topic", "true");
|
||||||
const response = await fetch(url);
|
const data = await fetchFromGitea(url,giteaOption);
|
||||||
const data = await response.json();
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getRepositoryTags(owner:string,
|
export async function getRepositoryTags(owner:string,
|
||||||
repo:string): Promise<Tag[]>{
|
repo:string, giteaOption? :GiteaOption): Promise<Tag[]>{
|
||||||
const url = new URL(ENDPOINT_URL+ "repos/"+owner+"/"+repo+"/tags");
|
const url = new URL(ENDPOINT_URL+ "repos/"+owner+"/"+repo+"/tags");
|
||||||
const response = await fetch(url);
|
const data = await fetchFromGitea(url,giteaOption);
|
||||||
const data = await response.json();
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getRepositoryContent(owner:string,
|
export async function getRepositoryContent(owner:string,
|
||||||
repo:string, path:string, ref:string): Promise<ContentsResponse[] | ContentsResponse>{
|
repo:string, path:string, ref:string, giteaOption? :GiteaOption): Promise<ContentsResponse[] | ContentsResponse>{
|
||||||
const url = new URL(ENDPOINT_URL+ "repos/"+owner+"/"+repo+"/contents/"+path);
|
const url = new URL(ENDPOINT_URL+ "repos/"+owner+"/"+repo+"/contents/"+path);
|
||||||
url.searchParams.append("ref", ref);
|
url.searchParams.append("ref", ref);
|
||||||
const response = await fetch(url);
|
const data = await fetchFromGitea(url,giteaOption);
|
||||||
const data = await response.json();
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user