feat(core): implement Kintone Customize Manager core features

Wave 1 - Foundation:
- Add shared TypeScript type definitions (domain, kintone, version, ipc)
- Implement storage module with safeStorage encryption
- Implement Kintone REST API client with authentication
- Add IPC handlers for all features
- Expose APIs via preload contextBridge
- Setup Zustand stores for state management

Wave 2 - Domain Management:
- Implement Domain store with IPC actions
- Create DomainManager, DomainList, DomainForm components
- Connect UI components to store

Wave 3 - Resource Browsing:
- Create SpaceTree component for browsing spaces/apps
- Create AppDetail component for app configuration view
- Create CodeViewer component with syntax highlighting

Wave 4 - Deployment:
- Create FileUploader drag-and-drop component
- Create DeployDialog with step-by-step deployment flow
- Implement deployment IPC handler with auto-backup

Wave 5 - Version Management:
- Create VersionHistory component
- Implement version storage and rollback logic

Wave 6 - Integration:
- Integrate all components into main App layout
- Update main process entry point
- Configure TypeScript paths for renderer imports
This commit is contained in:
2026-03-12 11:03:48 +08:00
parent ab7e9b597a
commit da7f566ecf
36 changed files with 5847 additions and 151 deletions

View File

@@ -1,11 +1,62 @@
import { ElectronAPI } from '@electron-toolkit/preload'
import { ElectronAPI } from "@electron-toolkit/preload";
import type {
Result,
CreateDomainParams,
UpdateDomainParams,
GetSpacesParams,
GetAppsParams,
GetAppDetailParams,
GetFileContentParams,
DeployParams,
DeployResult,
DownloadParams,
DownloadResult,
GetVersionsParams,
RollbackParams,
} from "@renderer/types/ipc";
import type { Domain, DomainWithStatus } from "@renderer/types/domain";
import type {
KintoneSpace,
KintoneApp,
AppDetail,
FileContent,
} from "@renderer/types/kintone";
import type { Version } from "@renderer/types/version";
declare global {
interface Window {
electron: ElectronAPI
api: {
ping: () => void
platform: NodeJS.Platform
}
electron: ElectronAPI;
api: ElectronAPI;
}
}
}
export interface ElectronAPI {
// Platform detection
platform: NodeJS.Platform;
// ==================== Domain Management ====================
getDomains: () => Promise<Result<Domain[]>>;
createDomain: (params: CreateDomainParams) => Promise<Result<Domain>>;
updateDomain: (params: UpdateDomainParams) => Promise<Result<Domain>>;
deleteDomain: (id: string) => Promise<Result<void>>;
testConnection: (id: string) => Promise<Result<DomainWithStatus>>;
// ==================== Browse ====================
getSpaces: (params: GetSpacesParams) => Promise<Result<KintoneSpace[]>>;
getApps: (params: GetAppsParams) => Promise<Result<KintoneApp[]>>;
getAppDetail: (params: GetAppDetailParams) => Promise<Result<AppDetail>>;
getFileContent: (
params: GetFileContentParams,
) => Promise<Result<FileContent>>;
// ==================== Deploy ====================
deploy: (params: DeployParams) => Promise<DeployResult>;
// ==================== Download ====================
download: (params: DownloadParams) => Promise<DownloadResult>;
// ==================== Version Management ====================
getVersions: (params: GetVersionsParams) => Promise<Result<Version[]>>;
deleteVersion: (id: string) => Promise<Result<void>>;
rollback: (params: RollbackParams) => Promise<DeployResult>;
}

View File

@@ -1,27 +1,50 @@
import { contextBridge, ipcRenderer } from 'electron'
import { electronAPI } from '@electron-toolkit/preload'
import { contextBridge, ipcRenderer } from "electron";
import { electronAPI } from "@electron-toolkit/preload";
import type { ElectronAPI } from "./index.d";
// Custom APIs for renderer
const api = {
ping: () => ipcRenderer.send('ping'),
// Custom APIs for renderer - bridges to IPC handlers
const api: ElectronAPI = {
// Platform detection
platform: process.platform,
// Store APIs will be added here
}
// ==================== Domain Management ====================
getDomains: () => ipcRenderer.invoke("getDomains"),
createDomain: (params) => ipcRenderer.invoke("createDomain", params),
updateDomain: (params) => ipcRenderer.invoke("updateDomain", params),
deleteDomain: (id) => ipcRenderer.invoke("deleteDomain", id),
testConnection: (id) => ipcRenderer.invoke("testConnection", id),
// ==================== Browse ====================
getSpaces: (params) => ipcRenderer.invoke("getSpaces", params),
getApps: (params) => ipcRenderer.invoke("getApps", params),
getAppDetail: (params) => ipcRenderer.invoke("getAppDetail", params),
getFileContent: (params) => ipcRenderer.invoke("getFileContent", params),
// ==================== Deploy ====================
deploy: (params) => ipcRenderer.invoke("deploy", params),
// ==================== Download ====================
download: (params) => ipcRenderer.invoke("download", params),
// ==================== Version Management ====================
getVersions: (params) => ipcRenderer.invoke("getVersions", params),
deleteVersion: (id) => ipcRenderer.invoke("deleteVersion", id),
rollback: (params) => ipcRenderer.invoke("rollback", params),
};
// Use `contextBridge` APIs to expose Electron APIs to
// renderer only if context isolation is enabled, otherwise
// just add to the DOM global.
if (process.contextIsolated) {
try {
contextBridge.exposeInMainWorld('electron', electronAPI)
contextBridge.exposeInMainWorld('api', api)
contextBridge.exposeInMainWorld("electron", electronAPI);
contextBridge.exposeInMainWorld("api", api);
} catch (error) {
console.error(error)
console.error(error);
}
} else {
// @ts-ignore (define in dts)
window.electron = electronAPI
window.electron = electronAPI;
// @ts-ignore (define in dts)
window.api = api
}
window.api = api;
}