mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-05 12:29:44 +08:00
refactor(ocr): restructure ocr types into modular files for better maintainability
- Split monolithic ocr.ts into separate files for base types, providers, models, and layers (api, data, business) - Update related imports and references across the codebase - Rename API request/response types to be more consistent (Patch->Update, Put->Replace) - Adjust repository and service implementations to match new type structure
This commit is contained in:
parent
327d0dab7f
commit
e0781e1bb0
@ -7,10 +7,10 @@ import type {
|
|||||||
ListOcrProvidersQuery,
|
ListOcrProvidersQuery,
|
||||||
ListOcrProvidersResponse,
|
ListOcrProvidersResponse,
|
||||||
OcrProviderId,
|
OcrProviderId,
|
||||||
PatchOcrProviderRequest,
|
ReplaceOcrProviderRequest,
|
||||||
PatchOcrProviderResponse,
|
ReplaceOcrProviderResponse,
|
||||||
PutOcrProviderRequest,
|
UpdateOcrProviderRequest,
|
||||||
PutOcrProviderResponse
|
UpdateOcrProviderResponse
|
||||||
} from '@types'
|
} from '@types'
|
||||||
|
|
||||||
import type { BodyForPath, ConcreteApiPaths, QueryParamsForPath, ResponseForPath } from './apiPaths'
|
import type { BodyForPath, ConcreteApiPaths, QueryParamsForPath, ResponseForPath } from './apiPaths'
|
||||||
@ -377,13 +377,13 @@ export interface ApiSchemas {
|
|||||||
}
|
}
|
||||||
PATCH: {
|
PATCH: {
|
||||||
params: { id: OcrProviderId }
|
params: { id: OcrProviderId }
|
||||||
body: PatchOcrProviderRequest
|
body: UpdateOcrProviderRequest
|
||||||
response: PatchOcrProviderResponse
|
response: UpdateOcrProviderResponse
|
||||||
}
|
}
|
||||||
PUT: {
|
PUT: {
|
||||||
params: { id: OcrProviderId }
|
params: { id: OcrProviderId }
|
||||||
body: PutOcrProviderRequest
|
body: ReplaceOcrProviderRequest
|
||||||
response: PutOcrProviderResponse
|
response: ReplaceOcrProviderResponse
|
||||||
}
|
}
|
||||||
DELETE: {
|
DELETE: {
|
||||||
params: { id: OcrProviderId }
|
params: { id: OcrProviderId }
|
||||||
|
|||||||
@ -2,16 +2,12 @@ import { dbService } from '@data/db/DbService'
|
|||||||
import { ocrProviderTable } from '@data/db/schemas/ocr/provider'
|
import { ocrProviderTable } from '@data/db/schemas/ocr/provider'
|
||||||
import { loggerService } from '@logger'
|
import { loggerService } from '@logger'
|
||||||
import type {
|
import type {
|
||||||
CreateOcrProviderRequest,
|
|
||||||
CreateOcrProviderResponse,
|
|
||||||
DbOcrProvider,
|
DbOcrProvider,
|
||||||
ListOcrProvidersQuery,
|
DbOcrProviderCreate,
|
||||||
ListOcrProvidersResponse,
|
DbOcrProviderReplace,
|
||||||
|
DbOcrProviderUpdate,
|
||||||
OcrProviderId,
|
OcrProviderId,
|
||||||
PatchOcrProviderRequest,
|
UpdateOcrProviderResponse
|
||||||
PatchOcrProviderResponse,
|
|
||||||
PutOcrProviderRequest,
|
|
||||||
PutOcrProviderResponse
|
|
||||||
} from '@types'
|
} from '@types'
|
||||||
import { BuiltinOcrProviderIds, isDbOcrProvider } from '@types'
|
import { BuiltinOcrProviderIds, isDbOcrProvider } from '@types'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
@ -28,17 +24,11 @@ export class OcrProviderRepository {
|
|||||||
/**
|
/**
|
||||||
* Get all OCR providers
|
* Get all OCR providers
|
||||||
*/
|
*/
|
||||||
public async findAll(query?: ListOcrProvidersQuery): Promise<ListOcrProvidersResponse> {
|
public async findAll(): Promise<DbOcrProvider[]> {
|
||||||
try {
|
try {
|
||||||
const providers = await dbService.getDb().select().from(ocrProviderTable)
|
const providers = await dbService.getDb().select().from(ocrProviderTable)
|
||||||
|
|
||||||
if (query?.registered) {
|
return providers
|
||||||
// Filter by registered providers (this would need to be implemented)
|
|
||||||
// For now, return all providers
|
|
||||||
return { data: providers }
|
|
||||||
}
|
|
||||||
|
|
||||||
return { data: providers }
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('Failed to find all OCR providers', error as Error)
|
logger.error('Failed to find all OCR providers', error as Error)
|
||||||
throw error
|
throw error
|
||||||
@ -90,16 +80,16 @@ export class OcrProviderRepository {
|
|||||||
/**
|
/**
|
||||||
* Create new OCR provider
|
* Create new OCR provider
|
||||||
*/
|
*/
|
||||||
public async create(data: CreateOcrProviderRequest): Promise<CreateOcrProviderResponse> {
|
public async create(param: DbOcrProviderCreate): Promise<DbOcrProvider> {
|
||||||
try {
|
try {
|
||||||
// Check if provider already exists
|
// Check if provider already exists
|
||||||
if (await this.exists(data.id)) {
|
if (await this.exists(param.id)) {
|
||||||
throw new Error(`OCR provider ${data.id} already exists`)
|
throw new Error(`OCR provider ${param.id} already exists`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const timestamp = dayjs().valueOf()
|
const timestamp = dayjs().valueOf()
|
||||||
const newProvider = {
|
const newProvider = {
|
||||||
...data,
|
...param,
|
||||||
createdAt: timestamp,
|
createdAt: timestamp,
|
||||||
updatedAt: timestamp
|
updatedAt: timestamp
|
||||||
} satisfies DbOcrProvider
|
} satisfies DbOcrProvider
|
||||||
@ -111,10 +101,10 @@ export class OcrProviderRepository {
|
|||||||
|
|
||||||
const [created] = await dbService.getDb().insert(ocrProviderTable).values(newProvider).returning()
|
const [created] = await dbService.getDb().insert(ocrProviderTable).values(newProvider).returning()
|
||||||
|
|
||||||
logger.info(`Created OCR provider: ${data.id}`)
|
logger.info(`Created OCR provider: ${param.id}`)
|
||||||
return { data: created }
|
return created
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`Failed to create OCR provider ${data.id}`, error as Error)
|
logger.error(`Failed to create OCR provider ${param.id}`, error as Error)
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,12 +112,12 @@ export class OcrProviderRepository {
|
|||||||
/**
|
/**
|
||||||
* Update OCR provider (partial update)
|
* Update OCR provider (partial update)
|
||||||
*/
|
*/
|
||||||
public async update(id: OcrProviderId, data: Partial<PatchOcrProviderRequest>): Promise<PatchOcrProviderResponse> {
|
public async update(id: OcrProviderId, update: DbOcrProviderUpdate): Promise<UpdateOcrProviderResponse> {
|
||||||
try {
|
try {
|
||||||
const existing = await this.findById(id)
|
const existing = await this.findById(id)
|
||||||
|
|
||||||
const newProvider = {
|
const newProvider = {
|
||||||
...merge({}, existing, data),
|
...merge({}, existing, update),
|
||||||
updatedAt: dayjs().valueOf()
|
updatedAt: dayjs().valueOf()
|
||||||
} satisfies DbOcrProvider
|
} satisfies DbOcrProvider
|
||||||
|
|
||||||
@ -154,7 +144,7 @@ export class OcrProviderRepository {
|
|||||||
/**
|
/**
|
||||||
* Replace OCR provider (full update)
|
* Replace OCR provider (full update)
|
||||||
*/
|
*/
|
||||||
public async replace(data: PutOcrProviderRequest): Promise<PutOcrProviderResponse> {
|
public async replace(data: DbOcrProviderReplace): Promise<DbOcrProvider> {
|
||||||
try {
|
try {
|
||||||
// Check if it's a built-in provider
|
// Check if it's a built-in provider
|
||||||
if (BuiltinOcrProviderIds.some((pid) => pid === data.id)) {
|
if (BuiltinOcrProviderIds.some((pid) => pid === data.id)) {
|
||||||
@ -199,7 +189,7 @@ export class OcrProviderRepository {
|
|||||||
.returning()
|
.returning()
|
||||||
|
|
||||||
logger.info(`Replaced OCR provider: ${data.id}`)
|
logger.info(`Replaced OCR provider: ${data.id}`)
|
||||||
return { data: saved }
|
return saved
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`Failed to replace OCR provider ${data.id}`, error as Error)
|
logger.error(`Failed to replace OCR provider ${data.id}`, error as Error)
|
||||||
throw error
|
throw error
|
||||||
|
|||||||
@ -4,17 +4,18 @@ import type {
|
|||||||
CreateOcrProviderRequest,
|
CreateOcrProviderRequest,
|
||||||
CreateOcrProviderResponse,
|
CreateOcrProviderResponse,
|
||||||
DbOcrProvider,
|
DbOcrProvider,
|
||||||
|
GetOcrProviderResponse,
|
||||||
ListOcrProvidersQuery,
|
ListOcrProvidersQuery,
|
||||||
ListOcrProvidersResponse,
|
ListOcrProvidersResponse,
|
||||||
OcrParams,
|
OcrParams,
|
||||||
OcrProvider,
|
OcrProvider,
|
||||||
OcrProviderId,
|
OcrProviderKeyBusiness,
|
||||||
OcrResult,
|
OcrResult,
|
||||||
PatchOcrProviderRequest,
|
ReplaceOcrProviderRequest,
|
||||||
PatchOcrProviderResponse,
|
ReplaceOcrProviderResponse,
|
||||||
PutOcrProviderRequest,
|
SupportedOcrFile,
|
||||||
PutOcrProviderResponse,
|
UpdateOcrProviderRequest,
|
||||||
SupportedOcrFile
|
UpdateOcrProviderResponse
|
||||||
} from '@types'
|
} from '@types'
|
||||||
import { BuiltinOcrProviderIdMap } from '@types'
|
import { BuiltinOcrProviderIdMap } from '@types'
|
||||||
|
|
||||||
@ -31,7 +32,7 @@ const logger = loggerService.withContext('OcrService')
|
|||||||
* Handles OCR provider registration, orchestration, and core OCR functionality
|
* Handles OCR provider registration, orchestration, and core OCR functionality
|
||||||
*/
|
*/
|
||||||
class OcrService {
|
class OcrService {
|
||||||
private registry: Map<OcrProviderId, OcrBaseService> = new Map()
|
private registry: Map<OcrProviderKeyBusiness, OcrBaseService> = new Map()
|
||||||
private initialized: boolean = false
|
private initialized: boolean = false
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -83,7 +84,7 @@ class OcrService {
|
|||||||
/**
|
/**
|
||||||
* Register an OCR provider service
|
* Register an OCR provider service
|
||||||
*/
|
*/
|
||||||
private register(providerId: OcrProviderId, service: OcrBaseService): void {
|
private register(providerId: OcrProviderKeyBusiness, service: OcrBaseService): void {
|
||||||
if (this.registry.has(providerId)) {
|
if (this.registry.has(providerId)) {
|
||||||
logger.warn(`Provider ${providerId} already registered. Overwriting.`)
|
logger.warn(`Provider ${providerId} already registered. Overwriting.`)
|
||||||
}
|
}
|
||||||
@ -104,14 +105,14 @@ class OcrService {
|
|||||||
/**
|
/**
|
||||||
* Get all registered provider IDs
|
* Get all registered provider IDs
|
||||||
*/
|
*/
|
||||||
public getRegisteredProviderIds(): OcrProviderId[] {
|
public getRegisteredProviderIds(): OcrProviderKeyBusiness[] {
|
||||||
return Array.from(this.registry.keys())
|
return Array.from(this.registry.keys())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a provider is registered
|
* Check if a provider is registered
|
||||||
*/
|
*/
|
||||||
public isProviderRegistered(providerId: OcrProviderId): boolean {
|
public isProviderRegistered(providerId: OcrProviderKeyBusiness): boolean {
|
||||||
return this.registry.has(providerId)
|
return this.registry.has(providerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,16 +122,17 @@ class OcrService {
|
|||||||
public async listProviders(query?: ListOcrProvidersQuery): Promise<ListOcrProvidersResponse> {
|
public async listProviders(query?: ListOcrProvidersQuery): Promise<ListOcrProvidersResponse> {
|
||||||
try {
|
try {
|
||||||
await this.ensureInitialized()
|
await this.ensureInitialized()
|
||||||
const result = await ocrProviderRepository.findAll(query)
|
const providers = await ocrProviderRepository.findAll()
|
||||||
|
|
||||||
|
let result = providers
|
||||||
if (query?.registered) {
|
if (query?.registered) {
|
||||||
// Filter by registered providers
|
// Filter by registered providers
|
||||||
const registeredIds = this.getRegisteredProviderIds()
|
const registeredIds = this.getRegisteredProviderIds()
|
||||||
result.data = result.data.filter((provider) => registeredIds.includes(provider.id))
|
result = providers.filter((provider) => registeredIds.includes(provider.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug(`Listed ${result.data.length} OCR providers`)
|
logger.debug(`Listed ${result.length} OCR providers`)
|
||||||
return result
|
return { data: result }
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('Failed to list OCR providers', error as Error)
|
logger.error('Failed to list OCR providers', error as Error)
|
||||||
throw error
|
throw error
|
||||||
@ -140,7 +142,7 @@ class OcrService {
|
|||||||
/**
|
/**
|
||||||
* Get OCR provider by ID
|
* Get OCR provider by ID
|
||||||
*/
|
*/
|
||||||
public async getProvider(providerId: OcrProviderId): Promise<{ data: DbOcrProvider }> {
|
public async getProvider(providerId: OcrProviderKeyBusiness): Promise<GetOcrProviderResponse> {
|
||||||
try {
|
try {
|
||||||
await this.ensureInitialized()
|
await this.ensureInitialized()
|
||||||
const provider = await ocrProviderRepository.findById(providerId)
|
const provider = await ocrProviderRepository.findById(providerId)
|
||||||
@ -160,7 +162,7 @@ class OcrService {
|
|||||||
await this.ensureInitialized()
|
await this.ensureInitialized()
|
||||||
const result = await ocrProviderRepository.create(data)
|
const result = await ocrProviderRepository.create(data)
|
||||||
logger.info(`Created OCR provider: ${data.id}`)
|
logger.info(`Created OCR provider: ${data.id}`)
|
||||||
return result
|
return { data: result }
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`Failed to create OCR provider ${data.id}`, error as Error)
|
logger.error(`Failed to create OCR provider ${data.id}`, error as Error)
|
||||||
throw error
|
throw error
|
||||||
@ -171,9 +173,9 @@ class OcrService {
|
|||||||
* Update OCR provider (partial update)
|
* Update OCR provider (partial update)
|
||||||
*/
|
*/
|
||||||
public async updateProvider(
|
public async updateProvider(
|
||||||
id: OcrProviderId,
|
id: OcrProviderKeyBusiness,
|
||||||
data: Partial<PatchOcrProviderRequest>
|
data: UpdateOcrProviderRequest
|
||||||
): Promise<PatchOcrProviderResponse> {
|
): Promise<UpdateOcrProviderResponse> {
|
||||||
try {
|
try {
|
||||||
await this.ensureInitialized()
|
await this.ensureInitialized()
|
||||||
const result = await ocrProviderRepository.update(id, data)
|
const result = await ocrProviderRepository.update(id, data)
|
||||||
@ -188,7 +190,7 @@ class OcrService {
|
|||||||
/**
|
/**
|
||||||
* Replace OCR provider (full update)
|
* Replace OCR provider (full update)
|
||||||
*/
|
*/
|
||||||
public async replaceProvider(data: PutOcrProviderRequest): Promise<PutOcrProviderResponse> {
|
public async replaceProvider(data: ReplaceOcrProviderRequest): Promise<ReplaceOcrProviderResponse> {
|
||||||
try {
|
try {
|
||||||
await this.ensureInitialized()
|
await this.ensureInitialized()
|
||||||
const result = await ocrProviderRepository.replace(data)
|
const result = await ocrProviderRepository.replace(data)
|
||||||
@ -203,7 +205,7 @@ class OcrService {
|
|||||||
/**
|
/**
|
||||||
* Delete OCR provider
|
* Delete OCR provider
|
||||||
*/
|
*/
|
||||||
public async deleteProvider(id: OcrProviderId): Promise<void> {
|
public async deleteProvider(id: OcrProviderKeyBusiness): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await this.ensureInitialized()
|
await this.ensureInitialized()
|
||||||
await ocrProviderRepository.delete(id)
|
await ocrProviderRepository.delete(id)
|
||||||
@ -242,7 +244,7 @@ class OcrService {
|
|||||||
/**
|
/**
|
||||||
* Check if a provider is available and ready
|
* Check if a provider is available and ready
|
||||||
*/
|
*/
|
||||||
public async isProviderAvailable(providerId: OcrProviderId): Promise<boolean> {
|
public async isProviderAvailable(providerId: OcrProviderKeyBusiness): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
const service = this.registry.get(providerId)
|
const service = this.registry.get(providerId)
|
||||||
if (!service) {
|
if (!service) {
|
||||||
|
|||||||
52
src/renderer/src/types/ocr/api.ts
Normal file
52
src/renderer/src/types/ocr/api.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import * as z from 'zod'
|
||||||
|
|
||||||
|
import { DbOcrProviderSchema } from './data'
|
||||||
|
import { OcrProviderSchema } from './provider/base'
|
||||||
|
import { OcrProviderNameSchema } from './provider/base'
|
||||||
|
import { OcrProviderIdSchema } from './provider/base'
|
||||||
|
import { OcrProviderConfigSchema } from './provider/base'
|
||||||
|
|
||||||
|
// ==========================================================
|
||||||
|
// API layer Types
|
||||||
|
// ==========================================================
|
||||||
|
export const TimestampExtendShape = {
|
||||||
|
createdAt: z.number().nullable(),
|
||||||
|
updatedAt: z.number().nullable()
|
||||||
|
}
|
||||||
|
export type ListOcrProvidersQuery = { registered?: boolean }
|
||||||
|
export const ListOcrProvidersResponseSchema = z.object({
|
||||||
|
data: z.array(DbOcrProviderSchema)
|
||||||
|
})
|
||||||
|
export type ListOcrProvidersResponse = z.infer<typeof ListOcrProvidersResponseSchema>
|
||||||
|
export const GetOcrProviderResponseSchema = z.object({
|
||||||
|
data: DbOcrProviderSchema
|
||||||
|
})
|
||||||
|
export type GetOcrProviderResponse = z.infer<typeof GetOcrProviderResponseSchema> /**
|
||||||
|
* Request payload for updating an OCR provider.
|
||||||
|
* Only the following fields are modifiable:
|
||||||
|
* - `name`: provider display name
|
||||||
|
* - `config`: provider-specific configuration object (all properties optional)
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const UpdateOcrProviderRequestSchema = z.object({
|
||||||
|
id: OcrProviderIdSchema,
|
||||||
|
name: OcrProviderNameSchema.optional(),
|
||||||
|
config: OcrProviderConfigSchema.partial().optional()
|
||||||
|
})
|
||||||
|
export type UpdateOcrProviderRequest = z.infer<typeof UpdateOcrProviderRequestSchema>
|
||||||
|
export const UpdateOcrProviderResponseSchema = z.object({
|
||||||
|
data: DbOcrProviderSchema
|
||||||
|
})
|
||||||
|
export type UpdateOcrProviderResponse = z.infer<typeof UpdateOcrProviderResponseSchema>
|
||||||
|
export const CreateOcrProviderRequestSchema = OcrProviderSchema
|
||||||
|
export type CreateOcrProviderRequest = z.infer<typeof CreateOcrProviderRequestSchema>
|
||||||
|
export const CreateOcrProviderResponseSchema = z.object({
|
||||||
|
data: DbOcrProviderSchema
|
||||||
|
})
|
||||||
|
export type CreateOcrProviderResponse = z.infer<typeof CreateOcrProviderResponseSchema>
|
||||||
|
export const ReplaceOcrProviderRequestSchema = OcrProviderSchema
|
||||||
|
export type ReplaceOcrProviderRequest = z.infer<typeof ReplaceOcrProviderRequestSchema>
|
||||||
|
export const ReplaceOcrProviderResponseSchema = z.object({
|
||||||
|
data: DbOcrProviderSchema
|
||||||
|
})
|
||||||
|
export type ReplaceOcrProviderResponse = z.infer<typeof ReplaceOcrProviderResponseSchema>
|
||||||
20
src/renderer/src/types/ocr/base.ts
Normal file
20
src/renderer/src/types/ocr/base.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import type { FileMetadata, ImageFileMetadata } from '..'
|
||||||
|
import { isImageFileMetadata } from '..'
|
||||||
|
|
||||||
|
export type SupportedOcrFile = ImageFileMetadata
|
||||||
|
|
||||||
|
export const isSupportedOcrFile = (file: FileMetadata): file is SupportedOcrFile => {
|
||||||
|
return isImageFileMetadata(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
export type OcrParams = {
|
||||||
|
providerId: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type OcrResult = {
|
||||||
|
text: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type OcrHandler = (file: SupportedOcrFile) => Promise<OcrResult>
|
||||||
|
|
||||||
|
export type OcrImageHandler = (file: ImageFileMetadata) => Promise<OcrResult>
|
||||||
31
src/renderer/src/types/ocr/business.ts
Normal file
31
src/renderer/src/types/ocr/business.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import type { DbOcrProviderCreate } from './data'
|
||||||
|
import type { DbOcrProviderUpdate } from './data'
|
||||||
|
import type { DbOcrProviderReplace } from './data'
|
||||||
|
import type { DbOcrProviderKey } from './data'
|
||||||
|
import type { DbOcrProvider } from './data'
|
||||||
|
|
||||||
|
// ==========================================================
|
||||||
|
// Business layer Types
|
||||||
|
// ==========================================================
|
||||||
|
/**
|
||||||
|
* Business-level representation of an OCR provider.
|
||||||
|
* Mirrors the data layer but is intended for use in domain/business logic.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type OcrProviderBusiness = DbOcrProvider /**
|
||||||
|
* Business-level representation of an OCR provider creation payload.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type OcrProviderCreateBusiness = DbOcrProviderCreate /**
|
||||||
|
* Business-level representation of an OCR provider update payload.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type OcrProviderUpdateBusiness = DbOcrProviderUpdate /**
|
||||||
|
* Business-level representation of an OCR provider replacement payload.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type OcrProviderReplaceBusiness = DbOcrProviderReplace /**
|
||||||
|
* Business-level key type for identifying an OCR provider.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type OcrProviderKeyBusiness = DbOcrProviderKey
|
||||||
22
src/renderer/src/types/ocr/data.ts
Normal file
22
src/renderer/src/types/ocr/data.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import type * as z from 'zod'
|
||||||
|
|
||||||
|
import { TimestampExtendShape, type UpdateOcrProviderRequest } from './api'
|
||||||
|
import { type OcrProvider } from './provider/base'
|
||||||
|
import { OcrProviderSchema } from './provider/base'
|
||||||
|
|
||||||
|
// ==========================================================
|
||||||
|
// Data layer Types
|
||||||
|
//
|
||||||
|
// NOTE: Timestamp operations are not exposed to outside.
|
||||||
|
// ==========================================================
|
||||||
|
|
||||||
|
export const DbOcrProviderSchema = OcrProviderSchema.extend(TimestampExtendShape)
|
||||||
|
export type DbOcrProvider = z.infer<typeof DbOcrProviderSchema>
|
||||||
|
export function isDbOcrProvider(p: unknown): p is DbOcrProvider {
|
||||||
|
return DbOcrProviderSchema.safeParse(p).success
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DbOcrProviderCreate = OcrProvider
|
||||||
|
export type DbOcrProviderUpdate = UpdateOcrProviderRequest
|
||||||
|
export type DbOcrProviderReplace = OcrProvider
|
||||||
|
export type DbOcrProviderKey = DbOcrProvider['id']
|
||||||
@ -1 +1,6 @@
|
|||||||
export * from './ocr'
|
export * from './api'
|
||||||
|
export * from './base'
|
||||||
|
export * from './business'
|
||||||
|
export * from './data'
|
||||||
|
export * from './model'
|
||||||
|
export * from './provider'
|
||||||
|
|||||||
17
src/renderer/src/types/ocr/model.ts
Normal file
17
src/renderer/src/types/ocr/model.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import * as z from 'zod'
|
||||||
|
|
||||||
|
import type { OcrProviderCapabilityRecord } from './provider/base'
|
||||||
|
import { OcrProviderCapabilityRecordSchema } from './provider/base'
|
||||||
|
|
||||||
|
// OCR models and providers share the same type definition.
|
||||||
|
// A provider can offer capabilities to process multiple file types,
|
||||||
|
// while a model belonging to that provider may be limited to processing only one specific file type.
|
||||||
|
|
||||||
|
export type OcrModelCapabilityRecord = OcrProviderCapabilityRecord
|
||||||
|
export const OcrModelSchema = z.object({
|
||||||
|
id: z.string(),
|
||||||
|
name: z.string(),
|
||||||
|
providerId: z.string(),
|
||||||
|
capabilities: OcrProviderCapabilityRecordSchema
|
||||||
|
})
|
||||||
|
export type OcrModel = z.infer<typeof OcrModelSchema>
|
||||||
@ -1,373 +0,0 @@
|
|||||||
import type Tesseract from 'tesseract.js'
|
|
||||||
import * as z from 'zod'
|
|
||||||
|
|
||||||
import type { FileMetadata, ImageFileMetadata, TranslateLanguageCode } from '..'
|
|
||||||
import { isImageFileMetadata, objectValues, TranslateLanguageCodeSchema } from '..'
|
|
||||||
|
|
||||||
export const BuiltinOcrProviderIdMap = {
|
|
||||||
tesseract: 'tesseract',
|
|
||||||
system: 'system',
|
|
||||||
paddleocr: 'paddleocr',
|
|
||||||
ovocr: 'ovocr'
|
|
||||||
} as const satisfies Record<string, BuiltinOcrProviderId>
|
|
||||||
|
|
||||||
export const BuiltinOcrProviderIds = Object.freeze(objectValues(BuiltinOcrProviderIdMap))
|
|
||||||
|
|
||||||
export const BuiltinOcrProviderIdSchema = z.enum(['tesseract', 'system', 'paddleocr', 'ovocr'])
|
|
||||||
|
|
||||||
export type BuiltinOcrProviderId = z.infer<typeof BuiltinOcrProviderIdSchema>
|
|
||||||
|
|
||||||
export const isBuiltinOcrProviderId = (id: string): id is BuiltinOcrProviderId => {
|
|
||||||
return BuiltinOcrProviderIdSchema.safeParse(id).success
|
|
||||||
}
|
|
||||||
|
|
||||||
// extensible
|
|
||||||
export const OcrProviderCapabilities = {
|
|
||||||
image: 'image'
|
|
||||||
// pdf: 'pdf'
|
|
||||||
} as const satisfies Record<string, OcrProviderCapability>
|
|
||||||
|
|
||||||
export const OcrProviderCapabilitySchema = z.enum(['image'])
|
|
||||||
|
|
||||||
export type OcrProviderCapability = z.infer<typeof OcrProviderCapabilitySchema>
|
|
||||||
|
|
||||||
export const isOcrProviderCapability = (cap: string): cap is OcrProviderCapability => {
|
|
||||||
return OcrProviderCapabilitySchema.safeParse(cap).success
|
|
||||||
}
|
|
||||||
|
|
||||||
export const OcrProviderCapabilityRecordSchema = z.partialRecord(OcrProviderCapabilitySchema, z.boolean())
|
|
||||||
|
|
||||||
export type OcrProviderCapabilityRecord = z.infer<typeof OcrProviderCapabilityRecordSchema>
|
|
||||||
|
|
||||||
// OCR models and providers share the same type definition.
|
|
||||||
// A provider can offer capabilities to process multiple file types,
|
|
||||||
// while a model belonging to that provider may be limited to processing only one specific file type.
|
|
||||||
export type OcrModelCapabilityRecord = OcrProviderCapabilityRecord
|
|
||||||
|
|
||||||
export const OcrModelSchema = z.object({
|
|
||||||
id: z.string(),
|
|
||||||
name: z.string(),
|
|
||||||
providerId: z.string(),
|
|
||||||
capabilities: OcrProviderCapabilityRecordSchema
|
|
||||||
})
|
|
||||||
|
|
||||||
export type OcrModel = z.infer<typeof OcrModelSchema>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extend this type to define provider-specefic config types.
|
|
||||||
*/
|
|
||||||
export const OcrProviderApiConfigSchema = z.object({
|
|
||||||
apiKey: z.string(),
|
|
||||||
apiHost: z.string(),
|
|
||||||
apiVersion: z.string().optional()
|
|
||||||
})
|
|
||||||
|
|
||||||
export type OcrProviderApiConfig = z.infer<typeof OcrProviderApiConfigSchema>
|
|
||||||
|
|
||||||
export const isOcrProviderApiConfig = (config: unknown): config is OcrProviderApiConfig => {
|
|
||||||
return OcrProviderApiConfigSchema.safeParse(config).success
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For future. Model based ocr, api based ocr. May different api client.
|
|
||||||
*
|
|
||||||
* Extend this type to define provider-specific config types.
|
|
||||||
*/
|
|
||||||
export const OcrProviderBaseConfigSchema = z.object({
|
|
||||||
enabled: z.boolean().default(false)
|
|
||||||
})
|
|
||||||
|
|
||||||
export type OcrProviderBaseConfig = z.infer<typeof OcrProviderBaseConfigSchema>
|
|
||||||
|
|
||||||
export const OcrProviderConfigSchema = OcrProviderBaseConfigSchema.loose()
|
|
||||||
|
|
||||||
export type OcrProviderConfig = z.infer<typeof OcrProviderConfigSchema>
|
|
||||||
|
|
||||||
const OcrProviderIdSchema = z.string()
|
|
||||||
|
|
||||||
export type OcrProviderId = z.infer<typeof OcrProviderIdSchema>
|
|
||||||
|
|
||||||
const OcrProviderNameSchema = z.string()
|
|
||||||
|
|
||||||
export const OcrProviderSchema = z.object({
|
|
||||||
id: OcrProviderIdSchema,
|
|
||||||
name: OcrProviderNameSchema,
|
|
||||||
capabilities: OcrProviderCapabilityRecordSchema,
|
|
||||||
config: OcrProviderConfigSchema
|
|
||||||
})
|
|
||||||
|
|
||||||
export type OcrProvider = z.infer<typeof OcrProviderSchema>
|
|
||||||
|
|
||||||
export const isOcrProvider = (p: unknown): p is OcrProvider => {
|
|
||||||
return OcrProviderSchema.safeParse(p).success
|
|
||||||
}
|
|
||||||
|
|
||||||
export const OcrApiProviderConfigSchema = OcrProviderBaseConfigSchema.extend({
|
|
||||||
api: OcrProviderApiConfigSchema
|
|
||||||
})
|
|
||||||
|
|
||||||
export type OcrApiProviderConfig = z.infer<typeof OcrApiProviderConfigSchema>
|
|
||||||
|
|
||||||
export const isOcrApiProviderConfig = (config: unknown): config is OcrApiProviderConfig => {
|
|
||||||
return OcrApiProviderConfigSchema.safeParse(config).success
|
|
||||||
}
|
|
||||||
|
|
||||||
export const OcrApiProviderSchema = OcrProviderSchema
|
|
||||||
|
|
||||||
/** Currently, there is no API provider yet, but we've left room for expansion. */
|
|
||||||
export type OcrApiProvider = z.infer<typeof OcrApiProviderSchema>
|
|
||||||
|
|
||||||
export const isOcrApiProvider = (p: unknown): p is OcrApiProvider => {
|
|
||||||
return OcrApiProviderSchema.safeParse(p).success
|
|
||||||
}
|
|
||||||
|
|
||||||
export type BuiltinOcrProvider = OcrProvider & {
|
|
||||||
id: BuiltinOcrProviderId
|
|
||||||
}
|
|
||||||
|
|
||||||
export const isBuiltinOcrProvider = (p: OcrProvider): p is BuiltinOcrProvider => {
|
|
||||||
return isBuiltinOcrProviderId(p.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not sure compatible api endpoint exists. May not support custom ocr provider
|
|
||||||
export type CustomOcrProvider = OcrProvider & {
|
|
||||||
id: Exclude<string, BuiltinOcrProviderId>
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ImageOcrProvider = OcrProvider & {
|
|
||||||
capabilities: OcrProviderCapabilityRecord & {
|
|
||||||
[OcrProviderCapabilities.image]: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// export type PdfOcrProvider = OcrProvider & {
|
|
||||||
// capabilities: OcrProviderCapabilityRecord & {
|
|
||||||
// [OcrProviderCapabilities.pdf]: true
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
export const isImageOcrProvider = (p: OcrProvider): p is ImageOcrProvider => {
|
|
||||||
return p.capabilities.image === true
|
|
||||||
}
|
|
||||||
|
|
||||||
export type SupportedOcrFile = ImageFileMetadata
|
|
||||||
|
|
||||||
export const isSupportedOcrFile = (file: FileMetadata): file is SupportedOcrFile => {
|
|
||||||
return isImageFileMetadata(file)
|
|
||||||
}
|
|
||||||
|
|
||||||
export type OcrParams = {
|
|
||||||
providerId: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export type OcrResult = {
|
|
||||||
text: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export type OcrHandler = (file: SupportedOcrFile) => Promise<OcrResult>
|
|
||||||
|
|
||||||
export type OcrImageHandler = (file: ImageFileMetadata) => Promise<OcrResult>
|
|
||||||
|
|
||||||
// ==========================================================
|
|
||||||
// Tesseract OCR Types
|
|
||||||
// ==========================================================
|
|
||||||
export const OcrTesseractConfigSchema = OcrProviderBaseConfigSchema.extend({
|
|
||||||
langs: z.record(TranslateLanguageCodeSchema, z.boolean()).optional()
|
|
||||||
})
|
|
||||||
|
|
||||||
export type OcrTesseractConfig = z.infer<typeof OcrTesseractConfigSchema>
|
|
||||||
|
|
||||||
export type OcrTesseractProvider = {
|
|
||||||
id: 'tesseract'
|
|
||||||
config: OcrTesseractConfig
|
|
||||||
} & ImageOcrProvider &
|
|
||||||
BuiltinOcrProvider
|
|
||||||
|
|
||||||
export const isOcrTesseractProvider = (p: OcrProvider): p is OcrTesseractProvider => {
|
|
||||||
return p.id === BuiltinOcrProviderIdMap.tesseract
|
|
||||||
}
|
|
||||||
|
|
||||||
export type TesseractLangCode = Tesseract.LanguageCode
|
|
||||||
|
|
||||||
// ==========================================================
|
|
||||||
// System OCR Types
|
|
||||||
// ==========================================================
|
|
||||||
export interface OcrSystemConfig extends OcrProviderBaseConfig {
|
|
||||||
langs?: TranslateLanguageCode[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export type OcrSystemProvider = {
|
|
||||||
id: 'system'
|
|
||||||
config: OcrSystemConfig
|
|
||||||
} & ImageOcrProvider &
|
|
||||||
// PdfOcrProvider &
|
|
||||||
BuiltinOcrProvider
|
|
||||||
|
|
||||||
export const isOcrSystemProvider = (p: OcrProvider): p is OcrSystemProvider => {
|
|
||||||
return p.id === BuiltinOcrProviderIdMap.system
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==========================================================
|
|
||||||
// PaddleOCR Types
|
|
||||||
// ==========================================================
|
|
||||||
export const OcrPpocrConfigSchema = OcrProviderBaseConfigSchema.extend({
|
|
||||||
apiUrl: z.string().optional(),
|
|
||||||
accessToken: z.string().optional()
|
|
||||||
})
|
|
||||||
|
|
||||||
export type OcrPpocrConfig = z.infer<typeof OcrPpocrConfigSchema>
|
|
||||||
|
|
||||||
export const isOcrPpocrConfig = (config: unknown): config is OcrPpocrConfig => {
|
|
||||||
return OcrPpocrConfigSchema.safeParse(config).success
|
|
||||||
}
|
|
||||||
|
|
||||||
export type OcrPpocrProvider = {
|
|
||||||
id: 'paddleocr'
|
|
||||||
config: OcrPpocrConfig
|
|
||||||
} & ImageOcrProvider &
|
|
||||||
// PdfOcrProvider &
|
|
||||||
BuiltinOcrProvider
|
|
||||||
|
|
||||||
export const isOcrPpocrProvider = (p: OcrProvider): p is OcrPpocrProvider => {
|
|
||||||
return p.id === BuiltinOcrProviderIdMap.paddleocr
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==========================================================
|
|
||||||
// OV OCR Types
|
|
||||||
// ==========================================================
|
|
||||||
export const OcrOvConfigSchema = OcrProviderBaseConfigSchema.extend({
|
|
||||||
// It's not configurable for now.
|
|
||||||
// langs: z.array(TranslateLanguageCodeSchema).optional()
|
|
||||||
})
|
|
||||||
|
|
||||||
export type OcrOvConfig = z.infer<typeof OcrOvConfigSchema>
|
|
||||||
|
|
||||||
export const isOcrOvConfig = (config: unknown): config is OcrOvConfig => {
|
|
||||||
return OcrOvConfigSchema.safeParse(config).success
|
|
||||||
}
|
|
||||||
|
|
||||||
export type OcrOvProvider = {
|
|
||||||
id: 'ovocr'
|
|
||||||
config: OcrOvConfig
|
|
||||||
} & ImageOcrProvider &
|
|
||||||
// PdfOcrProvider &
|
|
||||||
BuiltinOcrProvider
|
|
||||||
|
|
||||||
export const isOcrOVProvider = (p: OcrProvider): p is OcrOvProvider => {
|
|
||||||
return p.id === BuiltinOcrProviderIdMap.ovocr
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==========================================================
|
|
||||||
// API layer Types
|
|
||||||
// ==========================================================
|
|
||||||
|
|
||||||
const TimestampExtendShape = {
|
|
||||||
createdAt: z.number().nullable(),
|
|
||||||
updatedAt: z.number().nullable()
|
|
||||||
}
|
|
||||||
|
|
||||||
export const DbOcrProviderSchema = OcrProviderSchema.extend(TimestampExtendShape)
|
|
||||||
|
|
||||||
export type DbOcrProvider = z.infer<typeof DbOcrProviderSchema>
|
|
||||||
|
|
||||||
export const isDbOcrProvider = (p: unknown): p is DbOcrProvider => {
|
|
||||||
return DbOcrProviderSchema.safeParse(p).success
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ListOcrProvidersQuery = { registered?: boolean }
|
|
||||||
|
|
||||||
export const ListOcrProvidersResponseSchema = z.object({
|
|
||||||
data: z.array(DbOcrProviderSchema)
|
|
||||||
})
|
|
||||||
|
|
||||||
export type ListOcrProvidersResponse = z.infer<typeof ListOcrProvidersResponseSchema>
|
|
||||||
|
|
||||||
export const GetOcrProviderResponseSchema = z.object({
|
|
||||||
data: DbOcrProviderSchema
|
|
||||||
})
|
|
||||||
|
|
||||||
export type GetOcrProviderResponse = z.infer<typeof GetOcrProviderResponseSchema>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request payload for updating an OCR provider.
|
|
||||||
* Only the following fields are modifiable:
|
|
||||||
* - `name`: provider display name
|
|
||||||
* - `config`: provider-specific configuration object (all properties optional)
|
|
||||||
*/
|
|
||||||
export const UpdateOcrProviderRequestSchema = z.object({
|
|
||||||
id: OcrProviderIdSchema,
|
|
||||||
name: OcrProviderNameSchema.optional(),
|
|
||||||
config: OcrProviderConfigSchema.partial().optional()
|
|
||||||
})
|
|
||||||
|
|
||||||
export type UpdateOcrProviderRequest = z.infer<typeof UpdateOcrProviderRequestSchema>
|
|
||||||
|
|
||||||
export const UpdateOcrProviderResponseSchema = z.object({
|
|
||||||
data: DbOcrProviderSchema
|
|
||||||
})
|
|
||||||
|
|
||||||
export type UpdateOcrProviderResponse = z.infer<typeof UpdateOcrProviderResponseSchema>
|
|
||||||
|
|
||||||
export const CreateOcrProviderRequestSchema = OcrProviderSchema
|
|
||||||
|
|
||||||
export type CreateOcrProviderRequest = z.infer<typeof CreateOcrProviderRequestSchema>
|
|
||||||
|
|
||||||
export const CreateOcrProviderResponseSchema = z.object({
|
|
||||||
data: DbOcrProviderSchema
|
|
||||||
})
|
|
||||||
|
|
||||||
export type CreateOcrProviderResponse = z.infer<typeof CreateOcrProviderResponseSchema>
|
|
||||||
|
|
||||||
export const ReplaceOcrProviderRequestSchema = OcrProviderSchema
|
|
||||||
|
|
||||||
export type ReplaceOcrProviderRequest = z.infer<typeof ReplaceOcrProviderRequestSchema>
|
|
||||||
|
|
||||||
export const ReplaceOcrProviderResponseSchema = z.object({
|
|
||||||
data: DbOcrProviderSchema
|
|
||||||
})
|
|
||||||
|
|
||||||
export type ReplaceOcrProviderResponse = z.infer<typeof ReplaceOcrProviderResponseSchema>
|
|
||||||
|
|
||||||
// ==========================================================
|
|
||||||
// Business layer Types
|
|
||||||
// ==========================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Business-level representation of an OCR provider.
|
|
||||||
* Mirrors the data layer but is intended for use in domain/business logic.
|
|
||||||
*/
|
|
||||||
export type OcrProviderBusiness = DbOcrProvider
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Business-level representation of an OCR provider creation payload.
|
|
||||||
*/
|
|
||||||
export type OcrProviderCreateBusiness = DbOcrProviderCreate
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Business-level representation of an OCR provider update payload.
|
|
||||||
*/
|
|
||||||
export type OcrProviderUpdateBusiness = DbOcrProviderUpdate
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Business-level representation of an OCR provider replacement payload.
|
|
||||||
*/
|
|
||||||
export type OcrProviderReplaceBusiness = DbOcrProviderReplace
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Business-level key type for identifying an OCR provider.
|
|
||||||
*/
|
|
||||||
export type OcrProviderKeyBusiness = DbOcrProviderKey
|
|
||||||
|
|
||||||
// ==========================================================
|
|
||||||
// Data layer Types
|
|
||||||
//
|
|
||||||
// NOTE: Timestamp operations are not exposed to outside.
|
|
||||||
// ==========================================================
|
|
||||||
|
|
||||||
export type DbOcrProviderCreate = OcrProvider
|
|
||||||
|
|
||||||
export type DbOcrProviderUpdate = UpdateOcrProviderRequest
|
|
||||||
|
|
||||||
export type DbOcrProviderReplace = OcrProvider
|
|
||||||
|
|
||||||
export type DbOcrProviderKey = DbOcrProvider['id']
|
|
||||||
118
src/renderer/src/types/ocr/provider/base.ts
Normal file
118
src/renderer/src/types/ocr/provider/base.ts
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
import { objectValues } from '@types'
|
||||||
|
import * as z from 'zod'
|
||||||
|
|
||||||
|
export const BuiltinOcrProviderIdMap = {
|
||||||
|
tesseract: 'tesseract',
|
||||||
|
system: 'system',
|
||||||
|
paddleocr: 'paddleocr',
|
||||||
|
ovocr: 'ovocr'
|
||||||
|
} as const satisfies Record<string, BuiltinOcrProviderId>
|
||||||
|
|
||||||
|
export const BuiltinOcrProviderIds = Object.freeze(objectValues(BuiltinOcrProviderIdMap))
|
||||||
|
|
||||||
|
export const BuiltinOcrProviderIdSchema = z.enum(['tesseract', 'system', 'paddleocr', 'ovocr'])
|
||||||
|
|
||||||
|
export type BuiltinOcrProviderId = z.infer<typeof BuiltinOcrProviderIdSchema>
|
||||||
|
|
||||||
|
export const isBuiltinOcrProviderId = (id: string): id is BuiltinOcrProviderId => {
|
||||||
|
return BuiltinOcrProviderIdSchema.safeParse(id).success
|
||||||
|
} // extensible
|
||||||
|
|
||||||
|
export const OcrProviderCapabilities = {
|
||||||
|
image: 'image'
|
||||||
|
// pdf: 'pdf'
|
||||||
|
} as const satisfies Record<string, OcrProviderCapability>
|
||||||
|
|
||||||
|
export const OcrProviderCapabilitySchema = z.enum(['image'])
|
||||||
|
|
||||||
|
export type OcrProviderCapability = z.infer<typeof OcrProviderCapabilitySchema>
|
||||||
|
|
||||||
|
export const isOcrProviderCapability = (cap: string): cap is OcrProviderCapability => {
|
||||||
|
return OcrProviderCapabilitySchema.safeParse(cap).success
|
||||||
|
}
|
||||||
|
|
||||||
|
export const OcrProviderCapabilityRecordSchema = z.partialRecord(OcrProviderCapabilitySchema, z.boolean())
|
||||||
|
|
||||||
|
export type OcrProviderCapabilityRecord = z.infer<typeof OcrProviderCapabilityRecordSchema>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend this type to define provider-specefic config types.
|
||||||
|
*/
|
||||||
|
export const OcrProviderApiConfigSchema = z.object({
|
||||||
|
apiKey: z.string(),
|
||||||
|
apiHost: z.string(),
|
||||||
|
apiVersion: z.string().optional()
|
||||||
|
})
|
||||||
|
export type OcrProviderApiConfig = z.infer<typeof OcrProviderApiConfigSchema>
|
||||||
|
export const isOcrProviderApiConfig = (config: unknown): config is OcrProviderApiConfig => {
|
||||||
|
return OcrProviderApiConfigSchema.safeParse(config).success
|
||||||
|
} /**
|
||||||
|
* For future. Model based ocr, api based ocr. May different api client.
|
||||||
|
*
|
||||||
|
* Extend this type to define provider-specific config types.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const OcrProviderBaseConfigSchema = z.object({
|
||||||
|
enabled: z.boolean().default(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
export type OcrProviderBaseConfig = z.infer<typeof OcrProviderBaseConfigSchema>
|
||||||
|
|
||||||
|
export const OcrProviderConfigSchema = OcrProviderBaseConfigSchema.loose()
|
||||||
|
|
||||||
|
export type OcrProviderConfig = z.infer<typeof OcrProviderConfigSchema>
|
||||||
|
|
||||||
|
export const OcrProviderIdSchema = z.string()
|
||||||
|
|
||||||
|
export type OcrProviderId = z.infer<typeof OcrProviderIdSchema>
|
||||||
|
|
||||||
|
export const OcrProviderNameSchema = z.string()
|
||||||
|
|
||||||
|
export const OcrProviderSchema = z.object({
|
||||||
|
id: OcrProviderIdSchema,
|
||||||
|
name: OcrProviderNameSchema,
|
||||||
|
capabilities: OcrProviderCapabilityRecordSchema,
|
||||||
|
config: OcrProviderConfigSchema
|
||||||
|
})
|
||||||
|
|
||||||
|
export type OcrProvider = z.infer<typeof OcrProviderSchema>
|
||||||
|
|
||||||
|
export const isOcrProvider = (p: unknown): p is OcrProvider => {
|
||||||
|
return OcrProviderSchema.safeParse(p).success
|
||||||
|
}
|
||||||
|
|
||||||
|
export const OcrApiProviderConfigSchema = OcrProviderBaseConfigSchema.extend({
|
||||||
|
api: OcrProviderApiConfigSchema
|
||||||
|
})
|
||||||
|
export type OcrApiProviderConfig = z.infer<typeof OcrApiProviderConfigSchema>
|
||||||
|
export const isOcrApiProviderConfig = (config: unknown): config is OcrApiProviderConfig => {
|
||||||
|
return OcrApiProviderConfigSchema.safeParse(config).success
|
||||||
|
}
|
||||||
|
|
||||||
|
export const OcrApiProviderSchema = OcrProviderSchema
|
||||||
|
/** Currently, there is no API provider yet, but we've left room for expansion. */
|
||||||
|
export type OcrApiProvider = z.infer<typeof OcrApiProviderSchema>
|
||||||
|
export const isOcrApiProvider = (p: unknown): p is OcrApiProvider => {
|
||||||
|
return OcrApiProviderSchema.safeParse(p).success
|
||||||
|
}
|
||||||
|
|
||||||
|
export type BuiltinOcrProvider = OcrProvider & {
|
||||||
|
id: BuiltinOcrProviderId
|
||||||
|
}
|
||||||
|
export const isBuiltinOcrProvider = (p: OcrProvider): p is BuiltinOcrProvider => {
|
||||||
|
return isBuiltinOcrProviderId(p.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not sure compatible api endpoint exists. May not support custom ocr provider
|
||||||
|
export type CustomOcrProvider = OcrProvider & {
|
||||||
|
id: Exclude<string, BuiltinOcrProviderId>
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ImageOcrProvider = OcrProvider & {
|
||||||
|
capabilities: OcrProviderCapabilityRecord & {
|
||||||
|
[OcrProviderCapabilities.image]: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const isImageOcrProvider = (p: OcrProvider): p is ImageOcrProvider => {
|
||||||
|
return p.capabilities.image === true
|
||||||
|
}
|
||||||
5
src/renderer/src/types/ocr/provider/index.ts
Normal file
5
src/renderer/src/types/ocr/provider/index.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export * from './base'
|
||||||
|
export * from './ov'
|
||||||
|
export * from './paddle'
|
||||||
|
export * from './system'
|
||||||
|
export * from './tesseract'
|
||||||
29
src/renderer/src/types/ocr/provider/ov.ts
Normal file
29
src/renderer/src/types/ocr/provider/ov.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import type * as z from 'zod'
|
||||||
|
|
||||||
|
import type { ImageOcrProvider } from './base'
|
||||||
|
import type { BuiltinOcrProvider } from './base'
|
||||||
|
import type { OcrProvider } from './base'
|
||||||
|
import { OcrProviderBaseConfigSchema } from './base'
|
||||||
|
import { BuiltinOcrProviderIdMap } from './base'
|
||||||
|
|
||||||
|
// ==========================================================
|
||||||
|
// OV OCR Types
|
||||||
|
// ==========================================================
|
||||||
|
|
||||||
|
export const OcrOvConfigSchema = OcrProviderBaseConfigSchema.extend({
|
||||||
|
// It's not configurable for now.
|
||||||
|
// langs: z.array(TranslateLanguageCodeSchema).optional()
|
||||||
|
})
|
||||||
|
export type OcrOvConfig = z.infer<typeof OcrOvConfigSchema>
|
||||||
|
export const isOcrOvConfig = (config: unknown): config is OcrOvConfig => {
|
||||||
|
return OcrOvConfigSchema.safeParse(config).success
|
||||||
|
}
|
||||||
|
export type OcrOvProvider = {
|
||||||
|
id: 'ovocr'
|
||||||
|
config: OcrOvConfig
|
||||||
|
} & ImageOcrProvider &
|
||||||
|
// PdfOcrProvider &
|
||||||
|
BuiltinOcrProvider
|
||||||
|
export const isOcrOVProvider = (p: OcrProvider): p is OcrOvProvider => {
|
||||||
|
return p.id === BuiltinOcrProviderIdMap.ovocr
|
||||||
|
}
|
||||||
29
src/renderer/src/types/ocr/provider/paddle.ts
Normal file
29
src/renderer/src/types/ocr/provider/paddle.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import * as z from 'zod'
|
||||||
|
|
||||||
|
import type { ImageOcrProvider } from './base'
|
||||||
|
import type { BuiltinOcrProvider } from './base'
|
||||||
|
import type { OcrProvider } from './base'
|
||||||
|
import { OcrProviderBaseConfigSchema } from './base'
|
||||||
|
import { BuiltinOcrProviderIdMap } from './base'
|
||||||
|
|
||||||
|
// ==========================================================
|
||||||
|
// PaddleOCR Types
|
||||||
|
// ==========================================================
|
||||||
|
|
||||||
|
export const OcrPpocrConfigSchema = OcrProviderBaseConfigSchema.extend({
|
||||||
|
apiUrl: z.string().optional(),
|
||||||
|
accessToken: z.string().optional()
|
||||||
|
})
|
||||||
|
export type OcrPpocrConfig = z.infer<typeof OcrPpocrConfigSchema>
|
||||||
|
export const isOcrPpocrConfig = (config: unknown): config is OcrPpocrConfig => {
|
||||||
|
return OcrPpocrConfigSchema.safeParse(config).success
|
||||||
|
}
|
||||||
|
export type OcrPpocrProvider = {
|
||||||
|
id: 'paddleocr'
|
||||||
|
config: OcrPpocrConfig
|
||||||
|
} & ImageOcrProvider &
|
||||||
|
// PdfOcrProvider &
|
||||||
|
BuiltinOcrProvider
|
||||||
|
export const isOcrPpocrProvider = (p: OcrProvider): p is OcrPpocrProvider => {
|
||||||
|
return p.id === BuiltinOcrProviderIdMap.paddleocr
|
||||||
|
}
|
||||||
25
src/renderer/src/types/ocr/provider/system.ts
Normal file
25
src/renderer/src/types/ocr/provider/system.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import type { TranslateLanguageCode } from '@types'
|
||||||
|
|
||||||
|
import type { OcrProvider } from './base'
|
||||||
|
import { type ImageOcrProvider } from './base'
|
||||||
|
import { type BuiltinOcrProvider } from './base'
|
||||||
|
import { type OcrProviderBaseConfig } from './base'
|
||||||
|
import { BuiltinOcrProviderIdMap } from './base'
|
||||||
|
|
||||||
|
// ==========================================================
|
||||||
|
// System OCR Types
|
||||||
|
// ==========================================================
|
||||||
|
|
||||||
|
export interface OcrSystemConfig extends OcrProviderBaseConfig {
|
||||||
|
langs?: TranslateLanguageCode[]
|
||||||
|
}
|
||||||
|
export type OcrSystemProvider = {
|
||||||
|
id: 'system'
|
||||||
|
config: OcrSystemConfig
|
||||||
|
} & ImageOcrProvider &
|
||||||
|
// PdfOcrProvider &
|
||||||
|
BuiltinOcrProvider
|
||||||
|
|
||||||
|
export const isOcrSystemProvider = (p: OcrProvider): p is OcrSystemProvider => {
|
||||||
|
return p.id === BuiltinOcrProviderIdMap.system
|
||||||
|
}
|
||||||
31
src/renderer/src/types/ocr/provider/tesseract.ts
Normal file
31
src/renderer/src/types/ocr/provider/tesseract.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { TranslateLanguageCodeSchema } from '@types'
|
||||||
|
import type Tesseract from 'tesseract.js'
|
||||||
|
import * as z from 'zod'
|
||||||
|
|
||||||
|
import type { ImageOcrProvider } from './base'
|
||||||
|
import type { BuiltinOcrProvider } from './base'
|
||||||
|
import type { OcrProvider } from './base'
|
||||||
|
import { OcrProviderBaseConfigSchema } from './base'
|
||||||
|
import { BuiltinOcrProviderIdMap } from './base'
|
||||||
|
|
||||||
|
// ==========================================================
|
||||||
|
// Tesseract OCR Types
|
||||||
|
// ==========================================================
|
||||||
|
|
||||||
|
export const OcrTesseractConfigSchema = OcrProviderBaseConfigSchema.extend({
|
||||||
|
langs: z.record(TranslateLanguageCodeSchema, z.boolean()).optional()
|
||||||
|
})
|
||||||
|
|
||||||
|
export type OcrTesseractConfig = z.infer<typeof OcrTesseractConfigSchema>
|
||||||
|
|
||||||
|
export type OcrTesseractProvider = {
|
||||||
|
id: 'tesseract'
|
||||||
|
config: OcrTesseractConfig
|
||||||
|
} & ImageOcrProvider &
|
||||||
|
BuiltinOcrProvider
|
||||||
|
|
||||||
|
export const isOcrTesseractProvider = (p: OcrProvider): p is OcrTesseractProvider => {
|
||||||
|
return p.id === BuiltinOcrProviderIdMap.tesseract
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TesseractLangCode = Tesseract.LanguageCode
|
||||||
@ -11,7 +11,7 @@
|
|||||||
"packages/mcp-trace/**/*",
|
"packages/mcp-trace/**/*",
|
||||||
"src/renderer/src/services/traceApi.ts",
|
"src/renderer/src/services/traceApi.ts",
|
||||||
"tests/__mocks__/**/*"
|
"tests/__mocks__/**/*"
|
||||||
, "src/renderer/src/types/ocr/ocr.ts" ],
|
, "src/renderer/src/types/ocr/base.ts" ],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"composite": true,
|
"composite": true,
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user