feat: decorating the backroom #604

Merged
Sainan merged 4 commits from tailorshop into main 2024-12-22 11:32:19 -08:00
6 changed files with 103 additions and 13 deletions

View File

@ -27,7 +27,8 @@ export const getShipController: RequestHandler = async (req, res) => {
SkinFlavourItem: ship.SkinFlavourItem
}
},
Apartment: personalRooms.Apartment
Apartment: personalRooms.Apartment,
TailorShop: personalRooms.TailorShop
};
if (config.unlockAllShipFeatures) {

View File

@ -13,7 +13,7 @@ export const shipDecorationsController: RequestHandler = async (req, res) => {
res.send(placedDecoration);
} catch (error: unknown) {
if (error instanceof Error) {
logger.error(`error in saveLoadoutController: ${error.message}`);
logger.error(`error in shipDecorationsController: ${error.message}`);
res.status(400).json({ error: error.message });
}
}

View File

@ -1,6 +1,14 @@
import { toOid } from "@/src/helpers/inventoryHelpers";
import { IOrbiter, IPersonalRooms, PersonalRoomsModelType } from "@/src/types/personalRoomsTypes";
import { IApartment, IGardening, IPlacedDecosDatabase, IPictureFrameInfo } from "@/src/types/shipTypes";
import {
IApartment,
IFavouriteLoadoutDatabase,
IGardening,
IPlacedDecosDatabase,
IPictureFrameInfo,
IRoom,
ITailorShopDatabase
} from "@/src/types/shipTypes";
import { Schema, model } from "mongoose";
const pictureFrameInfoSchema = new Schema<IPictureFrameInfo>(
@ -44,7 +52,7 @@ placedDecosSchema.set("toJSON", {
}
});
const roomSchema = new Schema(
const roomSchema = new Schema<IRoom>(
{
Name: String,
MaxCapacity: Number,
@ -76,11 +84,59 @@ const orbiterSchema = new Schema<IOrbiter>(
{ _id: false }
);
const favouriteLoadoutSchema = new Schema<IFavouriteLoadoutDatabase>(
{
Tag: String,
LoadoutId: Schema.Types.ObjectId
},
{ _id: false }
);
favouriteLoadoutSchema.set("toJSON", {
virtuals: true,
transform(_document, returnedObject) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
returnedObject.LoadoutId = toOid(returnedObject.LoadoutId);
}
});
const tailorShopSchema = new Schema<ITailorShopDatabase>(
{
FavouriteLoadouts: [favouriteLoadoutSchema],
CustomJson: String,
LevelDecosVisible: Boolean,
Rooms: [roomSchema]
},
{ _id: false }
);
const tailorShopDefault: ITailorShopDatabase = {
FavouriteLoadouts: [],
CustomJson: "{}",
LevelDecosVisible: true,
Rooms: [
{
Name: "LabRoom",
MaxCapacity: 4000
},
{
Name: "LivingQuartersRoom",
MaxCapacity: 3000
},
{
Name: "HelminthRoom",
MaxCapacity: 2000
}
]
};
export const personalRoomsSchema = new Schema<IPersonalRooms>({
personalRoomsOwnerId: Schema.Types.ObjectId,
activeShipId: Schema.Types.ObjectId,
Ship: orbiterSchema,
Apartment: apartmentSchema
Apartment: apartmentSchema,
TailorShop: {
type: tailorShopSchema,
default: tailorShopDefault as any as undefined // Yeah, this is bad, but mongoose types here are wrong.
coderabbitai[bot] commented 2024-12-22 11:28:29 -08:00 (Migrated from github.com)
Review

💡 Codebase verification

CustomJson field requires schema validation and type safety improvements

Based on the codebase analysis, the CustomJson field appears to be a string type that's intended to store JSON data, but lacks proper validation and type safety:

  • It's defined as a String in the mongoose schema (CustomJson: String)
  • It has a default string value of "{}" rather than an actual object
  • No evidence of JSON parsing/stringifying operations or validation
  • No documentation or tests found explaining its purpose

Recommendations:

  • Define proper JSON schema validation for this field
  • Consider using a proper object type instead of string if storing structured data
  • Add documentation explaining the expected structure and purpose
🔗 Analysis chain

Verify the purpose of CustomJson default value.

The default value of "{}" for CustomJson seems unusual. Consider:

  1. Is this meant to be a valid JSON string?
  2. Should it be stored as an object instead of a string?

Let me gather more context about the CustomJson field usage in the codebase.


Let me try one more search to understand if this field is used in any API endpoints or data transformations.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for CustomJson usage to understand its purpose
rg -A 5 "CustomJson" --type ts

Length of output: 994


Script:

#!/bin/bash
# Search for any parsing or manipulation of CustomJson
rg -A 5 -B 5 'CustomJson.*=|\.CustomJson' --type ts

# Look for any tests or documentation
fd -e md -e test.ts -X rg -l "CustomJson"

Length of output: 95


Script:

#!/bin/bash
# Search for files containing both "CustomJson" and common data manipulation patterns
rg -l "CustomJson" --type ts | xargs rg -A 5 -B 5 "JSON\.|parse|stringify"

# Look for any API endpoints or routes that might handle this field
ast-grep --pattern 'router.$_($_, async function ($_, $_) {
  $$$
  CustomJson
  $$$
})'

Length of output: 165

_:bulb: Codebase verification_ **CustomJson field requires schema validation and type safety improvements** Based on the codebase analysis, the CustomJson field appears to be a string type that's intended to store JSON data, but lacks proper validation and type safety: - It's defined as a String in the mongoose schema (`CustomJson: String`) - It has a default string value of "{}" rather than an actual object - No evidence of JSON parsing/stringifying operations or validation - No documentation or tests found explaining its purpose Recommendations: - Define proper JSON schema validation for this field - Consider using a proper object type instead of string if storing structured data - Add documentation explaining the expected structure and purpose <details> <summary>🔗 Analysis chain</summary> **Verify the purpose of CustomJson default value.** The default value of `"{}"` for CustomJson seems unusual. Consider: 1. Is this meant to be a valid JSON string? 2. Should it be stored as an object instead of a string? --- Let me gather more context about the CustomJson field usage in the codebase. --- Let me try one more search to understand if this field is used in any API endpoints or data transformations. </details> <details> <summary>🏁 Scripts executed</summary> The following scripts were executed for the analysis: Script: ```shell #!/bin/bash # Search for CustomJson usage to understand its purpose rg -A 5 "CustomJson" --type ts ``` Length of output: 994 --- Script: ```shell #!/bin/bash # Search for any parsing or manipulation of CustomJson rg -A 5 -B 5 'CustomJson.*=|\.CustomJson' --type ts # Look for any tests or documentation fd -e md -e test.ts -X rg -l "CustomJson" ``` Length of output: 95 --- Script: ```shell #!/bin/bash # Search for files containing both "CustomJson" and common data manipulation patterns rg -l "CustomJson" --type ts | xargs rg -A 5 -B 5 "JSON\.|parse|stringify" # Look for any API endpoints or routes that might handle this field ast-grep --pattern 'router.$_($_, async function ($_, $_) { $$$ CustomJson $$$ })' ``` Length of output: 165 </details> <!-- This is an auto-generated comment by CodeRabbit -->
}
});
export const PersonalRooms = model<IPersonalRooms, PersonalRoomsModelType>("PersonalRooms", personalRoomsSchema);

View File

@ -37,7 +37,12 @@ export const handleSetShipDecorations = async (
): Promise<IShipDecorationsResponse> => {
const personalRooms = await getPersonalRooms(accountId);
const rooms = placedDecoration.IsApartment ? personalRooms.Apartment.Rooms : personalRooms.Ship.Rooms;
const rooms =
placedDecoration.BootLocation == "SHOP"
? personalRooms.TailorShop.Rooms
: placedDecoration.IsApartment
? personalRooms.Apartment.Rooms
: personalRooms.Ship.Rooms;
const roomToPlaceIn = rooms.find(room => room.Name === placedDecoration.Room);

View File

@ -1,9 +1,9 @@
import { IApartment, IRooms, IPlacedDecosDatabase, TBootLocation } from "@/src/types/shipTypes";
import { IApartment, IRoom, IPlacedDecosDatabase, ITailorShop, TBootLocation } from "@/src/types/shipTypes";
import { Model, Types } from "mongoose";
export interface IOrbiter {
Features: string[];
Rooms: IRooms[];
Rooms: IRoom[];
ContentUrlSignature: string;
BootLocation?: TBootLocation;
}
@ -13,6 +13,7 @@ export interface IPersonalRooms {
activeShipId: Types.ObjectId;
Ship: IOrbiter;
Apartment: IApartment;
TailorShop: ITailorShop;
}
export type RoomsType = { Name: string; MaxCapacity: number; PlacedDecos: Types.DocumentArray<IPlacedDecosDatabase> };
@ -24,6 +25,9 @@ export type PersonalRoomsDocumentProps = {
Apartment: Omit<IApartment, "Rooms"> & {
Rooms: RoomsType[];
};
TailorShop: Omit<ITailorShop, "Rooms"> & {
Rooms: RoomsType[];
};
};
// eslint-disable-next-line @typescript-eslint/ban-types

View File

@ -7,6 +7,7 @@ export interface IGetShipResponse {
ShipOwnerId: string;
Ship: IShip;
Apartment: IApartment;
TailorShop: ITailorShop;
LoadOutInventory: { LoadOutPresets: ILoadoutClient };
}
@ -26,7 +27,7 @@ export interface IShip {
Features: string[];
ShipId: IOid;
ShipInterior: IShipInterior;
Rooms: IRooms[];
Rooms: IRoom[];
ContentUrlSignature: string;
BootLocation?: TBootLocation;
}
@ -41,7 +42,7 @@ export interface IShipDatabase {
SkinFlavourItem?: string;
}
export interface IRooms {
export interface IRoom {
Name: string;
MaxCapacity: number;
PlacedDecos?: IPlacedDecosDatabase[];
@ -62,7 +63,7 @@ export interface IGardening {
}
export interface IApartment {
Gardening: IGardening;
Rooms: IRooms[];
Rooms: IRoom[];
FavouriteLoadouts: string[];
}
@ -102,7 +103,8 @@ export interface IShipDecorationsRequest {
Pos: [number, number, number];
Rot: [number, number, number];
Room: string;
IsApartment: boolean;
BootLocation?: TBootLocation;
IsApartment?: boolean;
RemoveId?: string;
MoveId?: string;
OldRoom?: string;
@ -112,7 +114,7 @@ export interface IShipDecorationsRequest {
export interface IShipDecorationsResponse {
DecoId?: string;
Room?: string;
IsApartment: boolean;
IsApartment?: boolean;
MaxCapacityIncrease?: number;
OldRoom?: string;
NewRoom?: string;
@ -141,3 +143,25 @@ export interface IPictureFrameInfo {
TextColorB: number;
TextOrientation: number;
}
export interface IFavouriteLoadout {
Tag: string;
LoadoutId: IOid;
}
export interface IFavouriteLoadoutDatabase {
Tag: string;
LoadoutId: Types.ObjectId;
}
export interface ITailorShopDatabase {
FavouriteLoadouts: IFavouriteLoadoutDatabase[];
CustomJson: "{}"; // ???
LevelDecosVisible: boolean;
Rooms: IRoom[];
}
export interface ITailorShop extends Omit<ITailorShopDatabase, "FavouriteLoadouts"> {
FavouriteLoadouts: IFavouriteLoadout[];
Colors: []; // ???
}