@dendotdev/grunt 1.0.4 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -951,6 +951,44 @@ var EconomyModule = class extends ModuleBase {
951
951
  `/hi/players/xuid(${player})/customization/appearance`
952
952
  );
953
953
  }
954
+ /**
955
+ * Get customization for multiple players.
956
+ *
957
+ * @param playerIds - List of player XUIDs
958
+ * @returns Player customization collection
959
+ */
960
+ getMultiplePlayersCustomization(playerIds) {
961
+ if (!playerIds.length) {
962
+ throw new Error("playerIds cannot be empty");
963
+ }
964
+ const formattedPlayers = playerIds.map((id) => `xuid(${id})`).join(",");
965
+ return this.get(`/hi/customization?players=${formattedPlayers}`);
966
+ }
967
+ // ─────────────────────────────────────────────────────────────────
968
+ // Cores
969
+ // ─────────────────────────────────────────────────────────────────
970
+ /**
971
+ * Get details about all owned cores for a player.
972
+ *
973
+ * @param player - Player's numeric XUID
974
+ * @returns All player cores
975
+ */
976
+ getAllOwnedCoresDetails(player) {
977
+ this.assertNotEmpty(player, "player");
978
+ return this.get(`/hi/players/xuid(${player})/cores`);
979
+ }
980
+ /**
981
+ * Get details about a specific owned core.
982
+ *
983
+ * @param player - Player's numeric XUID
984
+ * @param coreId - Core identifier
985
+ * @returns Core details
986
+ */
987
+ getOwnedCoreDetails(player, coreId) {
988
+ this.assertNotEmpty(player, "player");
989
+ this.assertNotEmpty(coreId, "coreId");
990
+ return this.get(`/hi/players/xuid(${player})/cores/${coreId}`);
991
+ }
954
992
  // ─────────────────────────────────────────────────────────────────
955
993
  // Stores
956
994
  // ─────────────────────────────────────────────────────────────────
@@ -1014,6 +1052,66 @@ var EconomyModule = class extends ModuleBase {
1014
1052
  this.assertNotEmpty(player, "player");
1015
1053
  return this.get(`/hi/players/xuid(${player})/stores/operations`);
1016
1054
  }
1055
+ /**
1056
+ * Get the operation reward levels store.
1057
+ *
1058
+ * @param player - Player's numeric XUID
1059
+ * @returns Store items
1060
+ */
1061
+ getOperationRewardLevelsStore(player) {
1062
+ this.assertNotEmpty(player, "player");
1063
+ return this.get(`/hi/players/xuid(${player})/stores/operationrewardlevels`);
1064
+ }
1065
+ /**
1066
+ * Get the XP grants store.
1067
+ *
1068
+ * @param player - Player's numeric XUID
1069
+ * @returns Store items
1070
+ */
1071
+ getXpGrantsStore(player) {
1072
+ this.assertNotEmpty(player, "player");
1073
+ return this.get(`/hi/players/xuid(${player})/stores/xpgrants`);
1074
+ }
1075
+ /**
1076
+ * Get items from a credit sub-store.
1077
+ *
1078
+ * Credit sub-stores (0-5) contain different categories of items
1079
+ * purchasable with credits.
1080
+ *
1081
+ * @param player - Player's numeric XUID
1082
+ * @param storeIndex - Sub-store index (0-5)
1083
+ * @returns Store items
1084
+ */
1085
+ getCreditSubStore(player, storeIndex) {
1086
+ this.assertNotEmpty(player, "player");
1087
+ if (storeIndex < 0 || storeIndex > 5) {
1088
+ throw new Error("storeIndex must be between 0 and 5");
1089
+ }
1090
+ const paddedIndex = storeIndex.toString().padStart(2, "0");
1091
+ return this.get(
1092
+ `/hi/players/xuid(${player})/stores/creditsubstorefront${paddedIndex}`
1093
+ );
1094
+ }
1095
+ /**
1096
+ * Get items from a soft currency (Spartan Points) sub-store.
1097
+ *
1098
+ * Soft currency sub-stores (0-15) contain different categories of items
1099
+ * purchasable with Spartan Points on The Exchange.
1100
+ *
1101
+ * @param player - Player's numeric XUID
1102
+ * @param storeIndex - Sub-store index (0-15)
1103
+ * @returns Store items
1104
+ */
1105
+ getSoftCurrencySubStore(player, storeIndex) {
1106
+ this.assertNotEmpty(player, "player");
1107
+ if (storeIndex < 0 || storeIndex > 15) {
1108
+ throw new Error("storeIndex must be between 0 and 15");
1109
+ }
1110
+ const paddedIndex = storeIndex.toString().padStart(2, "0");
1111
+ return this.get(
1112
+ `/hi/players/xuid(${player})/stores/softcurrencysubstorefront${paddedIndex}`
1113
+ );
1114
+ }
1017
1115
  /**
1018
1116
  * Get scheduled storefront offerings.
1019
1117
  *
@@ -1109,9 +1207,10 @@ var EconomyModule = class extends ModuleBase {
1109
1207
  throw new Error("playerIds cannot be empty");
1110
1208
  }
1111
1209
  this.assertNotEmpty(careerPathId, "careerPathId");
1112
- const playersQuery = playerIds.map((id) => `players=xuid(${id})`).join("&");
1210
+ const formattedPlayerList = playerIds.map((id) => `xuid(${id})`).join(",");
1113
1211
  return this.get(
1114
- `/hi/careerranks/${careerPathId}?${playersQuery}`
1212
+ `/hi/careerranks/${careerPathId}?players=${formattedPlayerList}`,
1213
+ { useClearance: true }
1115
1214
  );
1116
1215
  }
1117
1216
  };
@@ -1229,7 +1328,10 @@ var GameCmsModule = class extends ModuleBase {
1229
1328
  */
