fix ts problem

This commit is contained in:
2026-03-12 15:11:41 +08:00
parent 7be6a3ff6a
commit cb6d3f7ee0
6 changed files with 67 additions and 77 deletions

View File

@@ -16,7 +16,7 @@ import {
saveDownload, saveDownload,
saveBackup, saveBackup,
} from "./storage"; } from "./storage";
import { KintoneClient, createKintoneClient } from "./kintone-api"; import { SelfKintoneClient, createKintoneClient } from "./kintone-api";
import type { Result } from "@shared/types/ipc"; import type { Result } from "@shared/types/ipc";
import type { import type {
CreateDomainParams, CreateDomainParams,
@@ -41,12 +41,12 @@ import type {
} from "@shared/types/version"; } from "@shared/types/version";
// Cache for Kintone clients // Cache for Kintone clients
const clientCache = new Map<string, KintoneClient>(); const clientCache = new Map<string, SelfKintoneClient>();
/** /**
* Get or create a Kintone client for a domain * Get or create a Kintone client for a domain
*/ */
async function getClient(domainId: string): Promise<KintoneClient> { async function getClient(domainId: string): Promise<SelfKintoneClient> {
if (clientCache.has(domainId)) { if (clientCache.has(domainId)) {
return clientCache.get(domainId)!; return clientCache.get(domainId)!;
} }
@@ -243,7 +243,7 @@ function registerTestDomainConnection(): void {
function registerGetSpaces(): void { function registerGetSpaces(): void {
handleWithParams< handleWithParams<
GetSpacesParams, GetSpacesParams,
Awaited<ReturnType<KintoneClient["getSpaces"]>> Awaited<ReturnType<SelfKintoneClient["getSpaces"]>>
>("getSpaces", async (params) => { >("getSpaces", async (params) => {
const client = await getClient(params.domainId); const client = await getClient(params.domainId);
return client.getSpaces(); return client.getSpaces();
@@ -256,7 +256,7 @@ function registerGetSpaces(): void {
function registerGetApps(): void { function registerGetApps(): void {
handleWithParams< handleWithParams<
GetAppsParams, GetAppsParams,
Awaited<ReturnType<KintoneClient["getApps"]>> Awaited<ReturnType<SelfKintoneClient["getApps"]>>
>("getApps", async (params) => { >("getApps", async (params) => {
const client = await getClient(params.domainId); const client = await getClient(params.domainId);
return client.getApps(params.spaceId); return client.getApps(params.spaceId);
@@ -269,7 +269,7 @@ function registerGetApps(): void {
function registerGetAppDetail(): void { function registerGetAppDetail(): void {
handleWithParams< handleWithParams<
GetAppDetailParams, GetAppDetailParams,
Awaited<ReturnType<KintoneClient["getAppDetail"]>> Awaited<ReturnType<SelfKintoneClient["getAppDetail"]>>
>("getAppDetail", async (params) => { >("getAppDetail", async (params) => {
const client = await getClient(params.domainId); const client = await getClient(params.domainId);
return client.getAppDetail(params.appId); return client.getAppDetail(params.appId);
@@ -282,7 +282,7 @@ function registerGetAppDetail(): void {
function registerGetFileContent(): void { function registerGetFileContent(): void {
handleWithParams< handleWithParams<
GetFileContentParams, GetFileContentParams,
Awaited<ReturnType<KintoneClient["getFileContent"]>> Awaited<ReturnType<SelfKintoneClient["getFileContent"]>>
>("getFileContent", async (params) => { >("getFileContent", async (params) => {
const client = await getClient(params.domainId); const client = await getClient(params.domainId);
return client.getFileContent(params.fileKey); return client.getFileContent(params.fileKey);

View File

@@ -33,10 +33,17 @@ export class KintoneError extends Error {
} }
} }
// Use typeof to get SDK method return types
type KintoneClient = KintoneRestAPIClient;
type SpaceResponse = ReturnType<KintoneClient["space"]["getSpace"]>;
type AppResponse = ReturnType<KintoneClient["app"]["getApp"]>;
type AppsResponse = ReturnType<KintoneClient["app"]["getApps"]>;
type AppCustomizeResponse = ReturnType<KintoneClient["app"]["getAppCustomize"]>;
/** /**
* Kintone REST API Client * Kintone REST API Client
*/ */
export class KintoneClient { export class SelfKintoneClient {
private client: KintoneRestAPIClient; private client: KintoneRestAPIClient;
private domain: string; private domain: string;
@@ -82,39 +89,22 @@ export class KintoneClient {
} }
} }
private mapSpace(space: { private mapSpace(space: Awaited<SpaceResponse>): KintoneSpace {
id: string | number;
name: string;
code: string;
createdAt?: string;
creator?: { code: string; name: string };
}): KintoneSpace {
return { return {
id: String(space.id), id: space.id,
name: space.name, name: space.name,
code: space.code, code: "", // Space API doesn't return code
createdAt: space.createdAt, createdAt: undefined, // Space API doesn't return createdAt
creator: space.creator creator: { code: space.creator.code, name: space.creator.name },
? { code: space.creator.code, name: space.creator.name }
: undefined,
}; };
} }
private mapApp(app: { private mapApp(app: Awaited<AppResponse>): KintoneApp {
appId: string | number;
name: string;
code?: string;
spaceId?: string | number;
createdAt: string;
creator?: { code: string; name: string };
modifiedAt?: string;
modifier?: { code: string; name: string };
}): KintoneApp {
return { return {
appId: String(app.appId), appId: app.appId,
name: app.name, name: app.name,
code: app.code, code: app.code,
spaceId: app.spaceId ? String(app.spaceId) : undefined, spaceId: app.spaceId || undefined,
createdAt: app.createdAt, createdAt: app.createdAt,
creator: app.creator, creator: app.creator,
modifiedAt: app.modifiedAt, modifiedAt: app.modifiedAt,
@@ -122,15 +112,19 @@ export class KintoneClient {
}; };
} }
private mapResource(resource: { private mapResource(
type: string; resource:
file?: { fileKey: string; name: string }; | Awaited<AppCustomizeResponse>["desktop"]["js"][number]
url?: string; | Awaited<AppCustomizeResponse>["desktop"]["css"][number],
}): JSFileConfig | CSSFileConfig { ): JSFileConfig | CSSFileConfig {
return { return {
type: resource.type as "FILE" | "URL", type: resource.type,
file: resource.file file: resource.file
? { fileKey: resource.file.fileKey, name: resource.file.name, size: 0 } ? {
fileKey: resource.file.fileKey,
name: resource.file.name,
size: parseInt(resource.file.size, 10),
}
: undefined, : undefined,
url: resource.url, url: resource.url,
}; };
@@ -139,9 +133,7 @@ export class KintoneClient {
private buildCustomizeSection( private buildCustomizeSection(
js?: JSFileConfig[], js?: JSFileConfig[],
css?: CSSFileConfig[], css?: CSSFileConfig[],
): ): Parameters<KintoneClient["app"]["updateAppCustomize"]>[0] | undefined {
| { js?: CustomizeResourceItem[]; css?: CustomizeResourceItem[] }
| undefined {
if (!js && !css) return undefined; if (!js && !css) return undefined;
return { return {
@@ -160,10 +152,18 @@ export class KintoneClient {
// ==================== Space APIs ==================== // ==================== Space APIs ====================
// Note: Kintone REST API does not provide an endpoint to list all spaces.
// Use getSpace(spaceId) to retrieve individual spaces.
async getSpaces(): Promise<KintoneSpace[]> { async getSpaces(): Promise<KintoneSpace[]> {
// Since SDK doesn't have getSpaces and REST API doesn't support listing spaces,
// we return empty array. Users should use getSpace() for individual spaces.
return [];
}
async getSpace(spaceId: string): Promise<KintoneSpace> {
return this.withErrorHandling(async () => { return this.withErrorHandling(async () => {
const response = await this.client.space.getSpaces(); const response = await this.client.space.getSpace({ id: spaceId });
return response.spaces.map((space) => this.mapSpace(space)); return this.mapSpace(response);
}); });
} }
@@ -171,7 +171,7 @@ export class KintoneClient {
async getApps(spaceId?: string): Promise<KintoneApp[]> { async getApps(spaceId?: string): Promise<KintoneApp[]> {
return this.withErrorHandling(async () => { return this.withErrorHandling(async () => {
const params = spaceId ? { spaceId } : {}; const params = spaceId ? { spaceIds: [spaceId] } : {};
const response = await this.client.app.getApps(params); const response = await this.client.app.getApps(params);
return response.apps.map((app) => this.mapApp(app)); return response.apps.map((app) => this.mapApp(app));
}); });
@@ -186,28 +186,26 @@ export class KintoneClient {
const customization: AppCustomizationConfig = { const customization: AppCustomizationConfig = {
javascript: { javascript: {
pc: pc: customizeInfo.desktop.js?.map((js) => this.mapResource(js)) || [],
customizeInfo.desktop?.js?.map((js) => this.mapResource(js)) || [],
mobile: mobile:
customizeInfo.mobile?.js?.map((js) => this.mapResource(js)) || [], customizeInfo.mobile.js?.map((js) => this.mapResource(js)) || [],
}, },
stylesheet: { stylesheet: {
pc: pc:
customizeInfo.desktop?.css?.map((css) => this.mapResource(css)) || customizeInfo.desktop.css?.map((css) => this.mapResource(css)) ||
[], [],
mobile: mobile:
customizeInfo.mobile?.css?.map((css) => this.mapResource(css)) || customizeInfo.mobile.css?.map((css) => this.mapResource(css)) || [],
[],
}, },
plugins: [], plugins: [],
}; };
return { return {
appId: String(appInfo.appId), appId: appInfo.appId,
name: appInfo.name, name: appInfo.name,
code: appInfo.code, code: appInfo.code,
description: appInfo.description, description: appInfo.description,
spaceId: appInfo.spaceId ? String(appInfo.spaceId) : undefined, spaceId: appInfo.spaceId || undefined,
createdAt: appInfo.createdAt, createdAt: appInfo.createdAt,
creator: appInfo.creator, creator: appInfo.creator,
modifiedAt: appInfo.modifiedAt, modifiedAt: appInfo.modifiedAt,
@@ -257,14 +255,10 @@ export class KintoneClient {
return this.withErrorHandling(async () => { return this.withErrorHandling(async () => {
await this.client.app.updateAppCustomize({ await this.client.app.updateAppCustomize({
app: appId, app: appId,
desktop: this.buildCustomizeSection( ...this.buildCustomizeSection(
config.javascript?.pc, config.javascript?.pc,
config.stylesheet?.pc, config.stylesheet?.pc,
), ),
mobile: this.buildCustomizeSection(
config.javascript?.mobile,
config.stylesheet?.mobile,
),
scope: "ALL", scope: "ALL",
}); });
}); });
@@ -280,7 +274,7 @@ export class KintoneClient {
appId: string, appId: string,
): Promise<"PROCESSING" | "SUCCESS" | "FAIL" | "CANCEL"> { ): Promise<"PROCESSING" | "SUCCESS" | "FAIL" | "CANCEL"> {
return this.withErrorHandling(async () => { return this.withErrorHandling(async () => {
const response = await this.client.app.getDeployStatus({ app: appId }); const response = await this.client.app.getDeployStatus({ apps: [appId] });
return response.apps[0]?.status || "FAIL"; return response.apps[0]?.status || "FAIL";
}); });
} }
@@ -305,12 +299,8 @@ export class KintoneClient {
} }
} }
type CustomizeResourceItem = { export function createKintoneClient(
type: string; domain: DomainWithPassword,
file?: { fileKey: string }; ): SelfKintoneClient {
url?: string; return new SelfKintoneClient(domain);
};
export function createKintoneClient(domain: DomainWithPassword): KintoneClient {
return new KintoneClient(domain);
} }

View File

@@ -27,11 +27,11 @@ import type { Version } from "@shared/types/version";
declare global { declare global {
interface Window { interface Window {
electron: ElectronAPI; electron: ElectronAPI;
api: ElectronAPI; api: SelfAPI;
} }
} }
export interface ElectronAPI { export interface SelfAPI {
// Platform detection // Platform detection
platform: NodeJS.Platform; platform: NodeJS.Platform;

View File

@@ -1,9 +1,9 @@
import { contextBridge, ipcRenderer } from "electron"; import { contextBridge, ipcRenderer } from "electron";
import { electronAPI } from "@electron-toolkit/preload"; import { electronAPI } from "@electron-toolkit/preload";
import type { ElectronAPI } from "./index.d"; import type { SelfAPI } from "./index.d";
// Custom APIs for renderer - bridges to IPC handlers // Custom APIs for renderer - bridges to IPC handlers
const api: ElectronAPI = { const api: SelfAPI = {
// Platform detection // Platform detection
platform: process.platform, platform: process.platform,

View File

@@ -5,7 +5,6 @@
import React from "react"; import React from "react";
import { import {
Card,
Descriptions, Descriptions,
Tabs, Tabs,
Empty, Empty,
@@ -25,6 +24,7 @@ import { createStyles } from "antd-style";
import { useAppStore } from "@renderer/stores"; import { useAppStore } from "@renderer/stores";
import { useDomainStore } from "@renderer/stores"; import { useDomainStore } from "@renderer/stores";
import { CodeViewer } from "../CodeViewer"; import { CodeViewer } from "../CodeViewer";
import { JSFileConfig, CSSFileConfig } from "@shared/types/kintone";
const useStyles = createStyles(({ token, css }) => ({ const useStyles = createStyles(({ token, css }) => ({
container: css` container: css`

View File

@@ -38,8 +38,8 @@ export interface JSFileConfig {
type: "FILE" | "URL"; type: "FILE" | "URL";
file?: { file?: {
fileKey: string; fileKey: string;
name: string; name?: string; // Optional for deploy, filled by Kintone
size: number; size?: number; // Optional for deploy, filled by Kintone
}; };
url?: string; url?: string;
} }
@@ -48,8 +48,8 @@ export interface CSSFileConfig {
type: "FILE" | "URL"; type: "FILE" | "URL";
file?: { file?: {
fileKey: string; fileKey: string;
name: string; name?: string; // Optional for deploy, filled by Kintone
size: number; size?: number; // Optional for deploy, filled by Kintone
}; };
url?: string; url?: string;
} }