feat(cli): Update to gRPC v2

This commit is contained in:
Daniel López Guimaraes 2025-11-09 16:52:43 +00:00
parent 767730e42e
commit dd8ef4dde6
No known key found for this signature in database
GPG Key ID: 6AC74DE3DEF050E0
7 changed files with 45 additions and 28 deletions

View File

@ -20,6 +20,11 @@ const listCmd = new Command('ls')
if (key === 'name') {
return prettyTrunc(value, 20);
}
if (key === 'titleId') {
return value.toString(16).toLowerCase().padStart(16, '0');
}
return value;
}
});
@ -41,7 +46,7 @@ const viewCmd = new Command('view')
const obj = {
appId: app.bossAppId,
name: app.name,
titleId: app.titleId,
titleId: app.titleId.toString(16).toLowerCase().padStart(16, '0'),
titleRegion: app.titleRegion,
knownTasks: app.tasks
};

View File

@ -4,6 +4,7 @@ import { Readable } from 'node:stream';
import { request } from 'undici';
import { Command } from 'commander';
import { decryptWiiU } from '@pretendonetwork/boss-crypto';
import { PlatformType } from '@pretendonetwork/grpc/boss/v2/platform_type';
import { commandHandler, getCliContext } from './utils';
import { logOutputList, logOutputObject } from './output';
@ -14,7 +15,7 @@ const listCmd = new Command('ls')
.action(commandHandler<[string, string]>(async (cmd): Promise<void> => {
const [appId, taskId] = cmd.args;
const ctx = getCliContext();
const { files } = await ctx.grpc.listFiles({
const { files } = await ctx.grpc.listFilesWUP({
bossAppId: appId,
taskId: taskId
});
@ -38,7 +39,7 @@ const viewCmd = new Command('view')
.action(commandHandler<[string, string, bigint]>(async (cmd): Promise<void> => {
const [appId, taskId, dataId] = cmd.args;
const ctx = getCliContext();
const { files } = await ctx.grpc.listFiles({
const { files } = await ctx.grpc.listFilesWUP({
bossAppId: appId,
taskId: taskId
});
@ -76,7 +77,7 @@ const downloadCmd = new Command('download')
.action(commandHandler<[string, string, bigint]>(async (cmd): Promise<void> => {
const [appId, taskId, dataId] = cmd.args;
const ctx = getCliContext();
const { files } = await ctx.grpc.listFiles({
const { files } = await ctx.grpc.listFilesWUP({
bossAppId: appId,
taskId: taskId
});
@ -130,7 +131,7 @@ const createCmd = new Command('create')
const opts = cmd.opts<{ name: string; country: string[]; notifyNew: string[]; notifyLed: boolean; lang: string[]; nameAsId?: boolean; type: string; file: string }>();
const fileBuf = await fs.readFile(opts.file);
const ctx = getCliContext();
const { file } = await ctx.grpc.uploadFile({
const { file } = await ctx.grpc.uploadFileWUP({
taskId: taskId,
bossAppId: appId,
name: opts.name,
@ -160,7 +161,8 @@ const deleteCmd = new Command('delete')
const ctx = getCliContext();
await ctx.grpc.deleteFile({
bossAppId: appId,
dataId: dataId
dataId: dataId,
platformType: PlatformType.PLATFORM_TYPE_WUP
});
console.log(`Deleted task file with ID ${dataId}`);
}));

View File

@ -3,6 +3,7 @@ import fs from 'fs/promises';
import { Command } from 'commander';
import { xml2js } from 'xml-js';
import { decryptWiiU } from '@pretendonetwork/boss-crypto';
import { PlatformType } from '@pretendonetwork/grpc/boss/v2/platform_type';
import { getCliContext } from './utils';
import { seedFolder } from './root';
import type { CliContext } from './utils';
@ -31,7 +32,7 @@ export async function uploadFileIfChanged(ops: UploadFileOptions): Promise<void>
fileContents = decryptedContents.content;
}
const allExistingTaskFiles = await ops.ctx.grpc.listFiles({
const allExistingTaskFiles = await ops.ctx.grpc.listFilesWUP({
bossAppId: ops.bossAppId,
taskId: ops.taskId
});
@ -40,11 +41,12 @@ export async function uploadFileIfChanged(ops: UploadFileOptions): Promise<void>
console.warn(`${ops.dataId}: File already uploaded, reuploading`);
await ops.ctx.grpc.deleteFile({
bossAppId: ops.bossAppId,
dataId: BigInt(ops.dataId)
dataId: BigInt(ops.dataId),
platformType: PlatformType.PLATFORM_TYPE_WUP
});
}
await ops.ctx.grpc.uploadFile({
await ops.ctx.grpc.uploadFileWUP({
bossAppId: ops.bossAppId,
taskId: ops.taskId,
name: ops.fileXml.Filename._text,
@ -78,7 +80,7 @@ export async function processTasksheet(ctx: CliContext, taskFiles: string[], fil
await ctx.grpc.registerTask({
bossAppId: bossAppId,
id: taskName,
titleId: xmlContents.TaskSheet.TitleId._text,
titleId: BigInt(parseInt(xmlContents.TaskSheet.TitleId._text, 16)),
country: 'This value isnt used'
});
console.log(`${filename}: Created task`);
@ -87,7 +89,7 @@ export async function processTasksheet(ctx: CliContext, taskFiles: string[], fil
bossAppId: bossAppId,
id: taskName,
updateData: {
titleId: xmlContents.TaskSheet.TitleId._text,
titleId: BigInt(parseInt(xmlContents.TaskSheet.TitleId._text, 16)),
status: xmlContents.TaskSheet.ServiceStatus._text
}
});

View File

@ -38,7 +38,7 @@ const viewCmd = new Command('view')
taskId: task.id,
inGameId: task.inGameId,
description: task.description,
titleId: task.titleId,
titleId: task.titleId.toString(16).toLowerCase().padStart(16, '0'),
bossAppId: task.bossAppId,
creatorPid: task.creatorPid,
status: task.status,
@ -62,7 +62,7 @@ const createCmd = new Command('create')
const { task } = await ctx.grpc.registerTask({
bossAppId: appId,
id: opts.id,
titleId: opts.titleId,
titleId: BigInt(parseInt(opts.titleId, 16)),
description: opts.desc ?? '',
country: 'This value isnt used'
});

View File

@ -1,7 +1,7 @@
import { BOSSDefinition } from '@pretendonetwork/grpc/boss/boss_service';
import { BossServiceDefinition } from '@pretendonetwork/grpc/boss/v2/boss_service';
import { createChannel, createClient, Metadata } from 'nice-grpc';
import dotenv from 'dotenv';
import type { BOSSClient } from '@pretendonetwork/grpc/boss/boss_service';
import type { BossServiceClient } from '@pretendonetwork/grpc/boss/v2/boss_service';
import type { Command } from 'commander';
import type { FormatOption } from './output';
@ -12,7 +12,7 @@ export type NpdiUrl = {
};
export type CliContext = {
grpc: BOSSClient;
grpc: BossServiceClient;
getNpdiUrl: () => NpdiUrl;
getWiiUKeys: () => WiiUKeys;
};
@ -30,7 +30,7 @@ export function getCliContext(): CliContext {
}
const channel = createChannel(grpcHost);
const client: BOSSClient = createClient(BOSSDefinition, channel, {
const client: BossServiceClient = createClient(BossServiceDefinition, channel, {
'*': {
metadata: new Metadata({
'X-API-Key': grpcKey

View File

@ -61,6 +61,15 @@ export async function uploadFileCTR(request: UploadFileCTRRequest, context: Call
throw new ServerError(Status.INVALID_ARGUMENT, 'Cannot upload empty file');
}
if (!request.attributes) {
request.attributes = {
attribute1: '',
attribute2: '',
attribute3: '',
description: ''
};
}
const session = await databaseConnection().startSession();
await session.startTransaction();

View File

@ -78,6 +78,15 @@ export async function uploadFileWUP(request: UploadFileWUPRequest, context: Call
throw new ServerError(Status.INVALID_ARGUMENT, 'Cannot upload empty file');
}
if (!request.attributes) {
request.attributes = {
attribute1: '',
attribute2: '',
attribute3: '',
description: ''
};
}
let encryptedData: Buffer;
try {
@ -129,6 +138,7 @@ export async function uploadFileWUP(request: UploadFileWUPRequest, context: Call
file_key: key,
supported_countries: supportedCountries,
supported_languages: supportedLanguages,
attributes: request.attributes,
creator_pid: context.user?.pid,
name: name,
type: type,
@ -142,17 +152,6 @@ export async function uploadFileWUP(request: UploadFileWUPRequest, context: Call
updated: Date.now()
});
if (request.attributes) {
file.attributes = {
attribute1: request.attributes.attribute1,
attribute2: request.attributes.attribute2,
attribute3: request.attributes.attribute3,
description: request.attributes.description
};
await file.save();
}
if (nameEqualsDataID) {
file.name = file.data_id.toString(16).padStart(8, '0');
await file.save();