1230
1329
  getCareerRanks(careerPathId) {
1231
1330
  this.assertNotEmpty(careerPathId, "careerPathId");
1232
- return this.get(`/hi/Progression/file/careerranks/${careerPathId}`);
1331
+ return this.get(
1332
+ `/hi/Progression/file/RewardTracks/CareerRanks/${careerPathId}.json`,
1333
+ { useClearance: true }
1334
+ );
1233
1335
  }
1234
1336
  /**
1235
1337
  * Get the season calendar.
@@ -1270,7 +1372,7 @@ var GameCmsModule = class extends ModuleBase {
1270
1372
  * @returns Medal metadata
1271
1373
  */
1272
1374
  getMedalMetadata() {
1273
- return this.get("/hi/Progression/file/medals/metadata");
1375
+ return this.get("/hi/Waypoint/file/medals/metadata.json");
1274
1376
  }
1275
1377
  /**
1276
1378
  * Get general game metadata.
@@ -1339,6 +1441,232 @@ var GameCmsModule = class extends ModuleBase {
1339
1441
  this.assertNotEmpty(filePath, "filePath");
1340
1442
  return this.get(`/hi/Progression/file/${filePath}`);
1341
1443
  }
1444
+ // ─────────────────────────────────────────────────────────────────
1445
+ // Achievements & Settings
1446
+ // ─────────────────────────────────────────────────────────────────
1447
+ /**
1448
+ * Get all available achievements.
1449
+ *
1450
+ * @returns Achievement collection
1451
+ */
1452
+ getAchievements() {
1453
+ return this.get("/hi/Multiplayer/file/Live/Achievements.json");
1454
+ }
1455
+ /**
1456
+ * Get the Play Now button settings (fallback playlist).
1457
+ *
1458
+ * @returns Fallback playlist settings
1459
+ */
1460
+ getPlayNowButtonSettings() {
1461
+ return this.get(
1462
+ "/hi/Multiplayer/file/playlists/playNowButton/settings.json"
1463
+ );
1464
+ }
1465
+ /**
1466
+ * Get custom game default settings.
1467
+ *
1468
+ * @returns Custom game definition
1469
+ */
1470
+ getCustomGameDefaults() {
1471
+ return this.get("/hi/Multiplayer/file/NonMatchmaking/customgame.json");
1472
+ }
1473
+ /**
1474
+ * Get lobby error messages.
1475
+ *
1476
+ * @param flightId - Flight ID
1477
+ * @returns Lobby error message list
1478
+ */
1479
+ getLobbyErrorMessages(flightId) {
1480
+ this.assertNotEmpty(flightId, "flightId");
1481
+ return this.get(
1482
+ `/hi/Multiplayer/file/gameStartErrorMessages/LobbyHoppperErrorMessageList.json?flight=${flightId}`
1483
+ );
1484
+ }
1485
+ /**
1486
+ * Get network configuration.
1487
+ *
1488
+ * @param flightId - Flight ID
1489
+ * @returns Network configuration
1490
+ */
1491
+ getNetworkConfiguration(flightId) {
1492
+ this.assertNotEmpty(flightId, "flightId");
1493
+ return this.get(
1494
+ `/hi/Multiplayer/file/network/config.json?flight=${flightId}`
1495
+ );
1496
+ }
1497
+ /**
1498
+ * Get a multiplayer playlist configuration.
1499
+ *
1500
+ * @param playlistFile - Playlist file name (e.g., "uuid.json")
1501
+ * @returns Playlist configuration
1502
+ */
1503
+ getMultiplayerPlaylistConfiguration(playlistFile) {
1504
+ this.assertNotEmpty(playlistFile, "playlistFile");
1505
+ return this.get(
1506
+ `/hi/Multiplayer/file/playlists/assets/${playlistFile}`
1507
+ );
1508
+ }
1509
+ // ─────────────────────────────────────────────────────────────────
1510
+ // Graphics & Specs
1511
+ // ─────────────────────────────────────────────────────────────────
1512
+ /**
1513
+ * Get async compute overrides.
1514
+ *
1515
+ * @returns Async compute override configuration
1516
+ */
1517
+ getAsyncComputeOverrides() {
1518
+ return this.get("/hi/Specs/file/graphics/AsyncComputeOverrides.json");
1519
+ }
1520
+ /**
1521
+ * Get CPU presets.
1522
+ *
1523
+ * @returns CPU preset configuration
1524
+ */
1525
+ getCpuPresets() {
1526
+ return this.get("/hi/Specs/file/cpu/presets.json");
1527
+ }
1528
+ /**
1529
+ * Get device preset overrides.
1530
+ *
1531
+ * @returns Device preset overrides
1532
+ */
1533
+ getDevicePresetOverrides() {
1534
+ return this.get("/hi/Specs/file/graphics/DevicePresetOverrides.json");
1535
+ }
1536
+ /**
1537
+ * Get graphics spec control overrides.
1538
+ *
1539
+ * @returns Graphics spec control overrides
1540
+ */
1541
+ getGraphicsSpecControlOverrides() {
1542
+ return this.get(
1543
+ "/hi/Specs/file/graphics/GraphicsSpecControlOverrides.json"
1544
+ );
1545
+ }
1546
+ /**
1547
+ * Get graphics specs/overrides.
1548
+ *
1549
+ * @returns Graphics overrides
1550
+ */
1551
+ getGraphicSpecs() {
1552
+ return this.get("/hi/Specs/file/graphics/overrides.json");
1553
+ }
1554
+ /**
1555
+ * Get recommended drivers.
1556
+ *
1557
+ * @returns Driver manifest
1558
+ */
1559
+ getRecommendedDrivers() {
1560
+ return this.get("/hi/Specs/file/graphics/RecommendedDrivers.json");
1561
+ }
1562
+ // ─────────────────────────────────────────────────────────────────
1563
+ // Title Authorization & Access
1564
+ // ─────────────────────────────────────────────────────────────────
1565
+ /**
1566
+ * Get claw (clawback) access list.
1567
+ *
1568
+ * @param flightId - Flight ID
1569
+ * @returns Claw access snapshot
1570
+ */
1571
+ getClawAccess(flightId) {
1572
+ this.assertNotEmpty(flightId, "flightId");
1573
+ return this.get(
1574
+ `/hi/TitleAuthorization/file/claw/access.json?flight=${flightId}`
1575
+ );
1576
+ }
1577
+ /**
1578
+ * Get not allowed in title message.
1579
+ *
1580
+ * @returns OE configuration message
1581
+ */
1582
+ getNotAllowedInTitleMessage() {
1583
+ const url = `https://${HALO_CORE_ENDPOINTS.GAME_CMS_ORIGIN}.${HALO_CORE_ENDPOINTS.SERVICE_DOMAIN}/branches/hi/OEConfiguration/data/authfail/Default.json`;
1584
+ return this.getFullUrl(url, { useSpartanToken: false });
1585
+ }
1586
+ // ─────────────────────────────────────────────────────────────────
1587
+ // Guides (File Listings)
1588
+ // ─────────────────────────────────────────────────────────────────
1589
+ /**
1590
+ * Get guide for images files.
1591
+ *
1592
+ * @param flightId - Flight ID
1593
+ * @returns Guide container with file listings
1594
+ */
1595
+ getGuideImages(flightId) {
1596
+ this.assertNotEmpty(flightId, "flightId");
1597
+ return this.get(`/hi/images/guide/xo?flight=${flightId}`);
1598
+ }
1599
+ /**
1600
+ * Get guide for multiplayer files.
1601
+ *
1602
+ * @param flightId - Flight ID
1603
+ * @returns Guide container with file listings
1604
+ */
1605
+ getGuideMultiplayer(flightId) {
1606
+ this.assertNotEmpty(flightId, "flightId");
1607
+ return this.get(`/hi/Multiplayer/guide/xo?flight=${flightId}`);
1608
+ }
1609
+ /**
1610
+ * Get guide for news files.
1611
+ *
1612
+ * @param flightId - Flight ID
1613
+ * @returns Guide container with file listings
1614
+ */
1615
+ getGuideNews(flightId) {
1616
+ this.assertNotEmpty(flightId, "flightId");
1617
+ return this.get(`/hi/News/guide/xo?flight=${flightId}`);
1618
+ }
1619
+ /**
1620
+ * Get guide for progression files.
1621
+ *
1622
+ * @param flightId - Flight ID
1623
+ * @returns Guide container with file listings
1624
+ */
1625
+ getGuideProgression(flightId) {
1626
+ this.assertNotEmpty(flightId, "flightId");
1627
+ return this.get(`/hi/Progression/guide/xo?flight=${flightId}`);
1628
+ }
1629
+ /**
1630
+ * Get guide for spec files.
1631
+ *
1632
+ * @param flightId - Flight ID
1633
+ * @returns Guide container with file listings
1634
+ */
1635
+ getGuideSpecs(flightId) {
1636
+ this.assertNotEmpty(flightId, "flightId");
1637
+ return this.get(`/hi/Specs/guide/xo?flight=${flightId}`);
1638
+ }
1639
+ /**
1640
+ * Get guide for title authorization files.
1641
+ *
1642
+ * @param flightId - Flight ID
1643
+ * @returns Guide container with file listings
1644
+ */
1645
+ getGuideTitleAuthorization(flightId) {
1646
+ this.assertNotEmpty(flightId, "flightId");
1647
+ return this.get(`/hi/TitleAuthorization/guide/xo?flight=${flightId}`);
1648
+ }
1649
+ // ─────────────────────────────────────────────────────────────────
1650
+ // Waypoint Files
1651
+ // ─────────────────────────────────────────────────────────────────
1652
+ /**
1653
+ * Get emblem mapping configuration.
1654
+ *
1655
+ * @returns Emblem mapping dictionary
1656
+ */
1657
+ getEmblemMapping() {
1658
+ return this.get("/hi/Waypoint/file/images/emblems/mapping.json");
1659
+ }
1660
+ /**
1661
+ * Get a generic file from Waypoint service.
1662
+ *
1663
+ * @param filePath - Path to the file
1664
+ * @returns File data as bytes
1665
+ */
1666
+ getGenericWaypointFile(filePath) {
1667
+ this.assertNotEmpty(filePath, "filePath");
1668
+ return this.get(`/hi/Waypoint/file/${filePath}`, { returnRaw: true });
1669
+ }
1342
1670
  };
