cs2schema
Version:
A TypeScript SDK for Counter-Strike 2 schema data with ID/name resolution utilities
321 lines (320 loc) • 12.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.CS2SchemaSDK = void 0;
const fs_1 = require("fs");
const path_1 = require("path");
class CS2SchemaSDK {
constructor(schemaPath) {
this.nameToIdMaps = new Map();
this.searchCache = new Map();
this.initialized = false;
this.categories = [
"stickers",
"keychains",
"collectibles",
"containers",
"agents",
"custom_stickers",
"music_kits",
"weapons",
];
const defaultPath = schemaPath || (0, path_1.join)(__dirname, "..", "schema.json");
const resolvedPath = defaultPath;
try {
const schemaData = (0, fs_1.readFileSync)(resolvedPath, "utf-8");
this.schema = JSON.parse(schemaData);
this.processedSchema = this.processSchema(this.schema);
this.buildNameToIdMaps();
this.initialized = true;
}
catch (error) {
throw new Error(`Failed to load schema from ${resolvedPath}: ${error}`);
}
}
processSchema(schema) {
const processed = JSON.parse(JSON.stringify(schema));
const processedWeapons = {};
Object.entries(schema.weapons).forEach(([weaponId, weapon]) => {
Object.entries(weapon.paints).forEach(([paintId, paint]) => {
const compositeId = `${weaponId}-${paintId}`;
const weaponName = weapon.type === "Knives" ? `★ ${weapon.name}` : weapon.name;
processedWeapons[compositeId] = {
...paint,
market_hash_name: `${weaponName} | ${paint.name}`,
};
});
});
processed.weapons = processedWeapons;
return processed;
}
buildNameToIdMaps() {
this.categories.forEach((category) => {
const nameToIdMap = new Map();
const categoryData = this.processedSchema[category];
if (categoryData) {
Object.entries(categoryData).forEach(([id, item]) => {
if (item && typeof item === "object" && "market_hash_name" in item) {
const name = item.market_hash_name.toLowerCase();
nameToIdMap.set(name, id);
}
});
}
this.nameToIdMaps.set(category, nameToIdMap);
});
}
clearCache() {
this.searchCache.clear();
}
searchItems(query, options = {}) {
if (!this.initialized) {
throw new Error("SDK not properly initialized");
}
const cacheKey = `${query}:${JSON.stringify(options)}`;
if (this.searchCache.has(cacheKey)) {
return this.searchCache.get(cacheKey);
}
const { caseSensitive = false, category, exactMatch = false } = options;
const results = [];
const searchQuery = caseSensitive ? query : query.toLowerCase();
const categoriesToSearch = category
? [category]
: this.categories;
categoriesToSearch.forEach((cat) => {
const categoryData = this.processedSchema[cat];
if (!categoryData)
return;
Object.entries(categoryData).forEach(([id, item]) => {
if (item && typeof item === "object" && "market_hash_name" in item) {
const itemName = caseSensitive
? item.market_hash_name
: item.market_hash_name.toLowerCase();
const match = exactMatch
? itemName === searchQuery
: itemName.includes(searchQuery);
if (match) {
results.push({
id,
item: item,
category: cat,
});
}
}
});
});
this.searchCache.set(cacheKey, results);
return results;
}
resolveIdToName(id, category) {
if (!this.initialized) {
throw new Error("SDK not properly initialized");
}
const categoryData = this.processedSchema[category];
if (!categoryData || !(id in categoryData)) {
return null;
}
const item = categoryData[id];
return item && typeof item === "object" && "market_hash_name" in item
? item.market_hash_name
: null;
}
resolveNameToId(name, category, options = {}) {
if (!this.initialized) {
throw new Error("SDK not properly initialized");
}
const { caseSensitive = false, exactMatch = true } = options;
const nameToIdMap = this.nameToIdMaps.get(category);
if (!nameToIdMap) {
return null;
}
const searchName = caseSensitive ? name : name.toLowerCase();
if (exactMatch) {
return nameToIdMap.get(searchName) || null;
}
for (const [itemName, id] of nameToIdMap) {
if (itemName.includes(searchName)) {
return id;
}
}
return null;
}
getItemById(id, category) {
if (!this.initialized) {
throw new Error("SDK not properly initialized");
}
const categoryData = this.processedSchema[category];
if (!categoryData || !(id in categoryData)) {
return null;
}
const item = categoryData[id];
return {
id,
item,
category,
};
}
getItemByName(name, category, options = {}) {
const id = this.resolveNameToId(name, category, options);
if (!id) {
return null;
}
return this.getItemById(id, category);
}
searchSkins(query, options = {}) {
if (!this.initialized) {
throw new Error("SDK not properly initialized");
}
const results = this.searchItems(query, {
...options,
category: "weapons",
});
return results.map((result) => {
const [weaponId] = result.id.split("-");
return {
...result,
weaponId: weaponId || "",
};
});
}
getCollections() {
if (!this.initialized) {
throw new Error("SDK not properly initialized");
}
return this.schema.collections || [];
}
getRarities() {
if (!this.initialized) {
throw new Error("SDK not properly initialized");
}
return this.schema.rarities || [];
}
getCollectionByKey(key) {
const collections = this.getCollections();
return collections.find((col) => col.key === key) || null;
}
getRarityByKey(key) {
const rarities = this.getRarities();
return rarities.find((rarity) => rarity.key === key) || null;
}
getAllItemsInCategory(category) {
if (!this.initialized) {
throw new Error("SDK not properly initialized");
}
const categoryData = this.processedSchema[category];
if (!categoryData) {
return [];
}
return Object.entries(categoryData).map(([id, item]) => ({
id,
item: item,
category,
}));
}
getCategoryStats() {
if (!this.initialized) {
throw new Error("SDK not properly initialized");
}
const stats = {};
this.categories.forEach((category) => {
const categoryData = this.processedSchema[category];
stats[category] = categoryData ? Object.keys(categoryData).length : 0;
});
return stats;
}
isInitialized() {
return this.initialized;
}
getSchema() {
if (!this.initialized) {
throw new Error("SDK not properly initialized");
}
return this.processedSchema;
}
getAllCharmNames() {
if (!this.initialized) {
throw new Error("SDK not properly initialized");
}
const keychainData = this.processedSchema.keychains;
if (!keychainData) {
return [];
}
return Object.values(keychainData)
.filter((item) => item && typeof item === "object" && "market_hash_name" in item)
.map((item) => item.market_hash_name);
}
getWeaponWearStates() {
return [
{ name: "Factory New", minFloat: 0.0, maxFloat: 0.07 },
{ name: "Minimal Wear", minFloat: 0.07, maxFloat: 0.15 },
{ name: "Field-Tested", minFloat: 0.15, maxFloat: 0.38 },
{ name: "Well-Worn", minFloat: 0.38, maxFloat: 0.45 },
{ name: "Battle-Scarred", minFloat: 0.45, maxFloat: 1.0 },
];
}
generateAllWeaponMarketHashNames(options = {}) {
if (!this.initialized) {
throw new Error("SDK not properly initialized");
}
const { includeSouvenir = true, includeStatTrak = true, specificCollections, } = options;
const wearStates = this.getWeaponWearStates();
const collections = this.getCollections();
const generatedNames = [];
Object.entries(this.schema.weapons).forEach(([, weapon]) => {
const weaponName = weapon.type === "Knives" ? `★ ${weapon.name}` : weapon.name;
Object.entries(weapon.paints).forEach(([, paint]) => {
const baseName = `${weaponName} | ${paint.name}`;
const collection = paint.collection;
if (specificCollections &&
collection &&
!specificCollections.includes(collection)) {
return;
}
const collectionData = collections.find((col) => col.key === collection);
const isSouvenirEligible = collectionData?.has_souvenir || false;
wearStates.forEach((wearState) => {
const fullName = `${baseName} (${wearState.name})`;
generatedNames.push({
baseName,
wearState: wearState.name,
fullName,
minFloat: wearState.minFloat,
maxFloat: wearState.maxFloat,
collection,
isSouvenir: false,
});
if (includeStatTrak) {
const statTrakName = `StatTrak™ ${fullName}`;
generatedNames.push({
baseName: `StatTrak™ ${baseName}`,
wearState: wearState.name,
fullName: statTrakName,
minFloat: wearState.minFloat,
maxFloat: wearState.maxFloat,
collection,
isSouvenir: false,
});
}
if (includeSouvenir && isSouvenirEligible) {
const souvenirName = `Souvenir ${fullName}`;
generatedNames.push({
baseName: `Souvenir ${baseName}`,
wearState: wearState.name,
fullName: souvenirName,
minFloat: wearState.minFloat,
maxFloat: wearState.maxFloat,
collection,
isSouvenir: true,
});
}
});
});
});
return generatedNames;
}
generateWeaponMarketHashNamesByCollection(collectionKey, options = {}) {
return this.generateAllWeaponMarketHashNames({
...options,
specificCollections: [collectionKey],
});
}
}
exports.CS2SchemaSDK = CS2SchemaSDK;