feat: add storage system with local disk and S3 providers
Introduces a provider-agnostic storage subsystem for file attachments. Includes local disk and S3 backends, asset/attachment DB schemas, issue attachment CRUD routes with multer upload, CLI configure/doctor/env integration, and enriched issue ancestors with project/goal resolution. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { z } from "zod";
|
||||
import { SECRET_PROVIDERS } from "./constants.js";
|
||||
import { SECRET_PROVIDERS, STORAGE_PROVIDERS } from "./constants.js";
|
||||
|
||||
export const configMetaSchema = z.object({
|
||||
version: z.literal(1),
|
||||
@@ -29,6 +29,31 @@ export const serverConfigSchema = z.object({
|
||||
serveUi: z.boolean().default(true),
|
||||
});
|
||||
|
||||
export const storageLocalDiskConfigSchema = z.object({
|
||||
baseDir: z.string().default("~/.paperclip/instances/default/data/storage"),
|
||||
});
|
||||
|
||||
export const storageS3ConfigSchema = z.object({
|
||||
bucket: z.string().min(1).default("paperclip"),
|
||||
region: z.string().min(1).default("us-east-1"),
|
||||
endpoint: z.string().optional(),
|
||||
prefix: z.string().default(""),
|
||||
forcePathStyle: z.boolean().default(false),
|
||||
});
|
||||
|
||||
export const storageConfigSchema = z.object({
|
||||
provider: z.enum(STORAGE_PROVIDERS).default("local_disk"),
|
||||
localDisk: storageLocalDiskConfigSchema.default({
|
||||
baseDir: "~/.paperclip/instances/default/data/storage",
|
||||
}),
|
||||
s3: storageS3ConfigSchema.default({
|
||||
bucket: "paperclip",
|
||||
region: "us-east-1",
|
||||
prefix: "",
|
||||
forcePathStyle: false,
|
||||
}),
|
||||
});
|
||||
|
||||
export const secretsLocalEncryptedConfigSchema = z.object({
|
||||
keyFilePath: z.string().default("~/.paperclip/instances/default/secrets/master.key"),
|
||||
});
|
||||
@@ -47,6 +72,18 @@ export const paperclipConfigSchema = z.object({
|
||||
database: databaseConfigSchema,
|
||||
logging: loggingConfigSchema,
|
||||
server: serverConfigSchema,
|
||||
storage: storageConfigSchema.default({
|
||||
provider: "local_disk",
|
||||
localDisk: {
|
||||
baseDir: "~/.paperclip/instances/default/data/storage",
|
||||
},
|
||||
s3: {
|
||||
bucket: "paperclip",
|
||||
region: "us-east-1",
|
||||
prefix: "",
|
||||
forcePathStyle: false,
|
||||
},
|
||||
}),
|
||||
secrets: secretsConfigSchema.default({
|
||||
provider: "local_encrypted",
|
||||
strictMode: false,
|
||||
@@ -61,6 +98,9 @@ export type LlmConfig = z.infer<typeof llmConfigSchema>;
|
||||
export type DatabaseConfig = z.infer<typeof databaseConfigSchema>;
|
||||
export type LoggingConfig = z.infer<typeof loggingConfigSchema>;
|
||||
export type ServerConfig = z.infer<typeof serverConfigSchema>;
|
||||
export type StorageConfig = z.infer<typeof storageConfigSchema>;
|
||||
export type StorageLocalDiskConfig = z.infer<typeof storageLocalDiskConfigSchema>;
|
||||
export type StorageS3Config = z.infer<typeof storageS3ConfigSchema>;
|
||||
export type SecretsConfig = z.infer<typeof secretsConfigSchema>;
|
||||
export type SecretsLocalEncryptedConfig = z.infer<typeof secretsLocalEncryptedConfigSchema>;
|
||||
export type ConfigMeta = z.infer<typeof configMetaSchema>;
|
||||
|
||||
Reference in New Issue
Block a user