1343
1671
 
1344
1672
  // src/modules/halo-infinite/lobby.module.ts
@@ -1422,6 +1750,100 @@ var SettingsModule = class extends ModuleBase {
1422
1750
  useSpartanToken: true
1423
1751
  });
1424
1752
  }
1753
+ /**
1754
+ * Get a list of features enabled for a given flight.
1755
+ *
1756
+ * @param flightId - Clearance ID/flight that is being used
1757
+ * @returns Flighted feature flags
1758
+ */
1759
+ getFlightedFeatureFlags(flightId) {
1760
+ this.assertNotEmpty(flightId, "flightId");
1761
+ return this.get(`/featureflags/hi?flight=${flightId}`);
1762
+ }
1763
+ /**
1764
+ * Get the currently active clearance.
1765
+ *
1766
+ * @param release - Release identifier (e.g., "1.4", "1.5", "1.6")
1767
+ * @returns Player clearance data
1768
+ */
1769
+ getActiveClearance(release) {
1770
+ this.assertNotEmpty(release, "release");
1771
+ return this.get(`/hi/clearances/active?release=${release}`, {
1772
+ useSpartanToken: false
1773
+ });
1774
+ }
1775
+ /**
1776
+ * Get the currently active flight.
1777
+ *
1778
+ * @param sandbox - Sandbox identifier (typically "UNUSED")
1779
+ * @param buildNumber - Game build number (e.g., "211755.22.01.23.0549-0")
1780
+ * @param release - Release identifier (e.g., "1.4", "1.5")
1781
+ * @returns Player clearance data
1782
+ */
1783
+ getActiveFlight(sandbox, buildNumber, release) {
1784
+ this.assertNotEmpty(sandbox, "sandbox");
1785
+ this.assertNotEmpty(buildNumber, "buildNumber");
1786
+ this.assertNotEmpty(release, "release");
1787
+ return this.get(
1788
+ `/oban/flight-configurations/titles/hi/audiences/RETAIL/active?sandbox=${sandbox}&build=${buildNumber}&release=${release}`
1789
+ );
1790
+ }
1791
+ /**
1792
+ * Get the clearance/flight ID for a specific audience.
1793
+ *
1794
+ * @param audience - Audience targeting (e.g., "RETAIL")
1795
+ * @param sandbox - Sandbox identifier (typically "UNUSED")
1796
+ * @param buildNumber - Game build number
1797
+ * @param release - Release identifier
1798
+ * @returns Player clearance data
1799
+ */
1800
+ getClearance(audience, sandbox, buildNumber, release) {
1801
+ this.assertNotEmpty(audience, "audience");
1802
+ this.assertNotEmpty(sandbox, "sandbox");
1803
+ this.assertNotEmpty(buildNumber, "buildNumber");
1804
+ this.assertNotEmpty(release, "release");
1805
+ return this.get(
1806
+ `/oban/flight-configurations/titles/hi/audiences/${audience}/active?sandbox=${sandbox}&build=${buildNumber}&release=${release}`
1807
+ );
1808
+ }
1809
+ /**
1810
+ * Get the player clearance/flight ID for a specific audience.
1811
+ *
1812
+ * @param audience - Audience targeting (e.g., "RETAIL")
1813
+ * @param player - Player XUID
1814
+ * @param sandbox - Sandbox identifier (typically "UNUSED")
1815
+ * @param buildNumber - Game build number
1816
+ * @param release - Release identifier
1817
+ * @returns Player clearance data
1818
+ */
1819
+ getPlayerClearance(audience, player, sandbox, buildNumber, release) {
1820
+ this.assertNotEmpty(audience, "audience");
1821
+ this.assertNotEmpty(player, "player");
1822
+ this.assertNotEmpty(sandbox, "sandbox");
1823
+ this.assertNotEmpty(buildNumber, "buildNumber");
1824
+ this.assertNotEmpty(release, "release");
1825
+ return this.get(
1826
+ `/oban/flight-configurations/titles/hi/audiences/${audience}/players/xuid(${player})/active?sandbox=${sandbox}&build=${buildNumber}&release=${release}`
1827
+ );
1828
+ }
1829
+ /**
1830
+ * Get the player clearance/flight ID for RETAIL audience.
1831
+ *
1832
+ * @param player - Player XUID
1833
+ * @param sandbox - Sandbox identifier (typically "UNUSED")
1834
+ * @param buildNumber - Game build number
1835
+ * @param release - Release identifier
1836
+ * @returns Player clearance data
1837
+ */
1838
+ getPlayerClearanceRetail(player, sandbox, buildNumber, release) {
1839
+ this.assertNotEmpty(player, "player");
1840
+ this.assertNotEmpty(sandbox, "sandbox");
1841
+ this.assertNotEmpty(buildNumber, "buildNumber");
1842
+ this.assertNotEmpty(release, "release");
1843
+ return this.get(
1844
+ `/oban/flight-configurations/titles/hi/audiences/RETAIL/players/xuid(${player})/active?sandbox=${sandbox}&build=${buildNumber}&release=${release}`
1845
+ );
1846
+ }
1425
1847
  };
1426
1848
 
1427
1849
  // src/modules/halo-infinite/skill.module.ts
@@ -1603,6 +2025,28 @@ var TextModerationModule = class extends ModuleBase {
1603
2025
  getModerationKey() {
1604
2026
  return this.get("/hi/moderation/key");
1605
2027
  }
2028
+ /**
2029
+ * Get a specific moderation proof signing key.
2030
+ *
2031
+ * @param keyId - Key ID (can be obtained from getSigningKeys)
2032
+ * @returns Signing key data
2033
+ */
2034
+ getSigningKey(keyId) {
2035
+ this.assertNotEmpty(keyId, "keyId");
2036
+ return this.get(`/hi/moderation-proof-keys/${keyId}`, {
2037
+ useSpartanToken: false
2038
+ });
2039
+ }
2040
+ /**
2041
+ * Get all available moderation proof signing keys.
2042
+ *
2043
+ * @returns Container with all signing keys
2044
+ */
2045
+ getSigningKeys() {
2046
+ return this.get("/hi/moderation-proof-keys", {
2047
+ useSpartanToken: false
2048
+ });
2049
+ }
1606
2050
  };
1607
2051
 
1608
2052
  // src/modules/halo-infinite/ugc.module.ts
@@ -1639,6 +2083,18 @@ var UgcModule = class extends ModuleBase {
1639
2083
  this.assertNotEmpty(assetId, "assetId");
1640
2084
  return this.get(`/${title}/${assetType}/${assetId}/versions/latest`);
1641
2085
  }
