feat(core): initial implementation of @apiclient.xyz/gitea TypeScript client
Provides GiteaClient class with methods for repos, orgs, secrets, and action runs.
This commit is contained in:
19
.gitignore
vendored
Normal file
19
.gitignore
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
.nogit/
|
||||||
|
|
||||||
|
# artifacts
|
||||||
|
coverage/
|
||||||
|
public/
|
||||||
|
|
||||||
|
# installs
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# caches
|
||||||
|
.yarn/
|
||||||
|
.cache/
|
||||||
|
.rpt2_cache
|
||||||
|
|
||||||
|
# builds
|
||||||
|
dist/
|
||||||
|
dist_*/
|
||||||
|
|
||||||
|
#------# custom
|
||||||
21
license.md
Normal file
21
license.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025 Lossless GmbH (https://lossless.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
26
npmextra.json
Normal file
26
npmextra.json
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"npmci": {
|
||||||
|
"npmGlobalTools": [],
|
||||||
|
"npmAccessLevel": "public"
|
||||||
|
},
|
||||||
|
"gitzone": {
|
||||||
|
"projectType": "npm",
|
||||||
|
"module": {
|
||||||
|
"githost": "code.foss.global",
|
||||||
|
"gitscope": "apiclient.xyz",
|
||||||
|
"gitrepo": "gitea",
|
||||||
|
"description": "A TypeScript client for the Gitea API, providing easy access to repositories, organizations, secrets, and action runs.",
|
||||||
|
"npmPackagename": "@apiclient.xyz/gitea",
|
||||||
|
"license": "MIT",
|
||||||
|
"keywords": [
|
||||||
|
"gitea",
|
||||||
|
"api client",
|
||||||
|
"TypeScript",
|
||||||
|
"git hosting",
|
||||||
|
"CI/CD",
|
||||||
|
"actions",
|
||||||
|
"secrets management"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
55
package.json
Normal file
55
package.json
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
{
|
||||||
|
"name": "@apiclient.xyz/gitea",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": false,
|
||||||
|
"description": "A TypeScript client for the Gitea API, providing easy access to repositories, organizations, secrets, and action runs.",
|
||||||
|
"main": "dist_ts/index.js",
|
||||||
|
"typings": "dist_ts/index.d.ts",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"test": "(tstest test/ --verbose --timeout 600)",
|
||||||
|
"build": "(tsbuild --web --allowimplicitany)"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://code.foss.global/apiclient.xyz/gitea.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"gitea",
|
||||||
|
"api client",
|
||||||
|
"TypeScript",
|
||||||
|
"git hosting",
|
||||||
|
"CI/CD",
|
||||||
|
"actions",
|
||||||
|
"secrets management"
|
||||||
|
],
|
||||||
|
"author": "Lossless GmbH",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@push.rocks/smartlog": "^3.1.10",
|
||||||
|
"@push.rocks/smartrequest": "^5.0.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@git.zone/tsbuild": "^3.1.0",
|
||||||
|
"@git.zone/tsrun": "^2.0.0",
|
||||||
|
"@git.zone/tstest": "^2.8.2",
|
||||||
|
"@push.rocks/qenv": "^6.1.3",
|
||||||
|
"@push.rocks/tapbundle": "^5.6.0",
|
||||||
|
"@types/node": "^22.15.3"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"ts/**/*",
|
||||||
|
"ts_web/**/*",
|
||||||
|
"dist/**/*",
|
||||||
|
"dist_*/**/*",
|
||||||
|
"dist_ts/**/*",
|
||||||
|
"dist_ts_web/**/*",
|
||||||
|
"assets/**/*",
|
||||||
|
"cli.js",
|
||||||
|
"npmextra.json",
|
||||||
|
"readme.md"
|
||||||
|
],
|
||||||
|
"browserslist": [
|
||||||
|
"last 1 chrome versions"
|
||||||
|
]
|
||||||
|
}
|
||||||
9914
pnpm-lock.yaml
generated
Normal file
9914
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
30
readme.md
Normal file
30
readme.md
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# @apiclient.xyz/gitea
|
||||||
|
|
||||||
|
A TypeScript client for the Gitea API, providing easy access to repositories, organizations, secrets, and action runs.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install @apiclient.xyz/gitea
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { GiteaClient } from '@apiclient.xyz/gitea';
|
||||||
|
|
||||||
|
const client = new GiteaClient('https://gitea.example.com', 'your-api-token');
|
||||||
|
|
||||||
|
// Test connection
|
||||||
|
const result = await client.testConnection();
|
||||||
|
|
||||||
|
// List repositories
|
||||||
|
const repos = await client.getRepos();
|
||||||
|
|
||||||
|
// Manage secrets
|
||||||
|
await client.setRepoSecret('owner/repo', 'SECRET_KEY', 'secret-value');
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
||||||
34
test/test.node.ts
Normal file
34
test/test.node.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { tap, expect } from '@push.rocks/tapbundle';
|
||||||
|
import * as qenv from '@push.rocks/qenv';
|
||||||
|
import { GiteaClient } from '../ts/index.js';
|
||||||
|
|
||||||
|
const testQenv = new qenv.Qenv('./', '.nogit/');
|
||||||
|
|
||||||
|
let giteaClient: GiteaClient;
|
||||||
|
|
||||||
|
tap.test('should create a GiteaClient instance', async () => {
|
||||||
|
const baseUrl = testQenv.getEnvVarOnDemand('GITEA_BASE_URL') || 'https://gitea.lossless.digital';
|
||||||
|
const token = testQenv.getEnvVarOnDemand('GITEA_TOKEN') || '';
|
||||||
|
giteaClient = new GiteaClient(baseUrl, token);
|
||||||
|
expect(giteaClient).toBeInstanceOf(GiteaClient);
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('should test connection', async () => {
|
||||||
|
const result = await giteaClient.testConnection();
|
||||||
|
expect(result).toHaveProperty('ok');
|
||||||
|
console.log('Connection test:', result);
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('should get repos', async () => {
|
||||||
|
const repos = await giteaClient.getRepos({ perPage: 5 });
|
||||||
|
expect(repos).toBeArray();
|
||||||
|
console.log(`Found ${repos.length} repos`);
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('should get orgs', async () => {
|
||||||
|
const orgs = await giteaClient.getOrgs({ perPage: 5 });
|
||||||
|
expect(orgs).toBeArray();
|
||||||
|
console.log(`Found ${orgs.length} orgs`);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default tap.start();
|
||||||
8
ts/00_commitinfo_data.ts
Normal file
8
ts/00_commitinfo_data.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* autocreated commitinfo by @push.rocks/commitinfo
|
||||||
|
*/
|
||||||
|
export const commitinfo = {
|
||||||
|
name: '@apiclient.xyz/gitea',
|
||||||
|
version: '1.0.0',
|
||||||
|
description: 'A TypeScript client for the Gitea API, providing easy access to repositories, organizations, secrets, and action runs.',
|
||||||
|
};
|
||||||
211
ts/gitea.classes.giteaclient.ts
Normal file
211
ts/gitea.classes.giteaclient.ts
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
import * as plugins from './gitea.plugins.js';
|
||||||
|
import { logger } from './gitea.logging.js';
|
||||||
|
import type {
|
||||||
|
IGiteaUser,
|
||||||
|
IGiteaRepository,
|
||||||
|
IGiteaOrganization,
|
||||||
|
IGiteaSecret,
|
||||||
|
IGiteaActionRun,
|
||||||
|
IGiteaActionRunJob,
|
||||||
|
ITestConnectionResult,
|
||||||
|
IListOptions,
|
||||||
|
} from './gitea.interfaces.js';
|
||||||
|
|
||||||
|
export class GiteaClient {
|
||||||
|
private baseUrl: string;
|
||||||
|
private token: string;
|
||||||
|
|
||||||
|
constructor(baseUrl: string, token: string) {
|
||||||
|
// Remove trailing slash if present
|
||||||
|
this.baseUrl = baseUrl.replace(/\/+$/, '');
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// HTTP helpers
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
private async request<T = any>(
|
||||||
|
method: 'GET' | 'POST' | 'PUT' | 'DELETE',
|
||||||
|
path: string,
|
||||||
|
data?: any,
|
||||||
|
customHeaders?: Record<string, string>,
|
||||||
|
): Promise<T> {
|
||||||
|
const url = `${this.baseUrl}${path}`;
|
||||||
|
|
||||||
|
let builder = plugins.smartrequest.SmartRequest.create()
|
||||||
|
.url(url)
|
||||||
|
.header('Authorization', `token ${this.token}`)
|
||||||
|
.header('Content-Type', 'application/json');
|
||||||
|
|
||||||
|
if (customHeaders) {
|
||||||
|
for (const [k, v] of Object.entries(customHeaders)) {
|
||||||
|
builder = builder.header(k, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
builder = builder.json(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
let response: Awaited<ReturnType<typeof builder.get>>;
|
||||||
|
switch (method) {
|
||||||
|
case 'GET':
|
||||||
|
response = await builder.get();
|
||||||
|
break;
|
||||||
|
case 'POST':
|
||||||
|
response = await builder.post();
|
||||||
|
break;
|
||||||
|
case 'PUT':
|
||||||
|
response = await builder.put();
|
||||||
|
break;
|
||||||
|
case 'DELETE':
|
||||||
|
response = await builder.delete();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const errorText = await response.text();
|
||||||
|
throw new Error(`${method} ${path}: ${response.status} ${response.statusText} - ${errorText}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return await response.json() as T;
|
||||||
|
} catch {
|
||||||
|
return undefined as unknown as T;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async requestText(
|
||||||
|
method: 'GET' | 'POST' | 'PUT' | 'DELETE',
|
||||||
|
path: string,
|
||||||
|
): Promise<string> {
|
||||||
|
const url = `${this.baseUrl}${path}`;
|
||||||
|
|
||||||
|
let builder = plugins.smartrequest.SmartRequest.create()
|
||||||
|
.url(url)
|
||||||
|
.header('Authorization', `token ${this.token}`)
|
||||||
|
.header('Accept', 'text/plain');
|
||||||
|
|
||||||
|
let response: Awaited<ReturnType<typeof builder.get>>;
|
||||||
|
switch (method) {
|
||||||
|
case 'GET':
|
||||||
|
response = await builder.get();
|
||||||
|
break;
|
||||||
|
case 'POST':
|
||||||
|
response = await builder.post();
|
||||||
|
break;
|
||||||
|
case 'PUT':
|
||||||
|
response = await builder.put();
|
||||||
|
break;
|
||||||
|
case 'DELETE':
|
||||||
|
response = await builder.delete();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const errorText = await response.text();
|
||||||
|
throw new Error(`${method} ${path}: ${response.status} ${response.statusText} - ${errorText}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.text();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Connection
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
public async testConnection(): Promise<ITestConnectionResult> {
|
||||||
|
try {
|
||||||
|
await this.request<IGiteaUser>('GET', '/api/v1/user');
|
||||||
|
return { ok: true };
|
||||||
|
} catch (err) {
|
||||||
|
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Repositories
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
public async getRepos(opts?: IListOptions): Promise<IGiteaRepository[]> {
|
||||||
|
const page = opts?.page || 1;
|
||||||
|
const limit = opts?.perPage || 50;
|
||||||
|
let url = `/api/v1/repos/search?page=${page}&limit=${limit}&sort=updated`;
|
||||||
|
if (opts?.search) {
|
||||||
|
url += `&q=${encodeURIComponent(opts.search)}`;
|
||||||
|
}
|
||||||
|
const body = await this.request<any>('GET', url);
|
||||||
|
return body.data || body;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Organizations
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
public async getOrgs(opts?: IListOptions): Promise<IGiteaOrganization[]> {
|
||||||
|
const page = opts?.page || 1;
|
||||||
|
const limit = opts?.perPage || 50;
|
||||||
|
return this.request<IGiteaOrganization[]>('GET', `/api/v1/orgs?page=${page}&limit=${limit}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Repository Secrets
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
public async getRepoSecrets(ownerRepo: string): Promise<IGiteaSecret[]> {
|
||||||
|
return this.request<IGiteaSecret[]>('GET', `/api/v1/repos/${ownerRepo}/actions/secrets`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async setRepoSecret(ownerRepo: string, key: string, value: string): Promise<void> {
|
||||||
|
await this.request('PUT', `/api/v1/repos/${ownerRepo}/actions/secrets/${key}`, { data: value });
|
||||||
|
}
|
||||||
|
|
||||||
|
public async deleteRepoSecret(ownerRepo: string, key: string): Promise<void> {
|
||||||
|
await this.request('DELETE', `/api/v1/repos/${ownerRepo}/actions/secrets/${key}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Organization Secrets
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
public async getOrgSecrets(orgName: string): Promise<IGiteaSecret[]> {
|
||||||
|
return this.request<IGiteaSecret[]>('GET', `/api/v1/orgs/${orgName}/actions/secrets`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async setOrgSecret(orgName: string, key: string, value: string): Promise<void> {
|
||||||
|
await this.request('PUT', `/api/v1/orgs/${orgName}/actions/secrets/${key}`, { data: value });
|
||||||
|
}
|
||||||
|
|
||||||
|
public async deleteOrgSecret(orgName: string, key: string): Promise<void> {
|
||||||
|
await this.request('DELETE', `/api/v1/orgs/${orgName}/actions/secrets/${key}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Action Runs
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
public async getActionRuns(ownerRepo: string, opts?: IListOptions): Promise<IGiteaActionRun[]> {
|
||||||
|
const page = opts?.page || 1;
|
||||||
|
const limit = opts?.perPage || 30;
|
||||||
|
const body = await this.request<any>('GET', `/api/v1/repos/${ownerRepo}/actions/runs?page=${page}&limit=${limit}`);
|
||||||
|
return body.workflow_runs || body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getActionRunJobs(ownerRepo: string, runId: number): Promise<IGiteaActionRunJob[]> {
|
||||||
|
const body = await this.request<any>('GET', `/api/v1/repos/${ownerRepo}/actions/runs/${runId}/jobs`);
|
||||||
|
return body.jobs || body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getJobLog(ownerRepo: string, jobId: number): Promise<string> {
|
||||||
|
return this.requestText('GET', `/api/v1/repos/${ownerRepo}/actions/jobs/${jobId}/logs`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async rerunAction(ownerRepo: string, runId: number): Promise<void> {
|
||||||
|
await this.request('POST', `/api/v1/repos/${ownerRepo}/actions/runs/${runId}/rerun`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async cancelAction(ownerRepo: string, runId: number): Promise<void> {
|
||||||
|
await this.request('POST', `/api/v1/repos/${ownerRepo}/actions/runs/${runId}/cancel`);
|
||||||
|
}
|
||||||
|
}
|
||||||
70
ts/gitea.interfaces.ts
Normal file
70
ts/gitea.interfaces.ts
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
export interface IGiteaUser {
|
||||||
|
id: number;
|
||||||
|
login: string;
|
||||||
|
full_name: string;
|
||||||
|
email: string;
|
||||||
|
avatar_url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IGiteaRepository {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
full_name: string;
|
||||||
|
description: string;
|
||||||
|
default_branch: string;
|
||||||
|
html_url: string;
|
||||||
|
private: boolean;
|
||||||
|
topics: string[];
|
||||||
|
updated_at: string;
|
||||||
|
owner: {
|
||||||
|
id: number;
|
||||||
|
login: string;
|
||||||
|
avatar_url: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IGiteaOrganization {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
full_name: string;
|
||||||
|
description: string;
|
||||||
|
visibility: string;
|
||||||
|
repo_count: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IGiteaSecret {
|
||||||
|
name: string;
|
||||||
|
created_at: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IGiteaActionRun {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
status: string;
|
||||||
|
conclusion: string;
|
||||||
|
head_branch: string;
|
||||||
|
head_sha: string;
|
||||||
|
html_url: string;
|
||||||
|
event: string;
|
||||||
|
run_duration: number;
|
||||||
|
created_at: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IGiteaActionRunJob {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
status: string;
|
||||||
|
conclusion: string;
|
||||||
|
run_duration: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ITestConnectionResult {
|
||||||
|
ok: boolean;
|
||||||
|
error?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IListOptions {
|
||||||
|
search?: string;
|
||||||
|
page?: number;
|
||||||
|
perPage?: number;
|
||||||
|
}
|
||||||
3
ts/gitea.logging.ts
Normal file
3
ts/gitea.logging.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import * as plugins from './gitea.plugins.js';
|
||||||
|
|
||||||
|
export const logger = new plugins.smartlog.ConsoleLog();
|
||||||
4
ts/gitea.plugins.ts
Normal file
4
ts/gitea.plugins.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import * as smartlog from '@push.rocks/smartlog';
|
||||||
|
import * as smartrequest from '@push.rocks/smartrequest';
|
||||||
|
|
||||||
|
export { smartlog, smartrequest };
|
||||||
12
ts/index.ts
Normal file
12
ts/index.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
export { GiteaClient } from './gitea.classes.giteaclient.js';
|
||||||
|
export type {
|
||||||
|
IGiteaUser,
|
||||||
|
IGiteaRepository,
|
||||||
|
IGiteaOrganization,
|
||||||
|
IGiteaSecret,
|
||||||
|
IGiteaActionRun,
|
||||||
|
IGiteaActionRunJob,
|
||||||
|
ITestConnectionResult,
|
||||||
|
IListOptions,
|
||||||
|
} from './gitea.interfaces.js';
|
||||||
|
export { commitinfo } from './00_commitinfo_data.js';
|
||||||
16
tsconfig.json
Normal file
16
tsconfig.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"useDefineForClassFields": false,
|
||||||
|
"target": "ES2022",
|
||||||
|
"module": "NodeNext",
|
||||||
|
"moduleResolution": "NodeNext",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {}
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"dist_*/**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user