update main ts
This commit is contained in:
@@ -38,6 +38,7 @@ import type {
|
|||||||
DownloadMetadata,
|
DownloadMetadata,
|
||||||
BackupMetadata,
|
BackupMetadata,
|
||||||
} from "@shared/types/version";
|
} from "@shared/types/version";
|
||||||
|
import type { AppCustomizeResponse } from "@shared/types/kintone";
|
||||||
|
|
||||||
// Cache for Kintone clients
|
// Cache for Kintone clients
|
||||||
const clientCache = new Map<string, SelfKintoneClient>();
|
const clientCache = new Map<string, SelfKintoneClient>();
|
||||||
@@ -317,7 +318,7 @@ function registerDeploy(): void {
|
|||||||
const backupFileList: BackupMetadata["files"] = [];
|
const backupFileList: BackupMetadata["files"] = [];
|
||||||
|
|
||||||
// Add JS files to backup
|
// 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) {
|
if (js.file?.fileKey) {
|
||||||
const fileContent = await client.getFileContent(js.file.fileKey);
|
const fileContent = await client.getFileContent(js.file.fileKey);
|
||||||
const content = Buffer.from(fileContent.content || "", "base64");
|
const content = Buffer.from(fileContent.content || "", "base64");
|
||||||
@@ -334,7 +335,7 @@ function registerDeploy(): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add CSS files to backup
|
// 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) {
|
if (css.file?.fileKey) {
|
||||||
const fileContent = await client.getFileContent(css.file.fileKey);
|
const fileContent = await client.getFileContent(css.file.fileKey);
|
||||||
const content = Buffer.from(fileContent.content || "", "base64");
|
const content = Buffer.from(fileContent.content || "", "base64");
|
||||||
@@ -349,7 +350,6 @@ function registerDeploy(): void {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save backup
|
// Save backup
|
||||||
const backupMetadata: BackupMetadata = {
|
const backupMetadata: BackupMetadata = {
|
||||||
backedUpAt: new Date().toISOString(),
|
backedUpAt: new Date().toISOString(),
|
||||||
@@ -382,39 +382,40 @@ function registerDeploy(): void {
|
|||||||
|
|
||||||
// Build new customization config
|
// Build new customization config
|
||||||
// Note: This is simplified - real implementation would merge with existing config
|
// Note: This is simplified - real implementation would merge with existing config
|
||||||
const newConfig = {
|
const newConfig: AppCustomizeResponse = {
|
||||||
javascript: {
|
desktop: {
|
||||||
pc: uploadedFiles
|
js: uploadedFiles
|
||||||
.filter((f) => f.type === "js" && f.position.startsWith("pc_"))
|
.filter((f) => f.type === "js" && f.position.startsWith("pc_"))
|
||||||
.map((f) => ({
|
.map((f) => ({
|
||||||
type: "FILE" as const,
|
type: "FILE" as const,
|
||||||
file: { fileKey: f.fileKey },
|
file: { fileKey: f.fileKey },
|
||||||
})),
|
})),
|
||||||
mobile: uploadedFiles
|
css: uploadedFiles
|
||||||
.filter((f) => f.type === "js" && f.position.startsWith("mobile_"))
|
|
||||||
.map((f) => ({
|
|
||||||
type: "FILE" as const,
|
|
||||||
file: { fileKey: f.fileKey },
|
|
||||||
})),
|
|
||||||
},
|
|
||||||
stylesheet: {
|
|
||||||
pc: uploadedFiles
|
|
||||||
.filter((f) => f.type === "css" && f.position === "pc_css")
|
.filter((f) => f.type === "css" && f.position === "pc_css")
|
||||||
.map((f) => ({
|
.map((f) => ({
|
||||||
type: "FILE" as const,
|
type: "FILE" as const,
|
||||||
file: { fileKey: f.fileKey },
|
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")
|
.filter((f) => f.type === "css" && f.position === "mobile_css")
|
||||||
.map((f) => ({
|
.map((f) => ({
|
||||||
type: "FILE" as const,
|
type: "FILE" as const,
|
||||||
file: { fileKey: f.fileKey },
|
file: { fileKey: f.fileKey },
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
|
scope: "ALL",
|
||||||
|
revision: "-1",
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update app customization
|
// Update app customization
|
||||||
await client.updateAppCustomize(params.appId, newConfig);
|
|
||||||
|
|
||||||
// Deploy the changes
|
// Deploy the changes
|
||||||
await client.deployApp(params.appId);
|
await client.deployApp(params.appId);
|
||||||
@@ -458,12 +459,12 @@ function registerDownload(): void {
|
|||||||
for (const fileType of fileTypes) {
|
for (const fileType of fileTypes) {
|
||||||
const files =
|
const files =
|
||||||
fileType === "pc_js"
|
fileType === "pc_js"
|
||||||
? appDetail.customization?.javascript?.pc
|
? appDetail.customization?.desktop?.js
|
||||||
: fileType === "pc_css"
|
: fileType === "pc_css"
|
||||||
? appDetail.customization?.stylesheet?.pc
|
? appDetail.customization?.desktop?.css
|
||||||
: fileType === "mobile_js"
|
: fileType === "mobile_js"
|
||||||
? appDetail.customization?.javascript?.mobile
|
? appDetail.customization?.mobile?.js
|
||||||
: appDetail.customization?.stylesheet?.mobile;
|
: appDetail.customization?.mobile?.css;
|
||||||
|
|
||||||
for (const file of files || []) {
|
for (const file of files || []) {
|
||||||
if (file.file?.fileKey) {
|
if (file.file?.fileKey) {
|
||||||
|
|||||||
@@ -3,11 +3,9 @@ import type { KintoneRestAPIError } from "@kintone/rest-api-client";
|
|||||||
import type { DomainWithPassword } from "@shared/types/domain";
|
import type { DomainWithPassword } from "@shared/types/domain";
|
||||||
import type {
|
import type {
|
||||||
AppResponse,
|
AppResponse,
|
||||||
AppsResponse,
|
|
||||||
AppCustomizeResponse,
|
AppCustomizeResponse,
|
||||||
AppDetail,
|
AppDetail,
|
||||||
FileContent,
|
FileContent,
|
||||||
AppCustomizationConfig,
|
|
||||||
KintoneApiError,
|
KintoneApiError,
|
||||||
FileConfig,
|
FileConfig,
|
||||||
} from "@shared/types/kintone";
|
} 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(
|
private buildCustomizeSection(
|
||||||
js?: FileConfig[],
|
files?: FileConfig[],
|
||||||
css?: FileConfig[],
|
): NonNullable<
|
||||||
): Parameters<
|
Parameters<KintoneRestAPIClient["app"]["updateAppCustomize"]>[0]["desktop"]
|
||||||
KintoneRestAPIClient["app"]["updateAppCustomize"]
|
>["js"] {
|
||||||
>[0]["desktop"] {
|
if (!files || files.length === 0) return undefined;
|
||||||
if (!js && !css) return undefined;
|
|
||||||
|
|
||||||
const mapItem = (item: FileConfig) => {
|
return files.map((item) => {
|
||||||
if (item.type === "FILE" && item.file) {
|
if (item.type === "FILE" && item.file) {
|
||||||
return { type: "FILE" as const, file: { fileKey: item.file.fileKey } };
|
return { type: "FILE" as const, file: { fileKey: item.file.fileKey } };
|
||||||
}
|
}
|
||||||
return { type: "URL" as const, url: item.url || "" };
|
return { type: "URL" as const, url: item.url || "" };
|
||||||
};
|
});
|
||||||
|
|
||||||
return {
|
|
||||||
js: js?.map(mapItem),
|
|
||||||
css: css?.map(mapItem),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== App APIs ====================
|
// ==================== App APIs ====================
|
||||||
@@ -161,32 +144,9 @@ export class SelfKintoneClient {
|
|||||||
this.client.app.getAppCustomize({ app: appId }),
|
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 {
|
return {
|
||||||
appId: appInfo.appId,
|
...appInfo,
|
||||||
name: appInfo.name,
|
customization: customizeInfo,
|
||||||
code: appInfo.code,
|
|
||||||
description: appInfo.description,
|
|
||||||
spaceId: appInfo.spaceId || undefined,
|
|
||||||
createdAt: appInfo.createdAt,
|
|
||||||
creator: appInfo.creator,
|
|
||||||
modifiedAt: appInfo.modifiedAt,
|
|
||||||
modifier: appInfo.modifier,
|
|
||||||
customization,
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -226,20 +186,20 @@ export class SelfKintoneClient {
|
|||||||
|
|
||||||
async updateAppCustomize(
|
async updateAppCustomize(
|
||||||
appId: string,
|
appId: string,
|
||||||
config: AppCustomizationConfig,
|
config: AppCustomizeResponse,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
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(
|
desktop: {
|
||||||
config.javascript?.pc,
|
js: this.buildCustomizeSection(config.desktop?.js),
|
||||||
config.stylesheet?.pc,
|
css: this.buildCustomizeSection(config.desktop?.css),
|
||||||
),
|
},
|
||||||
mobile: this.buildCustomizeSection(
|
mobile: {
|
||||||
config.javascript?.mobile,
|
js: this.buildCustomizeSection(config.mobile?.js),
|
||||||
config.stylesheet?.mobile,
|
css: this.buildCustomizeSection(config.mobile?.css),
|
||||||
),
|
},
|
||||||
scope: "ALL",
|
scope: config.scope || "ALL",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ const AppDetail: React.FC = () => {
|
|||||||
key: "pc-js",
|
key: "pc-js",
|
||||||
label: "PC端 JS",
|
label: "PC端 JS",
|
||||||
children: renderFileList(
|
children: renderFileList(
|
||||||
currentApp.customization?.javascript?.pc,
|
currentApp.customization?.desktop?.js,
|
||||||
"js",
|
"js",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@@ -290,7 +290,7 @@ const AppDetail: React.FC = () => {
|
|||||||
key: "pc-css",
|
key: "pc-css",
|
||||||
label: "PC端 CSS",
|
label: "PC端 CSS",
|
||||||
children: renderFileList(
|
children: renderFileList(
|
||||||
currentApp.customization?.stylesheet?.pc,
|
currentApp.customization?.desktop?.css,
|
||||||
"css",
|
"css",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@@ -298,7 +298,7 @@ const AppDetail: React.FC = () => {
|
|||||||
key: "mobile-js",
|
key: "mobile-js",
|
||||||
label: "移动端 JS",
|
label: "移动端 JS",
|
||||||
children: renderFileList(
|
children: renderFileList(
|
||||||
currentApp.customization?.javascript?.mobile,
|
currentApp.customization?.mobile?.js,
|
||||||
"js",
|
"js",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@@ -306,7 +306,7 @@ const AppDetail: React.FC = () => {
|
|||||||
key: "mobile-css",
|
key: "mobile-css",
|
||||||
label: "移动端 CSS",
|
label: "移动端 CSS",
|
||||||
children: renderFileList(
|
children: renderFileList(
|
||||||
currentApp.customization?.stylesheet?.mobile,
|
currentApp.customization?.mobile?.css,
|
||||||
"css",
|
"css",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -12,19 +12,11 @@ type KintoneClient = KintoneRestAPIClient;
|
|||||||
/** App response from getApp/getApps */
|
/** App response from getApp/getApps */
|
||||||
export type AppResponse = Awaited<ReturnType<KintoneClient["app"]["getApp"]>>;
|
export type AppResponse = Awaited<ReturnType<KintoneClient["app"]["getApp"]>>;
|
||||||
|
|
||||||
/** Apps list response */
|
|
||||||
export type AppsResponse = Awaited<ReturnType<KintoneClient["app"]["getApps"]>>;
|
|
||||||
|
|
||||||
/** App customization response */
|
/** App customization response */
|
||||||
export type AppCustomizeResponse = Awaited<
|
export type AppCustomizeResponse = Awaited<
|
||||||
ReturnType<KintoneClient["app"]["getAppCustomize"]>
|
ReturnType<KintoneClient["app"]["getAppCustomize"]>
|
||||||
>;
|
>;
|
||||||
|
|
||||||
/** File upload response */
|
|
||||||
export type FileUploadResponse = Awaited<
|
|
||||||
ReturnType<KintoneClient["file"]["uploadFile"]>
|
|
||||||
>;
|
|
||||||
|
|
||||||
// ==================== Custom Business Types ====================
|
// ==================== Custom Business Types ====================
|
||||||
// These types represent business-layer aggregation or additional metadata
|
// 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
|
* This is a business-layer type that aggregates data from multiple API calls
|
||||||
*/
|
*/
|
||||||
export interface AppDetail extends AppResponse {
|
export interface AppDetail extends AppResponse {
|
||||||
customization?: AppCustomizationConfig;
|
customization?: AppCustomizeResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,27 +40,11 @@ export interface FileContent {
|
|||||||
content?: string; // Base64 encoded or text
|
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
|
* File config for customization
|
||||||
* Using SDK's type directly from AppCustomizeResponse
|
* 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
|
* API Error - simplified from SDK's KintoneRestAPIError
|
||||||
|
|||||||
Reference in New Issue
Block a user