2086
+ /**
2087
+ * Get the latest version of a film asset.
2088
+ *
2089
+ * @param title - Game title
2090
+ * @param assetId - Film asset GUID
2091
+ * @returns Latest film asset version
2092
+ */
2093
+ getLatestAssetVersionFilm(title, assetId) {
2094
+ this.assertNotEmpty(title, "title");
2095
+ this.assertNotEmpty(assetId, "assetId");
2096
+ return this.get(`/${title}/films/${assetId}/versions/latest`);
2097
+ }
1642
2098
  /**
1643
2099
  * Get a specific version of an asset.
1644
2100
  *
@@ -1814,18 +2270,31 @@ var UgcModule = class extends ModuleBase {
1814
2270
  // Asset Management
1815
2271
  // ─────────────────────────────────────────────────────────────────
1816
2272
  /**
1817
- * Delete an asset and all its versions.
2273
+ * Delete an asset.
1818
2274
  *
1819
2275
  * @param title - Game title
1820
2276
  * @param assetType - Type of asset
1821
2277
  * @param assetId - Asset GUID
1822
2278
  * @returns Success status
1823
2279
  */
1824
- deleteAllVersions(title, assetType, assetId) {
2280
+ deleteAsset(title, assetType, assetId) {
1825
2281
  this.assertNotEmpty(title, "title");
1826
2282
  this.assertNotEmpty(assetId, "assetId");
1827
2283
  return this.delete(`/${title}/${assetType}/${assetId}`);
1828
2284
  }
2285
+ /**
2286
+ * Delete all versions of an asset.
2287
+ *
2288
+ * @param title - Game title
2289
+ * @param assetType - Type of asset
2290
+ * @param assetId - Asset GUID
2291
+ * @returns Success status
2292
+ */
2293
+ deleteAllVersions(title, assetType, assetId) {
2294
+ this.assertNotEmpty(title, "title");
2295
+ this.assertNotEmpty(assetId, "assetId");
2296
+ return this.delete(`/${title}/${assetType}/${assetId}/versions`);
2297
+ }
1829
2298
  /**
1830
2299
  * Delete a specific version of an asset.
1831
2300
  *
@@ -1841,6 +2310,34 @@ var UgcModule = class extends ModuleBase {
1841
2310
  this.assertNotEmpty(versionId, "versionId");
1842
2311
  return this.delete(`/${title}/${assetType}/${assetId}/versions/${versionId}`);
1843
2312
  }
2313
+ /**
2314
+ * Undelete a previously deleted asset.
2315
+ *
2316
+ * @param title - Game title
2317
+ * @param assetType - Type of asset
2318
+ * @param assetId - Asset GUID
2319
+ * @returns Success status
2320
+ */
2321
+ undeleteAsset(title, assetType, assetId) {
2322
+ this.assertNotEmpty(title, "title");
2323
+ this.assertNotEmpty(assetId, "assetId");
2324
+ return this.post(`/${title}/${assetType}/${assetId}/recover`);
2325
+ }
2326
+ /**
2327
+ * Undelete a previously deleted asset version.
2328
+ *
2329
+ * @param title - Game title
2330
+ * @param assetType - Type of asset
2331
+ * @param assetId - Asset GUID
2332
+ * @param versionId - Version GUID
2333
+ * @returns Success status
2334
+ */
2335
+ undeleteVersion(title, assetType, assetId, versionId) {
2336
+ this.assertNotEmpty(title, "title");
2337
+ this.assertNotEmpty(assetId, "assetId");
2338
+ this.assertNotEmpty(versionId, "versionId");
2339
+ return this.post(`/${title}/${assetType}/${assetId}/versions/${versionId}/recover`);
2340
+ }
1844
2341
  /**
1845
2342
  * Publish an asset version.
1846
2343
  *
@@ -1939,6 +2436,21 @@ var UgcModule = class extends ModuleBase {
1939
2436
  this.assertNotEmpty(assetId, "assetId");
1940
2437
  return this.delete(`/${title}/${assetType}/${assetId}/sessions`);
1941
2438
  }
2439
+ /**
2440
+ * Spawn (create) a new asset.
2441
+ *
2442
+ * @param title - Game title
2443
+ * @param assetType - Type of asset (e.g., "UgcGameVariants", "Maps", "Prefabs")
2444
+ * @param asset - Asset definition
2445
+ * @returns Created asset
2446
+ */
2447
+ spawnAsset(title, assetType, asset) {
2448
+ this.assertNotEmpty(title, "title");
2449
+ return this.postJson(
2450
+ `/${title}/${assetType}`,
2451
+ asset
2452
+ );
2453
+ }
1942
2454
  /**
1943
2455
  * Create a new asset version.
1944
2456
  *
@@ -1996,6 +2508,9 @@ var UgcDiscoveryModule = class extends ModuleBase {
1996
2508
  constructor(client) {
1997
2509
  super(client, HALO_CORE_ENDPOINTS.DISCOVERY_ORIGIN);
1998
2510
  }
2511
+ // ─────────────────────────────────────────────────────────────────
2512
+ // Search & Browse
2513
+ // ─────────────────────────────────────────────────────────────────
1999
2514
  /**
2000
2515
  * Search for user-generated content.
2001
2516
  *
@@ -2032,6 +2547,27 @@ var UgcDiscoveryModule = class extends ModuleBase {
2032
2547
  if (params.start !== void 0) {
2033
2548
  queryParts.push(`start=${params.start}`);
2034
2549
  }
2550
+ if (params.averageRatingMin !== void 0) {
2551
+ queryParts.push(`averageRatingMin=${params.averageRatingMin}`);
2552
+ }
2553
+ if (params.fromDateCreatedUtc) {
2554
+ queryParts.push(`fromDateCreatedUtc=${encodeURIComponent(params.fromDateCreatedUtc.toISOString())}`);
2555
+ }
2556
+ if (params.toDateCreatedUtc) {
2557
+ queryParts.push(`toDateCreatedUtc=${encodeURIComponent(params.toDateCreatedUtc.toISOString())}`);
2558
+ }
2559
+ if (params.fromDateModifiedUtc) {
2560
+ queryParts.push(`fromDateModifiedUtc=${encodeURIComponent(params.fromDateModifiedUtc.toISOString())}`);
2561
+ }
2562
+ if (params.toDateModifiedUtc) {
2563
+ queryParts.push(`toDateModifiedUtc=${encodeURIComponent(params.toDateModifiedUtc.toISOString())}`);
2564
+ }
2565
+ if (params.fromDatePublishedUtc) {
2566
+ queryParts.push(`fromDatePublishedUtc=${encodeURIComponent(params.fromDatePublishedUtc.toISOString())}`);
2567
+ }
2568
+ if (params.toDatePublishedUtc) {
2569
+ queryParts.push(`toDatePublishedUtc=${encodeURIComponent(params.toDatePublishedUtc.toISOString())}`);
2570
+ }
2035
2571
  const queryString = queryParts.length > 0 ? `?${queryParts.join("&")}` : "";
2036
2572
  return this.get(`/hi/search${queryString}`);
2037
2573
  }
@@ -2111,15 +2647,298 @@ var UgcDiscoveryModule = class extends ModuleBase {
2111
2647
  return this.get(`/hi/${assetKind}/${assetId}`);
2112
2648
  }
2113
2649
  /**
2114
- * Get film asset for a match.
2650
+ * Get tags information.
2651
+ *
2652
+ * @returns Available tags info
2653
+ */
2654
+ getTagsInfo() {
2655
+ return this.get("/hi/info/tags");
2656
+ }
2657
+ // ─────────────────────────────────────────────────────────────────
2658
+ // Manifests
2659
+ // ─────────────────────────────────────────────────────────────────
2660
+ /**
2661
+ * Get the game manifest by build GUID.
2662
+ *
2663
+ * @param buildGuid - Build GUID
2664
+ * @returns Manifest data
2665
+ */
2666
+ getManifestByBuildGuid(buildGuid) {
2667
+ this.assertNotEmpty(buildGuid, "buildGuid");
2668
+ return this.get(`/hi/manifests/guids/${buildGuid}/game`);
2669
+ }
2670
+ /**
2671
+ * Get the game manifest by build number.
2672
+ *
2673
+ * @param buildNumber - Build number (e.g., "6.10022.10499")
2674
+ * @returns Manifest data
2675
+ */
2676
+ getManifestByBuild(buildNumber) {
2677
+ this.assertNotEmpty(buildNumber, "buildNumber");
2678
+ return this.get(`/hi/manifests/builds/${buildNumber}/game`);
2679
+ }
2680
+ /**
2681
+ * Get a specific manifest version.
2682
+ *
2683
+ * @param assetId - Manifest asset ID
2684
+ * @param versionId - Manifest version ID
2685
+ * @param clearanceId - Active flight clearance ID
2686
+ * @returns Manifest data
2687
+ */
2688
+ getManifest(assetId, versionId, clearanceId) {
2689
+ this.assertNotEmpty(assetId, "assetId");
2690
+ this.assertNotEmpty(versionId, "versionId");
2691
+ return this.get(
2692
+ `/hi/manifests/${assetId}/versions/${versionId}?clearanceId=${clearanceId}`
2693
+ );
2694
+ }
2695
+ // ─────────────────────────────────────────────────────────────────
2696
+ // Maps
2697
+ // ─────────────────────────────────────────────────────────────────
2698
+ /**
2699
+ * Get a specific map version.
2700
+ *
2701
+ * @param assetId - Map asset ID
2702
+ * @param versionId - Map version ID
2703
+ * @returns Map data
2704
+ */
2705
+ getMap(assetId, versionId) {
2706
+ this.assertNotEmpty(assetId, "assetId");
2707
+ this.assertNotEmpty(versionId, "versionId");
2708
+ return this.get(`/hi/maps/${assetId}/versions/${versionId}`);
2709
+ }
2710
+ /**
2711
+ * Get a map without specifying version (returns latest).
2712
+ *
2713
+ * @param assetId - Map asset ID
2714
+ * @returns Map data
2715
+ */
2716
+ getMapWithoutVersion(assetId) {
2717
+ this.assertNotEmpty(assetId, "assetId");
2718
+ return this.get(`/hi/maps/${assetId}`);
2719
+ }
2720
+ // ─────────────────────────────────────────────────────────────────
2721
+ // Map Mode Pairs
2722
+ // ─────────────────────────────────────────────────────────────────
2723
+ /**
2724
+ * Get a specific map mode pair version.
2725
+ *
2726
+ * @param assetId - Map mode pair asset ID
2727
+ * @param versionId - Version ID
2728
+ * @param clearanceId - Active flight clearance ID
2729
+ * @returns Map mode pair data
2730
+ */
2731
+ getMapModePair(assetId, versionId, clearanceId) {
2732
+ this.assertNotEmpty(assetId, "assetId");
2733
+ this.assertNotEmpty(versionId, "versionId");
2734
+ return this.get(
2735
+ `/hi/mapModePairs/${assetId}/versions/${versionId}?clearanceId=${clearanceId}`
2736
+ );
2737
+ }
2738
+ /**
2739
+ * Get a map mode pair without specifying version.
2740
+ *
2741
+ * @param assetId - Map mode pair asset ID
2742
+ * @returns Map mode pair data
2743
+ */
2744
+ getMapModePairWithoutVersion(assetId) {
2745
+ this.assertNotEmpty(assetId, "assetId");
2746
+ return this.get(`/hi/mapModePairs/${assetId}`);
2747
+ }
2748
+ // ─────────────────────────────────────────────────────────────────
2749
+ // Playlists
2750
+ // ─────────────────────────────────────────────────────────────────
2751
+ /**
2752
+ * Get a specific playlist version.
2753
+ *
2754
+ * @param assetId - Playlist asset ID
2755
+ * @param versionId - Version ID
2756
+ * @param clearanceId - Active flight clearance ID
2757
+ * @returns Playlist data
2758
+ */
2759
+ getPlaylist(assetId, versionId, clearanceId) {
2760
+ this.assertNotEmpty(assetId, "assetId");
2761
+ this.assertNotEmpty(versionId, "versionId");
2762
+ return this.get(
2763
+ `/hi/playlists/${assetId}/versions/${versionId}?clearanceId=${clearanceId}`
2764
+ );
2765
+ }
2766
+ /**
2767
+ * Get a playlist without specifying version.
2768
+ *
2769
+ * @param assetId - Playlist asset ID
2770
+ * @returns Playlist data
2771
+ */
2772
+ getPlaylistWithoutVersion(assetId) {
2773
+ this.assertNotEmpty(assetId, "assetId");
2774
+ return this.get(`/hi/playlists/${assetId}`);
2775
+ }
2776
+ // ─────────────────────────────────────────────────────────────────
2777
+ // Prefabs
2778
+ // ─────────────────────────────────────────────────────────────────
2779
+ /**
2780
+ * Get a specific prefab version.
2781
+ *
2782
+ * @param assetId - Prefab asset ID
2783
+ * @param versionId - Version ID
2784
+ * @returns Prefab data
2785
+ */
2786
+ getPrefab(assetId, versionId) {
2787
+ this.assertNotEmpty(assetId, "assetId");
2788
+ this.assertNotEmpty(versionId, "versionId");
2789
+ return this.get(`/hi/prefabs/${assetId}/versions/${versionId}`);
2790
+ }
2791
+ /**
2792
+ * Get a prefab without specifying version.
2793
+ *
2794
+ * @param assetId - Prefab asset ID
2795
+ * @returns Prefab data
2796
+ */
2797
+ getPrefabWithoutVersion(assetId) {
2798
+ this.assertNotEmpty(assetId, "assetId");
2799
+ return this.get(`/hi/prefabs/${assetId}`);
2800
+ }
2801
+ // ─────────────────────────────────────────────────────────────────
2802
+ // Projects
2803
+ // ─────────────────────────────────────────────────────────────────
2804
+ /**
2805
+ * Get a specific project version.
2806
+ *
2807
+ * @param assetId - Project asset ID
2808
+ * @param versionId - Version ID
2809
+ * @returns Project data
2810
+ */
2811
+ getProject(assetId, versionId) {
2812
+ this.assertNotEmpty(assetId, "assetId");
2813
+ this.assertNotEmpty(versionId, "versionId");
2814
+ return this.get(`/hi/projects/${assetId}/versions/${versionId}`);
2815
+ }
2816
+ /**
2817
+ * Get a project without specifying version.
2818
+ *
2819
+ * @param assetId - Project asset ID
2820
+ * @returns Project data
2821
+ */
2822
+ getProjectWithoutVersion(assetId) {
2823
+ this.assertNotEmpty(assetId, "assetId");
2824
+ return this.get(`/hi/projects/${assetId}`);
2825
+ }
2826
+ /**
2827
+ * Get the Forge templates (canvases).
2828
+ *
2829
+ * @returns Forge templates project
2830
+ */
2831
+ getForgeTemplates() {
2832
+ return this.get("/hi/projects/bf0e9bab-6fed-47a4-8bf7-bfd4422ee552");
2833
+ }
2834
+ /**
2835
+ * Get the Forge mode categories.
2836
+ *
2837
+ * @returns Forge mode categories project
2838
+ */
2839
+ getForgeModeCategories() {
2840
+ return this.get("/hi/projects/aff73c44-0771-468f-b9cf-5c52eee7ab4c");
2841
+ }
2842
+ /**
2843
+ * Get the community tab assets.
2844
+ *
2845
+ * @returns Community tab project
2846
+ */
2847
+ getCommunityTab() {
2848
+ return this.get("/hi/projects/90f9e508-99ce-411c-bf88-7bf12b5e9f52");
2849
+ }
2850
+ /**
2851
+ * Get 343 recommended assets.
2852
+ *
2853
+ * @returns 343 recommended project
2854
+ */
2855
+ get343Recommended() {
2856
+ return this.get("/hi/projects/712add52-f989-48e1-b3bb-ac7cd8a1c17a");
2857
+ }
2858
+ // ─────────────────────────────────────────────────────────────────
2859
+ // Game Variants
2860
+ // ─────────────────────────────────────────────────────────────────
2861
+ /**
2862
+ * Get a specific engine game variant version.
2863
+ *
2864
+ * @param assetId - Engine game variant asset ID
2865
+ * @param versionId - Version ID
2866
+ * @returns Engine game variant data
2867
+ */
2868
+ getEngineGameVariant(assetId, versionId) {
2869
+ this.assertNotEmpty(assetId, "assetId");
2870
+ this.assertNotEmpty(versionId, "versionId");
2871
+ return this.get(
2872
+ `/hi/engineGameVariants/${assetId}/versions/${versionId}`
2873
+ );
2874
+ }
2875
+ /**
2876
+ * Get an engine game variant without specifying version.
2877
+ *
2878
+ * @param assetId - Engine game variant asset ID
2879
+ * @returns Engine game variant data
2880
+ */
2881
+ getEngineGameVariantWithoutVersion(assetId) {
2882
+ this.assertNotEmpty(assetId, "assetId");
2883
+ return this.get(`/hi/engineGameVariants/${assetId}`);
2884
+ }
2885
+ /**
2886
+ * Get a specific UGC game variant version.
2887
+ *
2888
+ * @param assetId - UGC game variant asset ID
2889
+ * @param versionId - Version ID
2890
+ * @returns UGC game variant data
2891
+ */
2892
+ getUgcGameVariant(assetId, versionId) {
2893
+ this.assertNotEmpty(assetId, "assetId");
2894
+ this.assertNotEmpty(versionId, "versionId");
2895
+ return this.get(
2896
+ `/hi/ugcGameVariants/${assetId}/versions/${versionId}`
2897
+ );
2898
+ }
2899
+ /**
2900
+ * Get a UGC game variant without specifying version.
2901
+ *
2902
+ * @param assetId - UGC game variant asset ID
2903
+ * @returns UGC game variant data
2904
+ */
2905
+ getUgcGameVariantWithoutVersion(assetId) {
2906
+ this.assertNotEmpty(assetId, "assetId");
2907
+ return this.get(`/hi/ugcGameVariants/${assetId}`);
2908
+ }
2909
+ // ─────────────────────────────────────────────────────────────────
2910
+ // Films
2911
+ // ─────────────────────────────────────────────────────────────────
2912
+ /**
2913
+ * Get a film by asset ID.
2914
+ *
2915
+ * @param assetId - Film asset ID
2916
+ * @returns Film data
2917
+ */
2918
+ getFilm(assetId) {
2919
+ this.assertNotEmpty(assetId, "assetId");
2920
+ return this.get(`/hi/films/${assetId}`);
2921
+ }
2922
+ /**
2923
+ * Get film asset for a match (spectate).
2115
2924
  *
2116
2925
  * @param matchId - Match GUID
2117
2926
  * @returns Film asset if available
2118
2927
  */
2119
- getFilmByMatchId(matchId) {
2928
+ spectateByMatchId(matchId) {
2120
2929
  this.assertNotEmpty(matchId, "matchId");
2121
2930
  return this.get(`/hi/films/matches/${matchId}/spectate`);
2122
2931
  }
2932
+ /**
2933
+ * Get film asset for a match.
2934
+ *
2935
+ * @param matchId - Match GUID
2936
+ * @returns Film asset if available
2937
+ * @deprecated Use spectateByMatchId instead
2938
+ */
2939
+ getFilmByMatchId(matchId) {
2940
+ return this.spectateByMatchId(matchId);
2941
+ }
2123
2942
  };
2124
2943
 
2125
2944
  // src/clients/halo-infinite-client.ts