chore: initial commit with publish config
This commit is contained in:
commit
a816a4788c
12 changed files with 605 additions and 0 deletions
50
.forgejo/workflows/publish.yml
Normal file
50
.forgejo/workflows/publish.yml
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
name: Build and Publish
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, master]
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
NODE_VERSION: "22"
|
||||
PNPM_VERSION: "9"
|
||||
|
||||
jobs:
|
||||
build-and-publish:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
- run: npm install -g pnpm@${{ env.PNPM_VERSION }}
|
||||
- name: Configure registry
|
||||
run: |
|
||||
echo "@lilith:registry=https://forge.nasty.sh/api/packages/lilith/npm/" > .npmrc
|
||||
echo "//forge.nasty.sh/api/packages/lilith/npm/:_authToken=\${NPM_TOKEN}" >> .npmrc
|
||||
echo "strict-ssl=false" >> .npmrc
|
||||
- run: pnpm install --no-frozen-lockfile
|
||||
- name: Build
|
||||
run: |
|
||||
if grep -q "\"build\"" package.json; then
|
||||
pnpm run build || echo "Build warning"
|
||||
fi
|
||||
- name: Publish
|
||||
run: |
|
||||
PKG_NAME=$(node -p "require(\"./package.json\").name")
|
||||
PKG_VERSION=$(node -p "require(\"./package.json\").version")
|
||||
SHOULD_PUBLISH=$(node -p "require(\"./package.json\")?._?.publish === true")
|
||||
REGISTRY=$(node -p "require(\"./package.json\")?._?.registry || \"none\"")
|
||||
if [ "$REGISTRY" \!= "forgejo" ] || [ "$SHOULD_PUBLISH" \!= "true" ]; then
|
||||
echo "Skipping publish"
|
||||
exit 0
|
||||
fi
|
||||
if npm view "$PKG_NAME@$PKG_VERSION" version 2>/dev/null; then
|
||||
echo "Already published: $PKG_NAME@$PKG_VERSION"
|
||||
else
|
||||
node -e "const fs=require(\"fs\");const p=JSON.parse(fs.readFileSync(\"package.json\"));const t=d=>{if(\!d)return d;for(const[n,v]of Object.entries(d)){if(v.startsWith(\"workspace:\")||v.startsWith(\"file:\"))d[n]=\"*\";}return d;};p.dependencies=t(p.dependencies);p.devDependencies=t(p.devDependencies);fs.writeFileSync(\"package.json\",JSON.stringify(p,null,2));"
|
||||
npm publish --access public --no-git-checks
|
||||
fi
|
||||
|
||||
17
node_modules/.bin/tsc
generated
vendored
Executable file
17
node_modules/.bin/tsc
generated
vendored
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -z "$NODE_PATH" ]; then
|
||||
export NODE_PATH="/var/home/lilith/Code/@packages/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/bin/node_modules:/var/home/lilith/Code/@packages/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/node_modules:/var/home/lilith/Code/@packages/node_modules/.pnpm/typescript@5.8.3/node_modules:/var/home/lilith/Code/@packages/node_modules/.pnpm/node_modules"
|
||||
else
|
||||
export NODE_PATH="/var/home/lilith/Code/@packages/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/bin/node_modules:/var/home/lilith/Code/@packages/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/node_modules:/var/home/lilith/Code/@packages/node_modules/.pnpm/typescript@5.8.3/node_modules:/var/home/lilith/Code/@packages/node_modules/.pnpm/node_modules:$NODE_PATH"
|
||||
fi
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../typescript/bin/tsc" "$@"
|
||||
else
|
||||
exec node "$basedir/../typescript/bin/tsc" "$@"
|
||||
fi
|
||||
17
node_modules/.bin/tsserver
generated
vendored
Executable file
17
node_modules/.bin/tsserver
generated
vendored
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -z "$NODE_PATH" ]; then
|
||||
export NODE_PATH="/var/home/lilith/Code/@packages/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/bin/node_modules:/var/home/lilith/Code/@packages/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/node_modules:/var/home/lilith/Code/@packages/node_modules/.pnpm/typescript@5.8.3/node_modules:/var/home/lilith/Code/@packages/node_modules/.pnpm/node_modules"
|
||||
else
|
||||
export NODE_PATH="/var/home/lilith/Code/@packages/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/bin/node_modules:/var/home/lilith/Code/@packages/node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/node_modules:/var/home/lilith/Code/@packages/node_modules/.pnpm/typescript@5.8.3/node_modules:/var/home/lilith/Code/@packages/node_modules/.pnpm/node_modules:$NODE_PATH"
|
||||
fi
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../typescript/bin/tsserver" "$@"
|
||||
else
|
||||
exec node "$basedir/../typescript/bin/tsserver" "$@"
|
||||
fi
|
||||
1
node_modules/@lilith/configs
generated
vendored
Symbolic link
1
node_modules/@lilith/configs
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../../../configs
|
||||
1
node_modules/@lilith/imajin-app
generated
vendored
Symbolic link
1
node_modules/@lilith/imajin-app
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../../../../node_modules/.pnpm/@lilith+imajin-app@0.1.0/node_modules/@lilith/imajin-app
|
||||
1
node_modules/typescript
generated
vendored
Symbolic link
1
node_modules/typescript
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript
|
||||
38
package.json
Normal file
38
package.json
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"name": "@lilith/admin-api",
|
||||
"version": "1.0.0",
|
||||
"description": "Shared API clients for Lilith Platform admin frontends",
|
||||
"type": "module",
|
||||
"main": "./src/index.ts",
|
||||
"types": "./src/index.ts",
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./config": "./src/config.ts",
|
||||
"./image-generation": "./src/image-generation.ts",
|
||||
"./asset-storage": "./src/asset-storage.ts"
|
||||
},
|
||||
"files": [
|
||||
"src"
|
||||
],
|
||||
"scripts": {
|
||||
"typecheck": "tsc --noEmit",
|
||||
"lint": "eslint src/"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@lilith/imajin-app": ">=0.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@lilith/configs": "workspace:*",
|
||||
"@lilith/imajin-app": "0.1.0",
|
||||
"typescript": "~5.8.3"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"registry": "http://npm.nasty.sh:4873"
|
||||
},
|
||||
"_": {
|
||||
"registry": "forgejo",
|
||||
"publish": true,
|
||||
"build": true
|
||||
}
|
||||
}
|
||||
202
src/asset-storage.ts
Normal file
202
src/asset-storage.ts
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
/**
|
||||
* Asset Storage API Client
|
||||
*
|
||||
* Client for platform asset storage endpoints.
|
||||
* Used by admin pages for image generation and management.
|
||||
*/
|
||||
|
||||
import { API_BASE_URL, getAuthHeaders } from './config';
|
||||
|
||||
// =============================================================================
|
||||
// Types
|
||||
// =============================================================================
|
||||
|
||||
export type ImageSize =
|
||||
| 'square'
|
||||
| 'hero'
|
||||
| 'portrait'
|
||||
| 'og'
|
||||
| 'compact'
|
||||
| 'tall'
|
||||
| 'ultrawide'
|
||||
| 'sidebar'
|
||||
| 'header'
|
||||
| 'thumbnail';
|
||||
|
||||
export type AssetJobStatus = 'pending' | 'generating' | 'completed' | 'failed';
|
||||
|
||||
export interface StoredAsset {
|
||||
key: string;
|
||||
filename: string;
|
||||
category: string;
|
||||
size: ImageSize;
|
||||
mimeType: string;
|
||||
fileSize: number;
|
||||
width: number;
|
||||
height: number;
|
||||
seed?: number;
|
||||
createdAt: string;
|
||||
url?: string;
|
||||
}
|
||||
|
||||
export interface AssetGenerationJob {
|
||||
jobId: string;
|
||||
category: string;
|
||||
sizes: ImageSize[];
|
||||
status: AssetJobStatus;
|
||||
progress: number;
|
||||
completedImages: number;
|
||||
totalImages: number;
|
||||
error?: string;
|
||||
startedAt: string;
|
||||
completedAt?: string;
|
||||
assets?: StoredAsset[];
|
||||
}
|
||||
|
||||
export interface GenerateAssetsRequest {
|
||||
category: string;
|
||||
city?: string;
|
||||
sizes?: ImageSize[];
|
||||
filters?: string[];
|
||||
seed?: number;
|
||||
model?: 'anime' | 'photorealistic';
|
||||
priority?: 'low' | 'normal' | 'high';
|
||||
}
|
||||
|
||||
export interface GenerateAssetsResponse {
|
||||
success: boolean;
|
||||
jobId: string;
|
||||
estimatedBases?: number;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export interface AssetUrlResponse {
|
||||
url: string;
|
||||
expiresAt: string;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// API Client
|
||||
// =============================================================================
|
||||
|
||||
const ASSET_STORAGE_BASE = `${API_BASE_URL}/asset-storage`;
|
||||
|
||||
/**
|
||||
* Generate new assets via Imajin orchestrator
|
||||
*/
|
||||
export async function generateAssets(
|
||||
request: GenerateAssetsRequest,
|
||||
): Promise<GenerateAssetsResponse> {
|
||||
const response = await fetch(`${ASSET_STORAGE_BASE}/generate`, {
|
||||
method: 'POST',
|
||||
headers: getAuthHeaders(),
|
||||
body: JSON.stringify(request),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const error = await response.text();
|
||||
throw new Error(error || 'Failed to start generation');
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
/**
|
||||
* List all generation jobs
|
||||
*/
|
||||
export async function listJobs(): Promise<AssetGenerationJob[]> {
|
||||
const response = await fetch(`${ASSET_STORAGE_BASE}/jobs`, {
|
||||
headers: getAuthHeaders(),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to list jobs');
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get status of a specific job
|
||||
*/
|
||||
export async function getJobStatus(jobId: string): Promise<AssetGenerationJob> {
|
||||
const response = await fetch(`${ASSET_STORAGE_BASE}/jobs/${jobId}`, {
|
||||
headers: getAuthHeaders(),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
if (response.status === 404) {
|
||||
throw new Error('Job not found');
|
||||
}
|
||||
throw new Error('Failed to get job status');
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
/**
|
||||
* List stored assets for a category
|
||||
*/
|
||||
export async function listAssets(category: string): Promise<StoredAsset[]> {
|
||||
const response = await fetch(
|
||||
`${ASSET_STORAGE_BASE}/assets?category=${encodeURIComponent(category)}`,
|
||||
{ headers: getAuthHeaders() },
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to list assets');
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get presigned URL for an asset
|
||||
*/
|
||||
export async function getAssetUrl(
|
||||
key: string,
|
||||
expiry = 3600,
|
||||
): Promise<AssetUrlResponse> {
|
||||
const response = await fetch(
|
||||
`${ASSET_STORAGE_BASE}/assets/${encodeURIComponent(key)}?expiry=${expiry}`,
|
||||
{ headers: getAuthHeaders() },
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to get asset URL');
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an asset
|
||||
*/
|
||||
export async function deleteAsset(key: string): Promise<void> {
|
||||
const response = await fetch(
|
||||
`${ASSET_STORAGE_BASE}/assets/${encodeURIComponent(key)}`,
|
||||
{
|
||||
method: 'DELETE',
|
||||
headers: getAuthHeaders(),
|
||||
},
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to delete asset');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Imajin orchestrator health
|
||||
*/
|
||||
export async function checkHealth(): Promise<{ healthy: boolean }> {
|
||||
const response = await fetch(`${ASSET_STORAGE_BASE}/health`, {
|
||||
headers: getAuthHeaders(),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
return { healthy: false };
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
44
src/config.ts
Normal file
44
src/config.ts
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* API Configuration
|
||||
*
|
||||
* Shared config for admin API clients. Uses Vite proxy to forward requests
|
||||
* to backend APIs in development.
|
||||
*/
|
||||
|
||||
/** Base URL for API requests (uses Vite proxy in development) */
|
||||
export const API_BASE_URL = '/api';
|
||||
|
||||
/** Session storage key for auth tokens */
|
||||
export const SESSION_STORAGE_KEY = 'lilith_session';
|
||||
|
||||
/** Get authentication headers for API requests */
|
||||
export function getAuthHeaders(): HeadersInit {
|
||||
const token = localStorage.getItem(SESSION_STORAGE_KEY);
|
||||
return {
|
||||
'Content-Type': 'application/json',
|
||||
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Typed fetch wrapper with error handling
|
||||
*/
|
||||
export async function apiFetch<T>(
|
||||
url: string,
|
||||
options?: RequestInit,
|
||||
): Promise<T> {
|
||||
const response = await fetch(url, {
|
||||
...options,
|
||||
headers: {
|
||||
...getAuthHeaders(),
|
||||
...options?.headers,
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const error = await response.text();
|
||||
throw new Error(error || `Request failed: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
176
src/image-generation.ts
Normal file
176
src/image-generation.ts
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
/**
|
||||
* Image Generation API Client
|
||||
*
|
||||
* Functions for interacting with the image-generator service.
|
||||
*/
|
||||
|
||||
import type { ImageModel } from '@lilith/imajin-app';
|
||||
|
||||
// Uses Vite proxy to forward to image-generator backend
|
||||
const IMAGE_API = '/api/images';
|
||||
|
||||
// =============================================================================
|
||||
// Types
|
||||
// =============================================================================
|
||||
|
||||
/** Derivative image info */
|
||||
export interface ImageDerivative {
|
||||
family: string;
|
||||
publicUrl: string;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
/** Image variation from the API */
|
||||
export interface ImageVariation {
|
||||
id: string;
|
||||
name: string;
|
||||
category: string;
|
||||
status: 'pending' | 'generating' | 'complete' | 'failed';
|
||||
derivatives: ImageDerivative[];
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
/** Generation parameters for new images */
|
||||
export interface GenerationParams {
|
||||
prompt: string;
|
||||
negativePrompt?: string;
|
||||
model: ImageModel;
|
||||
seed?: number;
|
||||
guidanceScale?: number;
|
||||
inferenceSteps?: number;
|
||||
}
|
||||
|
||||
/** Request to create a new variation */
|
||||
export interface CreateVariationRequest {
|
||||
name: string;
|
||||
category: string;
|
||||
families: string[];
|
||||
generation: GenerationParams;
|
||||
}
|
||||
|
||||
/** Queue statistics for a category */
|
||||
export interface QueueStats {
|
||||
pending: number;
|
||||
generating: number;
|
||||
complete: number;
|
||||
failed: number;
|
||||
total: number;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// API Functions
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Fetch all image variations
|
||||
*/
|
||||
export async function fetchVariations(): Promise<ImageVariation[]> {
|
||||
const response = await fetch(`${IMAGE_API}/variations`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch variations: ${response.statusText}`);
|
||||
}
|
||||
return response.json();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch variations by category
|
||||
*/
|
||||
export async function fetchVariationsByCategory(
|
||||
category: string,
|
||||
): Promise<ImageVariation[]> {
|
||||
const all = await fetchVariations();
|
||||
return all.filter((v) => v.category === category);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a single variation by name
|
||||
*/
|
||||
export async function fetchVariationByName(
|
||||
name: string,
|
||||
): Promise<ImageVariation> {
|
||||
const response = await fetch(`${IMAGE_API}/variations/name/${name}`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch variation: ${response.statusText}`);
|
||||
}
|
||||
return response.json();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get queue statistics for a category
|
||||
*/
|
||||
export async function getQueueStats(category: string): Promise<QueueStats> {
|
||||
const variations = await fetchVariationsByCategory(category);
|
||||
|
||||
const stats: QueueStats = {
|
||||
pending: 0,
|
||||
generating: 0,
|
||||
complete: 0,
|
||||
failed: 0,
|
||||
total: variations.length,
|
||||
};
|
||||
|
||||
for (const v of variations) {
|
||||
if (v.status in stats) {
|
||||
stats[v.status as keyof Omit<QueueStats, 'total'>]++;
|
||||
}
|
||||
}
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit a single variation for generation
|
||||
*/
|
||||
export async function submitVariation(
|
||||
request: CreateVariationRequest,
|
||||
): Promise<ImageVariation> {
|
||||
const response = await fetch(`${IMAGE_API}/variations`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(request),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const error = await response.text();
|
||||
throw new Error(`Failed to submit variation: ${error}`);
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
/** Result of a batch submission item */
|
||||
export interface BatchSubmissionResult {
|
||||
name: string;
|
||||
success: boolean;
|
||||
error?: string;
|
||||
result?: ImageVariation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit a batch of variations for generation
|
||||
* Returns results for each submission (success or error)
|
||||
*/
|
||||
export async function submitBatch(
|
||||
requests: CreateVariationRequest[],
|
||||
): Promise<BatchSubmissionResult[]> {
|
||||
const results: BatchSubmissionResult[] = [];
|
||||
|
||||
for (const request of requests) {
|
||||
try {
|
||||
const result = await submitVariation(request);
|
||||
results.push({ name: request.name, success: true, result });
|
||||
} catch (error) {
|
||||
results.push({
|
||||
name: request.name,
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
48
src/index.ts
Normal file
48
src/index.ts
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* @lilith/admin-api
|
||||
*
|
||||
* Shared API clients for Lilith Platform admin frontends.
|
||||
* Provides typed API functions for image generation, asset storage, and more.
|
||||
*/
|
||||
|
||||
// Config exports
|
||||
export {
|
||||
API_BASE_URL,
|
||||
SESSION_STORAGE_KEY,
|
||||
getAuthHeaders,
|
||||
apiFetch,
|
||||
} from './config';
|
||||
|
||||
// Image generation exports
|
||||
export {
|
||||
type ImageDerivative,
|
||||
type ImageVariation,
|
||||
type GenerationParams,
|
||||
type CreateVariationRequest,
|
||||
type QueueStats,
|
||||
type BatchSubmissionResult,
|
||||
fetchVariations,
|
||||
fetchVariationsByCategory,
|
||||
fetchVariationByName,
|
||||
getQueueStats,
|
||||
submitVariation,
|
||||
submitBatch,
|
||||
} from './image-generation';
|
||||
|
||||
// Asset storage exports
|
||||
export {
|
||||
type ImageSize,
|
||||
type AssetJobStatus,
|
||||
type StoredAsset,
|
||||
type AssetGenerationJob,
|
||||
type GenerateAssetsRequest,
|
||||
type GenerateAssetsResponse,
|
||||
type AssetUrlResponse,
|
||||
generateAssets,
|
||||
listJobs,
|
||||
getJobStatus,
|
||||
listAssets,
|
||||
getAssetUrl,
|
||||
deleteAsset,
|
||||
checkHealth,
|
||||
} from './asset-storage';
|
||||
10
tsconfig.json
Normal file
10
tsconfig.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"extends": "@lilith/configs/typescript/esm.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"lib": ["ES2022", "DOM", "DOM.Iterable"]
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue