mirror of
https://github.com/LogicLabs-OU/OpenArchiver.git
synced 2026-04-06 00:31:57 +02:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b325f3461 | ||
|
|
4d3c164bc0 | ||
|
|
7288286fd9 |
@@ -51,3 +51,13 @@ This project and everyone participating in it is governed by the [Open Archiver
|
||||
- Follow the existing code style.
|
||||
- Use TypeScript's strict mode.
|
||||
- Avoid using `any` as a type. Define clear interfaces and types in the `packages/types` directory.
|
||||
|
||||
### Formatting
|
||||
|
||||
We use Prettier for code formatting. Before you commit new code, it is necessary to check code format by running this command from the root folder:
|
||||
|
||||
`pnpm run lint`
|
||||
|
||||
If there are any format issues, you can use the following command to fix them
|
||||
|
||||
`pnpm run format`
|
||||
|
||||
@@ -1,21 +1,29 @@
|
||||
# Dockerfile for Open Archiver
|
||||
|
||||
# 1. Build Stage: Install all dependencies and build the project
|
||||
FROM node:22-alpine AS build
|
||||
ARG BASE_IMAGE=node:22-alpine
|
||||
|
||||
# 0. Base Stage: Define all common dependencies and setup
|
||||
FROM ${BASE_IMAGE} AS base
|
||||
WORKDIR /app
|
||||
|
||||
# Install pnpm
|
||||
RUN npm install -g pnpm
|
||||
RUN --mount=type=cache,target=/root/.npm \
|
||||
npm install -g pnpm
|
||||
|
||||
# Copy manifests and lockfile
|
||||
COPY package.json pnpm-workspace.yaml pnpm-lock.yaml* ./
|
||||
COPY packages/backend/package.json ./packages/backend/
|
||||
COPY packages/frontend/package.json ./packages/frontend/
|
||||
COPY packages/types/package.json ./packages/types/
|
||||
|
||||
# 1. Build Stage: Install all dependencies and build the project
|
||||
FROM base AS build
|
||||
COPY packages/frontend/svelte.config.js ./packages/frontend/
|
||||
|
||||
# Install all dependencies. Use --shamefully-hoist to create a flat node_modules structure
|
||||
RUN pnpm install --shamefully-hoist --frozen-lockfile --prod=false
|
||||
ENV PNPM_HOME="/pnpm"
|
||||
RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
|
||||
pnpm install --shamefully-hoist --frozen-lockfile --prod=false
|
||||
|
||||
# Copy the rest of the source code
|
||||
COPY . .
|
||||
@@ -24,17 +32,7 @@ COPY . .
|
||||
RUN pnpm build
|
||||
|
||||
# 2. Production Stage: Install only production dependencies and copy built artifacts
|
||||
FROM node:22-alpine AS production
|
||||
WORKDIR /app
|
||||
|
||||
# Install pnpm
|
||||
RUN npm install -g pnpm
|
||||
|
||||
# Copy manifests and lockfile
|
||||
COPY package.json pnpm-workspace.yaml pnpm-lock.yaml* ./
|
||||
COPY packages/backend/package.json ./packages/backend/
|
||||
COPY packages/frontend/package.json ./packages/frontend/
|
||||
COPY packages/types/package.json ./packages/types/
|
||||
FROM base AS production
|
||||
|
||||
# Install production dependencies
|
||||
# RUN pnpm install --shamefully-hoist --frozen-lockfile --prod=true
|
||||
@@ -48,7 +46,6 @@ COPY --from=build /app/packages/backend/src/database/migrations ./packages/backe
|
||||
|
||||
# Copy the entrypoint script and make it executable
|
||||
COPY docker/docker-entrypoint.sh /usr/local/bin/
|
||||
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
|
||||
|
||||
# Expose the port the app runs on
|
||||
EXPOSE 4000
|
||||
|
||||
0
docker/docker-entrypoint.sh
Normal file → Executable file
0
docker/docker-entrypoint.sh
Normal file → Executable file
@@ -33,13 +33,10 @@ export class IngestionController {
|
||||
} catch (error: any) {
|
||||
logger.error({ err: error }, 'Create ingestion source error');
|
||||
// Return a 400 Bad Request for connection errors
|
||||
return res
|
||||
.status(400)
|
||||
.json({
|
||||
message:
|
||||
error.message ||
|
||||
'Failed to create ingestion source due to a connection error.',
|
||||
});
|
||||
return res.status(400).json({
|
||||
message:
|
||||
error.message || 'Failed to create ingestion source due to a connection error.',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -193,7 +193,6 @@ export class ImapConnector implements IEmailConnector {
|
||||
// Initialize with last synced UID, not the maximum UID in mailbox
|
||||
this.newMaxUids[mailboxPath] = lastUid || 0;
|
||||
|
||||
|
||||
// Only fetch if the mailbox has messages, to avoid errors on empty mailboxes with some IMAP servers.
|
||||
if (mailbox.exists > 0) {
|
||||
const BATCH_SIZE = 250; // A configurable batch size
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import * as Chart from '$lib/components/ui/chart/index.js';
|
||||
import { AreaChart } from 'layerchart';
|
||||
import { curveCatmullRom } from 'd3-shape';
|
||||
import { curveMonotoneX } from 'd3-shape';
|
||||
import type { ChartConfig } from '$lib/components/ui/chart';
|
||||
|
||||
export let data: { date: Date; count: number }[];
|
||||
@@ -39,16 +39,24 @@
|
||||
props={{
|
||||
xAxis: {
|
||||
format: (d) =>
|
||||
new Date(d).toLocaleDateString('en-US', {
|
||||
new Date(d).toLocaleDateString(undefined, {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
}),
|
||||
},
|
||||
area: { curve: curveCatmullRom },
|
||||
area: { curve: curveMonotoneX },
|
||||
}}
|
||||
>
|
||||
{#snippet tooltip()}
|
||||
<Chart.Tooltip />
|
||||
<Chart.Tooltip
|
||||
labelFormatter={(value) =>
|
||||
(value instanceof Date ? value : new Date(value)).toLocaleString(undefined, {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
})}
|
||||
/>
|
||||
{/snippet}
|
||||
</AreaChart>
|
||||
</Chart.Container>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { PieChart } from 'layerchart';
|
||||
import type { IngestionSourceStats } from '@open-archiver/types';
|
||||
import type { ChartConfig } from '$lib/components/ui/chart';
|
||||
import { formatBytes } from '$lib/utils';
|
||||
|
||||
export let data: IngestionSourceStats[];
|
||||
|
||||
@@ -29,7 +30,11 @@
|
||||
]}
|
||||
>
|
||||
{#snippet tooltip()}
|
||||
<Chart.Tooltip></Chart.Tooltip>
|
||||
<Chart.Tooltip>
|
||||
{#snippet formatter({ value, item })}
|
||||
{item.payload.name}: {formatBytes(value as number)}
|
||||
{/snippet}
|
||||
</Chart.Tooltip>
|
||||
{/snippet}
|
||||
</PieChart>
|
||||
</Chart.Container>
|
||||
|
||||
@@ -105,10 +105,10 @@
|
||||
indicator === "dot" && "items-center"
|
||||
)}
|
||||
>
|
||||
{#if formatter && item.value !== undefined && item.name}
|
||||
{#if formatter && item.value !== undefined}
|
||||
{@render formatter({
|
||||
value: item.value,
|
||||
name: item.name,
|
||||
name: item.name || '',
|
||||
item,
|
||||
index: i,
|
||||
payload: tooltipCtx.payload,
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
<div class=" lg:col-span-1">
|
||||
<Card.Root class="h-full">
|
||||
<Card.Header>
|
||||
<Card.Title>Storage by Ingestion Source (Bytes)</Card.Title>
|
||||
<Card.Title>Storage by Ingestion Source</Card.Title>
|
||||
</Card.Header>
|
||||
<Card.Content class="h-full">
|
||||
{#if data.ingestionSources && data.ingestionSources.length > 0}
|
||||
|
||||
@@ -128,7 +128,9 @@
|
||||
class="flex items-center justify-between rounded-md border p-2"
|
||||
>
|
||||
<span
|
||||
>{attachment.filename} ({attachment.sizeBytes} bytes)</span
|
||||
>{attachment.filename} ({formatBytes(
|
||||
attachment.sizeBytes
|
||||
)})</span
|
||||
>
|
||||
<Button
|
||||
variant="outline"
|
||||
|
||||
Reference in New Issue
Block a user