update main ts

This commit is contained in:
2026-03-12 23:03:01 +08:00
parent 4a8cd53617
commit f53f43a6b9
4 changed files with 48 additions and 111 deletions

View File

@@ -38,6 +38,7 @@ import type {
DownloadMetadata,
BackupMetadata,
} from "@shared/types/version";
import type { AppCustomizeResponse } from "@shared/types/kintone";
// Cache for Kintone clients
const clientCache = new Map<string, SelfKintoneClient>();
@@ -317,7 +318,7 @@ function registerDeploy(): void {
const backupFileList: BackupMetadata["files"] = [];
// Add JS files to backup
for (const js of appDetail.customization?.javascript?.pc || []) {
for (const js of appDetail.customization?.desktop?.js || []) {
if (js.file?.fileKey) {
const fileContent = await client.getFileContent(js.file.fileKey);
const content = Buffer.from(fileContent.content || "", "base64");
@@ -334,7 +335,7 @@ function registerDeploy(): void {
}
// Add CSS files to backup
for (const css of appDetail.customization?.stylesheet?.pc || []) {
for (const css of appDetail.customization?.desktop?.css || []) {
if (css.file?.fileKey) {
const fileContent = await client.getFileContent(css.file.fileKey);
const content = Buffer.from(fileContent.content || "", "base64");
@@ -349,7 +350,6 @@ function registerDeploy(): void {
});
}
}
// Save backup
const backupMetadata: BackupMetadata = {
backedUpAt: new Date().toISOString(),
@@ -382,39 +382,40 @@ function registerDeploy(): void {
// Build new customization config
// Note: This is simplified - real implementation would merge with existing config
const newConfig = {
javascript: {
pc: uploadedFiles
const newConfig: AppCustomizeResponse = {
desktop: {
js: uploadedFiles
.filter((f) => f.type === "js" && f.position.startsWith("pc_"))
.map((f) => ({
type: "FILE" as const,
file: { fileKey: f.fileKey },
})),
mobile: uploadedFiles
.filter((f) => f.type === "js" && f.position.startsWith("mobile_"))
.map((f) => ({
type: "FILE" as const,
file: { fileKey: f.fileKey },
})),
},
stylesheet: {
pc: uploadedFiles
css: uploadedFiles
.filter((f) => f.type === "css" && f.position === "pc_css")
.map((f) => ({
type: "FILE" as const,
file: { fileKey: f.fileKey },
})),
mobile: uploadedFiles
},
mobile: {
js: uploadedFiles
.filter((f) => f.type === "js" && f.position.startsWith("mobile_"))
.map((f) => ({
type: "FILE" as const,
file: { fileKey: f.fileKey },
})),
css: uploadedFiles
.filter((f) => f.type === "css" && f.position === "mobile_css")
.map((f) => ({
type: "FILE" as const,
file: { fileKey: f.fileKey },
})),
},
scope: "ALL",
revision: "-1",
};
// Update app customization
await client.updateAppCustomize(params.appId, newConfig);
// Deploy the changes
await client.deployApp(params.appId);
@@ -458,12 +459,12 @@ function registerDownload(): void {
for (const fileType of fileTypes) {
const files =
fileType === "pc_js"
? appDetail.customization?.javascript?.pc
? appDetail.customization?.desktop?.js
: fileType === "pc_css"
? appDetail.customization?.stylesheet?.pc
? appDetail.customization?.desktop?.css
: fileType === "mobile_js"
? appDetail.customization?.javascript?.mobile
: appDetail.customization?.stylesheet?.mobile;
? appDetail.customization?.mobile?.js
: appDetail.customization?.mobile?.css;
for (const file of files || []) {
if (file.file?.fileKey) {

View File

@@ -3,11 +3,9 @@ import type { KintoneRestAPIError } from "@kintone/rest-api-client";
import type { DomainWithPassword } from "@shared/types/domain";
import type {
AppResponse,
AppsResponse,
AppCustomizeResponse,
AppDetail,
FileContent,
AppCustomizationConfig,
KintoneApiError,
FileConfig,
} from "@shared/types/kintone";
@@ -82,34 +80,19 @@ export class SelfKintoneClient {
}
}
private mapResource(
resource:
| Awaited<AppCustomizeResponse>["desktop"]["js"][number]
| Awaited<AppCustomizeResponse>["desktop"]["css"][number],
): FileConfig {
// Return SDK type directly - no conversion needed
return resource;
}
private buildCustomizeSection(
js?: FileConfig[],
css?: FileConfig[],
): Parameters<
KintoneRestAPIClient["app"]["updateAppCustomize"]
>[0]["desktop"] {
if (!js && !css) return undefined;
files?: FileConfig[],
): NonNullable<
Parameters<KintoneRestAPIClient["app"]["updateAppCustomize"]>[0]["desktop"]
>["js"] {
if (!files || files.length === 0) return undefined;
const mapItem = (item: FileConfig) => {
return files.map((item) => {
if (item.type === "FILE" && item.file) {
return { type: "FILE" as const, file: { fileKey: item.file.fileKey } };
}
return { type: "URL" as const, url: item.url || "" };
};
return {
js: js?.map(mapItem),
css: css?.map(mapItem),
};
});
}
// ==================== App APIs ====================
@@ -161,32 +144,9 @@ export class SelfKintoneClient {
this.client.app.getAppCustomize({ app: appId }),
]);
const customization: AppCustomizationConfig = {
javascript: {
pc: customizeInfo.desktop.js?.map((js) => this.mapResource(js)) || [],
mobile:
customizeInfo.mobile.js?.map((js) => this.mapResource(js)) || [],
},
stylesheet: {
pc:
customizeInfo.desktop.css?.map((css) => this.mapResource(css)) ||
[],
mobile:
customizeInfo.mobile.css?.map((css) => this.mapResource(css)) || [],
},
};
return {
appId: appInfo.appId,
name: appInfo.name,
code: appInfo.code,
description: appInfo.description,
spaceId: appInfo.spaceId || undefined,
createdAt: appInfo.createdAt,
creator: appInfo.creator,
modifiedAt: appInfo.modifiedAt,
modifier: appInfo.modifier,
customization,
...appInfo,
customization: customizeInfo,
};
});
}
@@ -226,20 +186,20 @@ export class SelfKintoneClient {
async updateAppCustomize(
appId: string,
config: AppCustomizationConfig,
config: AppCustomizeResponse,
): Promise<void> {
return this.withErrorHandling(async () => {
await this.client.app.updateAppCustomize({
app: appId,
desktop: this.buildCustomizeSection(
config.javascript?.pc,
config.stylesheet?.pc,
),
mobile: this.buildCustomizeSection(
config.javascript?.mobile,
config.stylesheet?.mobile,
),
scope: "ALL",
desktop: {
js: this.buildCustomizeSection(config.desktop?.js),
css: this.buildCustomizeSection(config.desktop?.css),
},
mobile: {
js: this.buildCustomizeSection(config.mobile?.js),
css: this.buildCustomizeSection(config.mobile?.css),
},
scope: config.scope || "ALL",
});
});
}

View File

@@ -282,7 +282,7 @@ const AppDetail: React.FC = () => {
key: "pc-js",
label: "PC端 JS",
children: renderFileList(
currentApp.customization?.javascript?.pc,
currentApp.customization?.desktop?.js,
"js",
),
},
@@ -290,7 +290,7 @@ const AppDetail: React.FC = () => {
key: "pc-css",
label: "PC端 CSS",
children: renderFileList(
currentApp.customization?.stylesheet?.pc,
currentApp.customization?.desktop?.css,
"css",
),
},
@@ -298,7 +298,7 @@ const AppDetail: React.FC = () => {
key: "mobile-js",
label: "移动端 JS",
children: renderFileList(
currentApp.customization?.javascript?.mobile,
currentApp.customization?.mobile?.js,
"js",
),
},
@@ -306,7 +306,7 @@ const AppDetail: React.FC = () => {
key: "mobile-css",
label: "移动端 CSS",
children: renderFileList(
currentApp.customization?.stylesheet?.mobile,
currentApp.customization?.mobile?.css,
"css",
),
},

View File

@@ -12,19 +12,11 @@ type KintoneClient = KintoneRestAPIClient;
/** App response from getApp/getApps */
export type AppResponse = Awaited<ReturnType<KintoneClient["app"]["getApp"]>>;
/** Apps list response */
export type AppsResponse = Awaited<ReturnType<KintoneClient["app"]["getApps"]>>;
/** App customization response */
export type AppCustomizeResponse = Awaited<
ReturnType<KintoneClient["app"]["getAppCustomize"]>
>;
/** File upload response */
export type FileUploadResponse = Awaited<
ReturnType<KintoneClient["file"]["uploadFile"]>
>;
// ==================== Custom Business Types ====================
// These types represent business-layer aggregation or additional metadata
@@ -33,7 +25,7 @@ export type FileUploadResponse = Awaited<
* This is a business-layer type that aggregates data from multiple API calls
*/
export interface AppDetail extends AppResponse {
customization?: AppCustomizationConfig;
customization?: AppCustomizeResponse;
}
/**
@@ -48,27 +40,11 @@ export interface FileContent {
content?: string; // Base64 encoded or text
}
/**
* App customization config
* Uses SDK's customize types structure (desktop/mobile) but simplified for internal use
* Note: SDK uses { js: [], css: [] } but we use { javascript: { pc, mobile } } for easier UI binding
*/
export interface AppCustomizationConfig {
javascript?: {
pc?: FileConfig[];
mobile?: FileConfig[];
};
stylesheet?: {
pc?: FileConfig[];
mobile?: FileConfig[];
};
}
/**
* File config for customization
* Using SDK's type directly from AppCustomizeResponse
*/
export type FileConfig = Awaited<AppCustomizeResponse>["desktop"]["js"][number];
export type FileConfig = NonNullable<AppCustomizeResponse["desktop"]["js"]>[number];
/**
* API Error - simplified from SDK's KintoneRestAPIError