@1upmonster/cli 0.1.0

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.
Files changed (38) hide show
  1. package/LICENSE +21 -0
  2. package/dist/commands/auth.d.ts +3 -0
  3. package/dist/commands/auth.d.ts.map +1 -0
  4. package/dist/commands/auth.js +58 -0
  5. package/dist/commands/auth.js.map +1 -0
  6. package/dist/commands/game-api-keys.d.ts +3 -0
  7. package/dist/commands/game-api-keys.d.ts.map +1 -0
  8. package/dist/commands/game-api-keys.js +37 -0
  9. package/dist/commands/game-api-keys.js.map +1 -0
  10. package/dist/commands/tenant.d.ts +3 -0
  11. package/dist/commands/tenant.d.ts.map +1 -0
  12. package/dist/commands/tenant.js +57 -0
  13. package/dist/commands/tenant.js.map +1 -0
  14. package/dist/commands/versus/config.d.ts +3 -0
  15. package/dist/commands/versus/config.d.ts.map +1 -0
  16. package/dist/commands/versus/config.js +90 -0
  17. package/dist/commands/versus/config.js.map +1 -0
  18. package/dist/commands/versus/match.d.ts +3 -0
  19. package/dist/commands/versus/match.d.ts.map +1 -0
  20. package/dist/commands/versus/match.js +45 -0
  21. package/dist/commands/versus/match.js.map +1 -0
  22. package/dist/config.d.ts +2 -0
  23. package/dist/config.d.ts.map +1 -0
  24. package/dist/config.js +2 -0
  25. package/dist/config.js.map +1 -0
  26. package/dist/credentials.d.ts +10 -0
  27. package/dist/credentials.d.ts.map +1 -0
  28. package/dist/credentials.js +49 -0
  29. package/dist/credentials.js.map +1 -0
  30. package/dist/index.d.ts +3 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +32 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/output.d.ts +5 -0
  35. package/dist/output.d.ts.map +1 -0
  36. package/dist/output.js +34 -0
  37. package/dist/output.js.map +1 -0
  38. package/package.json +32 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 1upmonster
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerAuth(program: Command): void;
3
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUzC,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAwDnD"}
@@ -0,0 +1,58 @@
1
+ import { AuthClient } from "@1upmonster/sdk";
2
+ import { createKeyPairFromBytes, getAddressFromPublicKey } from "@solana/kit";
3
+ import { readFile } from "node:fs/promises";
4
+ import { clearCredentials, loadCredentials, saveCredentials, } from "../credentials.js";
5
+ import { fail, print } from "../output.js";
6
+ import { API_BASE } from "../config.js";
7
+ export function registerAuth(program) {
8
+ const auth = program.command("auth").description("Manage authentication");
9
+ auth
10
+ .command("login")
11
+ .description("Authenticate with your Solana wallet")
12
+ .option("--keypair <path>", "Path to Solana keypair JSON file (headless)")
13
+ .action(async (opts) => {
14
+ const client = new AuthClient(API_BASE);
15
+ if (opts.keypair) {
16
+ // Load 64-byte keypair from Solana CLI JSON format
17
+ const raw = JSON.parse(await readFile(opts.keypair, "utf-8"));
18
+ const keypair = await createKeyPairFromBytes(Uint8Array.from(raw));
19
+ const publicKey = await getAddressFromPublicKey(keypair.publicKey);
20
+ const session = await client.login({
21
+ publicKey,
22
+ signMessage: async (msg) => {
23
+ const sig = await crypto.subtle.sign("Ed25519", keypair.privateKey, msg);
24
+ return new Uint8Array(sig);
25
+ },
26
+ });
27
+ await saveCredentials({
28
+ token: session.token,
29
+ walletPubkey: session.walletPubkey,
30
+ expiresAt: session.expiresAt,
31
+ });
32
+ print(`Logged in as ${session.walletPubkey}`);
33
+ }
34
+ else {
35
+ fail("Interactive wallet signing not yet implemented. Use --keypair <path> for now.");
36
+ }
37
+ });
38
+ auth
39
+ .command("logout")
40
+ .description("Clear saved credentials")
41
+ .action(async () => {
42
+ await clearCredentials();
43
+ print("Logged out.");
44
+ });
45
+ auth
46
+ .command("status")
47
+ .description("Show current auth status")
48
+ .action(async () => {
49
+ const creds = await loadCredentials();
50
+ if (!creds?.token) {
51
+ print("Not authenticated.");
52
+ }
53
+ else {
54
+ print({ walletPubkey: creds.walletPubkey, expiresAt: creds.expiresAt });
55
+ }
56
+ });
57
+ }
58
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAE9E,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,MAAM,UAAU,YAAY,CAAC,OAAgB;IAC3C,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,uBAAuB,CAAC,CAAC;IAE1E,IAAI;SACD,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,sCAAsC,CAAC;SACnD,MAAM,CAAC,kBAAkB,EAAE,6CAA6C,CAAC;SACzE,MAAM,CAAC,KAAK,EAAE,IAA0B,EAAE,EAAE;QAC3C,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC;QAExC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,mDAAmD;YACnD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAa,CAAC;YAC1E,MAAM,OAAO,GAAG,MAAM,sBAAsB,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YACnE,MAAM,SAAS,GAAG,MAAM,uBAAuB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAEnE,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;gBACjC,SAAS;gBACT,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;oBACzB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;oBACzE,OAAO,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;gBAC7B,CAAC;aACF,CAAC,CAAC;YAEH,MAAM,eAAe,CAAC;gBACpB,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,YAAY,EAAE,OAAO,CAAC,YAAY;gBAClC,SAAS,EAAE,OAAO,CAAC,SAAS;aAC7B,CAAC,CAAC;YACH,KAAK,CAAC,gBAAgB,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,IAAI,CACF,+EAA+E,CAChF,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,IAAI;SACD,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,yBAAyB,CAAC;SACtC,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,gBAAgB,EAAE,CAAC;QACzB,KAAK,CAAC,aAAa,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;IAEL,IAAI;SACD,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,0BAA0B,CAAC;SACvC,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,KAAK,GAAG,MAAM,eAAe,EAAE,CAAC;QACtC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC;YAClB,KAAK,CAAC,oBAAoB,CAAC,CAAC;QAC9B,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,EAAE,YAAY,EAAE,KAAK,CAAC,YAAY,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerGameApiKeys(game: Command): void;
3
+ //# sourceMappingURL=game-api-keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"game-api-keys.d.ts","sourceRoot":"","sources":["../../src/commands/game-api-keys.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAkCvD"}
@@ -0,0 +1,37 @@
1
+ import { TenantClient } from "@1upmonster/sdk";
2
+ import { requireCredentials } from "../credentials.js";
3
+ import { fail, print, printTable } from "../output.js";
4
+ import { API_BASE } from "../config.js";
5
+ export function registerGameApiKeys(game) {
6
+ const apiKey = game.command("api-key").description("Manage game API keys");
7
+ apiKey
8
+ .command("create <gameId>")
9
+ .description("Create a new API key for a game")
10
+ .option("--name <name>", "Key label", "default")
11
+ .action(async (gameId, opts) => {
12
+ const creds = await requireCredentials();
13
+ const client = new TenantClient(API_BASE, creds.token);
14
+ const result = await client.createApiKey(gameId, opts.name).catch((e) => fail(e.message));
15
+ print("⚠ Store this key — it will not be shown again.");
16
+ print(result);
17
+ });
18
+ apiKey
19
+ .command("list <gameId>")
20
+ .description("List API keys for a game")
21
+ .action(async (gameId) => {
22
+ const creds = await requireCredentials();
23
+ const client = new TenantClient(API_BASE, creds.token);
24
+ const keys = await client.listApiKeys(gameId).catch((e) => fail(e.message));
25
+ printTable(keys);
26
+ });
27
+ apiKey
28
+ .command("revoke <gameId> <keyId>")
29
+ .description("Revoke an API key")
30
+ .action(async (gameId, keyId) => {
31
+ const creds = await requireCredentials();
32
+ const client = new TenantClient(API_BASE, creds.token);
33
+ await client.revokeApiKey(gameId, keyId).catch((e) => fail(e.message));
34
+ print(`Key ${keyId} revoked.`);
35
+ });
36
+ }
37
+ //# sourceMappingURL=game-api-keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"game-api-keys.js","sourceRoot":"","sources":["../../src/commands/game-api-keys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,MAAM,UAAU,mBAAmB,CAAC,IAAa;IAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,WAAW,CAAC,sBAAsB,CAAC,CAAC;IAE3E,MAAM;SACH,OAAO,CAAC,iBAAiB,CAAC;SAC1B,WAAW,CAAC,iCAAiC,CAAC;SAC9C,MAAM,CAAC,eAAe,EAAE,WAAW,EAAE,SAAS,CAAC;SAC/C,MAAM,CAAC,KAAK,EAAE,MAAc,EAAE,IAAsB,EAAE,EAAE;QACvD,MAAM,KAAK,GAAG,MAAM,kBAAkB,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QACjG,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACzD,KAAK,CAAC,MAAM,CAAC,CAAC;IAChB,CAAC,CAAC,CAAC;IAEL,MAAM;SACH,OAAO,CAAC,eAAe,CAAC;SACxB,WAAW,CAAC,0BAA0B,CAAC;SACvC,MAAM,CAAC,KAAK,EAAE,MAAc,EAAE,EAAE;QAC/B,MAAM,KAAK,GAAG,MAAM,kBAAkB,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QACnF,UAAU,CAAC,IAA4C,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEL,MAAM;SACH,OAAO,CAAC,yBAAyB,CAAC;SAClC,WAAW,CAAC,mBAAmB,CAAC;SAChC,MAAM,CAAC,KAAK,EAAE,MAAc,EAAE,KAAa,EAAE,EAAE;QAC9C,MAAM,KAAK,GAAG,MAAM,kBAAkB,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QACvD,MAAM,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QAC9E,KAAK,CAAC,OAAO,KAAK,WAAW,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerTenant(program: Command): Command;
3
+ //# sourceMappingURL=tenant.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant.d.ts","sourceRoot":"","sources":["../../src/commands/tenant.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CA0DxD"}
@@ -0,0 +1,57 @@
1
+ import { TenantClient } from "@1upmonster/sdk";
2
+ import { requireCredentials } from "../credentials.js";
3
+ import { fail, print } from "../output.js";
4
+ import { API_BASE } from "../config.js";
5
+ export function registerTenant(program) {
6
+ const tenant = program.command("tenant").description("Manage your tenant");
7
+ tenant
8
+ .command("create")
9
+ .description("Create a new tenant account")
10
+ .requiredOption("--name <name>", "Tenant/studio name")
11
+ .action(async (opts) => {
12
+ const creds = await requireCredentials();
13
+ const client = new TenantClient(API_BASE, creds.token);
14
+ const result = await client.createTenant(opts.name).catch((e) => fail(e.message));
15
+ print(result);
16
+ });
17
+ tenant
18
+ .command("info")
19
+ .description("Show current tenant info")
20
+ .action(async () => {
21
+ const creds = await requireCredentials();
22
+ const client = new TenantClient(API_BASE, creds.token);
23
+ const result = await client.getTenant().catch((e) => fail(e.message));
24
+ print(result);
25
+ });
26
+ const game = program.command("game").description("Manage games");
27
+ game
28
+ .command("create")
29
+ .description("Register a new game")
30
+ .requiredOption("--name <name>", "Game name")
31
+ .action(async (opts) => {
32
+ const creds = await requireCredentials();
33
+ const client = new TenantClient(API_BASE, creds.token);
34
+ const result = await client.createGame(opts.name).catch((e) => fail(e.message));
35
+ print(result);
36
+ });
37
+ game
38
+ .command("list")
39
+ .description("List all games")
40
+ .action(async () => {
41
+ const creds = await requireCredentials();
42
+ const client = new TenantClient(API_BASE, creds.token);
43
+ const result = await client.listGames().catch((e) => fail(e.message));
44
+ print(result);
45
+ });
46
+ game
47
+ .command("delete <gameId>")
48
+ .description("Delete a game")
49
+ .action(async (gameId) => {
50
+ const creds = await requireCredentials();
51
+ const client = new TenantClient(API_BASE, creds.token);
52
+ await client.deleteGame(gameId).catch((e) => fail(e.message));
53
+ print(`Game ${gameId} deleted.`);
54
+ });
55
+ return game;
56
+ }
57
+ //# sourceMappingURL=tenant.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant.js","sourceRoot":"","sources":["../../src/commands/tenant.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerVersusConfig(versus: Command): void;
3
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/commands/versus/config.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAoF1D"}
@@ -0,0 +1,90 @@
1
+ import { VersusClient } from "@1upmonster/versus";
2
+ import { requireCredentials } from "../../credentials.js";
3
+ import { fail, print } from "../../output.js";
4
+ import { API_BASE } from "../../config.js";
5
+ export function registerVersusConfig(versus) {
6
+ const config = versus.command("config").description("Manage Versus config");
7
+ config
8
+ .command("get <gameId>")
9
+ .description("Show Versus config for a game")
10
+ .action(async (gameId) => {
11
+ const creds = await requireCredentials();
12
+ const client = new VersusClient({ baseUrl: API_BASE, token: creds.token });
13
+ const result = await client.getConfig(gameId).catch((e) => fail(e.message));
14
+ print(result);
15
+ });
16
+ config
17
+ .command("set <gameId>")
18
+ .description("Set Versus config for a game")
19
+ .option("--elo-account-type <type>", "pda or static")
20
+ .option("--elo-seeds <seeds>", "Comma-separated PDA seeds (use {wallet} for player pubkey)")
21
+ .option("--elo-program-id <programId>", "Program ID for PDA derivation")
22
+ .option("--elo-address <address>", "Static account address (use {wallet} for player pubkey)")
23
+ .option("--elo-offset <n>", "Byte offset of ELO field", parseInt)
24
+ .option("--elo-type <type>", "ELO field data type (u8/u16/u32/u64/i8/i16/i32/i64)")
25
+ .option("--elo-endian <endian>", "Byte order: little or big (default: little)")
26
+ .option("--elo-default <n>", "Default ELO for new players", parseInt)
27
+ .option("--elo-rpc-fail <behavior>", "reject | use_default | use_cached")
28
+ .option("--authority-offset <n>", "Byte offset of authority pubkey (32 bytes) in the account. When set, verifies account owner matches authenticated wallet.", parseInt)
29
+ .option("--players-per-team <n>", "Players per team (1 for 1v1, 5 for 5v5)", parseInt)
30
+ .option("--teams <n>", "Number of teams (default: 2)", parseInt)
31
+ .option("--elo-aggregate <agg>", "Team ELO aggregate: average | max | min")
32
+ .option("--queue-ttl <s>", "Queue TTL in seconds", parseInt)
33
+ .option("--match-ttl <s>", "Match TTL in seconds", parseInt)
34
+ .option("--accept-window <s>", "Match accept window in seconds", parseInt)
35
+ .option("--expire-behavior <behavior>", "expire | match_any")
36
+ .action(async (gameId, opts) => {
37
+ const creds = await requireCredentials();
38
+ const client = new VersusClient({ baseUrl: API_BASE, token: creds.token });
39
+ const patch = {};
40
+ // ELO source
41
+ if (opts["eloAccountType"] === "pda") {
42
+ if (!opts["eloProgramId"])
43
+ fail("--elo-program-id required for pda type");
44
+ patch.eloSource = {
45
+ account: {
46
+ type: "pda",
47
+ seeds: String(opts["eloSeeds"] ?? "").split(","),
48
+ programId: opts["eloProgramId"],
49
+ },
50
+ offset: opts["eloOffset"] ?? 0,
51
+ type: opts["eloType"] ?? "u32",
52
+ endian: opts["eloEndian"] ?? "little",
53
+ default: opts["eloDefault"] ?? 1000,
54
+ rpcFailBehavior: opts["eloRpcFail"] ?? "use_default",
55
+ ...(opts["authorityOffset"] !== undefined && { authorityOffset: opts["authorityOffset"] }),
56
+ };
57
+ }
58
+ else if (opts["eloAccountType"] === "static") {
59
+ if (!opts["eloAddress"])
60
+ fail("--elo-address required for static type");
61
+ patch.eloSource = {
62
+ account: { type: "static", address: opts["eloAddress"] },
63
+ offset: opts["eloOffset"] ?? 0,
64
+ type: opts["eloType"] ?? "u32",
65
+ endian: opts["eloEndian"] ?? "little",
66
+ default: opts["eloDefault"] ?? 1000,
67
+ rpcFailBehavior: opts["eloRpcFail"] ?? "use_default",
68
+ ...(opts["authorityOffset"] !== undefined && { authorityOffset: opts["authorityOffset"] }),
69
+ };
70
+ }
71
+ if (opts["playersPerTeam"] !== undefined || opts["teams"] !== undefined) {
72
+ patch.matchFormat = {
73
+ playersPerTeam: opts["playersPerTeam"] ?? 1,
74
+ teams: opts["teams"] ?? 2,
75
+ eloAggregate: opts["eloAggregate"] ?? "average",
76
+ };
77
+ }
78
+ if (opts["queueTtl"] !== undefined)
79
+ patch.queueTtl = opts["queueTtl"];
80
+ if (opts["matchTtl"] !== undefined)
81
+ patch.matchTtl = opts["matchTtl"];
82
+ if (opts["acceptWindow"] !== undefined)
83
+ patch.acceptWindow = opts["acceptWindow"];
84
+ if (opts["expireBehavior"] !== undefined)
85
+ patch.expireBehavior = opts["expireBehavior"];
86
+ const result = await client.setConfig(gameId, patch).catch((e) => fail(e.message));
87
+ print(result);
88
+ });
89
+ }
90
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/commands/versus/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AASlD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,MAAM,UAAU,oBAAoB,CAAC,MAAe;IAClD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,sBAAsB,CAAC,CAAC;IAE5E,MAAM;SACH,OAAO,CAAC,cAAc,CAAC;SACvB,WAAW,CAAC,+BAA+B,CAAC;SAC5C,MAAM,CAAC,KAAK,EAAE,MAAc,EAAE,EAAE;QAC/B,MAAM,KAAK,GAAG,MAAM,kBAAkB,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;QAC3E,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QACnF,KAAK,CAAC,MAAM,CAAC,CAAC;IAChB,CAAC,CAAC,CAAC;IAEL,MAAM;SACH,OAAO,CAAC,cAAc,CAAC;SACvB,WAAW,CAAC,8BAA8B,CAAC;SAC3C,MAAM,CAAC,2BAA2B,EAAE,eAAe,CAAC;SACpD,MAAM,CAAC,qBAAqB,EAAE,4DAA4D,CAAC;SAC3F,MAAM,CAAC,8BAA8B,EAAE,+BAA+B,CAAC;SACvE,MAAM,CAAC,yBAAyB,EAAE,yDAAyD,CAAC;SAC5F,MAAM,CAAC,kBAAkB,EAAE,0BAA0B,EAAE,QAAQ,CAAC;SAChE,MAAM,CAAC,mBAAmB,EAAE,qDAAqD,CAAC;SAClF,MAAM,CAAC,uBAAuB,EAAE,6CAA6C,CAAC;SAC9E,MAAM,CAAC,mBAAmB,EAAE,6BAA6B,EAAE,QAAQ,CAAC;SACpE,MAAM,CAAC,2BAA2B,EAAE,mCAAmC,CAAC;SACxE,MAAM,CAAC,wBAAwB,EAAE,2HAA2H,EAAE,QAAQ,CAAC;SACvK,MAAM,CAAC,wBAAwB,EAAE,yCAAyC,EAAE,QAAQ,CAAC;SACrF,MAAM,CAAC,aAAa,EAAE,8BAA8B,EAAE,QAAQ,CAAC;SAC/D,MAAM,CAAC,uBAAuB,EAAE,yCAAyC,CAAC;SAC1E,MAAM,CAAC,iBAAiB,EAAE,sBAAsB,EAAE,QAAQ,CAAC;SAC3D,MAAM,CAAC,iBAAiB,EAAE,sBAAsB,EAAE,QAAQ,CAAC;SAC3D,MAAM,CAAC,qBAAqB,EAAE,gCAAgC,EAAE,QAAQ,CAAC;SACzE,MAAM,CAAC,8BAA8B,EAAE,oBAAoB,CAAC;SAC5D,MAAM,CAAC,KAAK,EAAE,MAAc,EAAE,IAA6B,EAAE,EAAE;QAC9D,MAAM,KAAK,GAAG,MAAM,kBAAkB,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;QAE3E,MAAM,KAAK,GAA0B,EAAE,CAAC;QAExC,aAAa;QACb,IAAI,IAAI,CAAC,gBAAgB,CAAC,KAAK,KAAK,EAAE,CAAC;YACrC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC;gBAAE,IAAI,CAAC,wCAAwC,CAAC,CAAC;YAC1E,KAAK,CAAC,SAAS,GAAG;gBAChB,OAAO,EAAE;oBACP,IAAI,EAAE,KAAK;oBACX,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;oBAChD,SAAS,EAAE,IAAI,CAAC,cAAc,CAAW;iBAC1C;gBACD,MAAM,EAAG,IAAI,CAAC,WAAW,CAAwB,IAAI,CAAC;gBACtD,IAAI,EAAG,IAAI,CAAC,SAAS,CAAyB,IAAI,KAAK;gBACvD,MAAM,EAAG,IAAI,CAAC,WAAW,CAAkC,IAAI,QAAQ;gBACvE,OAAO,EAAG,IAAI,CAAC,YAAY,CAAwB,IAAI,IAAI;gBAC3D,eAAe,EAAG,IAAI,CAAC,YAAY,CAAoC,IAAI,aAAa;gBACxF,GAAG,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,SAAS,IAAI,EAAE,eAAe,EAAE,IAAI,CAAC,iBAAiB,CAAW,EAAE,CAAC;aACrG,CAAC;QACJ,CAAC;aAAM,IAAI,IAAI,CAAC,gBAAgB,CAAC,KAAK,QAAQ,EAAE,CAAC;YAC/C,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC;gBAAE,IAAI,CAAC,wCAAwC,CAAC,CAAC;YACxE,KAAK,CAAC,SAAS,GAAG;gBAChB,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,YAAY,CAAW,EAAE;gBAClE,MAAM,EAAG,IAAI,CAAC,WAAW,CAAwB,IAAI,CAAC;gBACtD,IAAI,EAAG,IAAI,CAAC,SAAS,CAAyB,IAAI,KAAK;gBACvD,MAAM,EAAG,IAAI,CAAC,WAAW,CAAkC,IAAI,QAAQ;gBACvE,OAAO,EAAG,IAAI,CAAC,YAAY,CAAwB,IAAI,IAAI;gBAC3D,eAAe,EAAG,IAAI,CAAC,YAAY,CAAoC,IAAI,aAAa;gBACxF,GAAG,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,SAAS,IAAI,EAAE,eAAe,EAAE,IAAI,CAAC,iBAAiB,CAAW,EAAE,CAAC;aACrG,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,CAAC,gBAAgB,CAAC,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,SAAS,EAAE,CAAC;YACxE,KAAK,CAAC,WAAW,GAAG;gBAClB,cAAc,EAAG,IAAI,CAAC,gBAAgB,CAAwB,IAAI,CAAC;gBACnE,KAAK,EAAG,IAAI,CAAC,OAAO,CAAwB,IAAI,CAAC;gBACjD,YAAY,EAAG,IAAI,CAAC,cAAc,CAA8B,IAAI,SAAS;aAC9E,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,SAAS;YAAE,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAW,CAAC;QAChF,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,SAAS;YAAE,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAW,CAAC;QAChF,IAAI,IAAI,CAAC,cAAc,CAAC,KAAK,SAAS;YAAE,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,cAAc,CAAW,CAAC;QAC5F,IAAI,IAAI,CAAC,gBAAgB,CAAC,KAAK,SAAS;YAAE,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC,gBAAgB,CAAmB,CAAC;QAE1G,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QAC1F,KAAK,CAAC,MAAM,CAAC,CAAC;IAChB,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerVersusMatch(versus: Command): void;
3
+ //# sourceMappingURL=match.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"match.d.ts","sourceRoot":"","sources":["../../../src/commands/versus/match.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CA4CzD"}
@@ -0,0 +1,45 @@
1
+ import { VersusClient } from "@1upmonster/versus";
2
+ import { requireCredentials } from "../../credentials.js";
3
+ import { fail, print, printTable } from "../../output.js";
4
+ import { API_BASE } from "../../config.js";
5
+ export function registerVersusMatch(versus) {
6
+ const match = versus.command("match").description("Inspect matches");
7
+ match
8
+ .command("list <gameId>")
9
+ .description("List active matches for a game")
10
+ .action(async (gameId) => {
11
+ const creds = await requireCredentials();
12
+ const client = new VersusClient({ baseUrl: API_BASE, token: creds.token });
13
+ const matches = await client.listMatches(gameId).catch((e) => fail(e.message));
14
+ printTable(matches.map((m) => ({
15
+ id: m.id,
16
+ state: m.state,
17
+ players: m.teams.flatMap((t) => t.players.map((p) => p.walletPubkey)).join(", "),
18
+ createdAt: new Date(m.createdAt).toISOString(),
19
+ expiresAt: new Date(m.expiresAt).toISOString(),
20
+ })));
21
+ });
22
+ match
23
+ .command("inspect <matchId>")
24
+ .description("Show full details of a match")
25
+ .action(async (matchId) => {
26
+ const creds = await requireCredentials();
27
+ const client = new VersusClient({ baseUrl: API_BASE, token: creds.token });
28
+ const result = await client.inspectMatch(matchId).catch((e) => fail(e.message));
29
+ print(result);
30
+ });
31
+ const queue = versus.command("queue").description("Queue stats");
32
+ queue
33
+ .command("status <gameId>")
34
+ .description("Show live queue stats for a game")
35
+ .action(async (gameId) => {
36
+ const creds = await requireCredentials();
37
+ const res = await fetch(`${API_BASE}/versus/${gameId}/queue/status`, {
38
+ headers: { Authorization: `Bearer ${creds.token}` },
39
+ });
40
+ if (!res.ok)
41
+ fail(await res.text());
42
+ print(await res.json());
43
+ });
44
+ }
45
+ //# sourceMappingURL=match.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"match.js","sourceRoot":"","sources":["../../../src/commands/versus/match.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const API_BASE: string;
2
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ,QAA4D,CAAC"}
package/dist/config.js ADDED
@@ -0,0 +1,2 @@
1
+ export const API_BASE = process.env["ONEUP_API_URL"] ?? "https://api.1up.monster";
2
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,yBAAyB,CAAC"}
@@ -0,0 +1,10 @@
1
+ export interface Credentials {
2
+ token: string;
3
+ walletPubkey: string;
4
+ expiresAt: number;
5
+ }
6
+ export declare function saveCredentials(creds: Credentials): Promise<void>;
7
+ export declare function loadCredentials(): Promise<Credentials | null>;
8
+ export declare function clearCredentials(): Promise<void>;
9
+ export declare function requireCredentials(): Promise<Credentials>;
10
+ //# sourceMappingURL=credentials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAKvE;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAkBnE;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMtD;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,WAAW,CAAC,CAS/D"}
@@ -0,0 +1,49 @@
1
+ import { mkdir, readFile, unlink, writeFile } from "node:fs/promises";
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+ const CONFIG_DIR = join(homedir(), ".config", "1upmonster");
5
+ const CREDENTIALS_FILE = join(CONFIG_DIR, "credentials.json");
6
+ export async function saveCredentials(creds) {
7
+ await mkdir(CONFIG_DIR, { recursive: true });
8
+ await writeFile(CREDENTIALS_FILE, JSON.stringify(creds, null, 2), {
9
+ mode: 0o600,
10
+ });
11
+ }
12
+ export async function loadCredentials() {
13
+ // Env var takes priority (CI / agent use)
14
+ const envKey = process.env["ONEUP_API_KEY"];
15
+ const envWallet = process.env["ONEUP_WALLET"];
16
+ if (envKey && envWallet) {
17
+ return { token: envKey, walletPubkey: envWallet, expiresAt: Infinity };
18
+ }
19
+ try {
20
+ const raw = await readFile(CREDENTIALS_FILE, "utf-8");
21
+ const creds = JSON.parse(raw);
22
+ if (!creds.token)
23
+ return null;
24
+ // Reject expired credentials so callers don't send stale JWTs (GAP-25)
25
+ if (creds.expiresAt !== Infinity && creds.expiresAt < Date.now())
26
+ return null;
27
+ return creds;
28
+ }
29
+ catch {
30
+ return null;
31
+ }
32
+ }
33
+ export async function clearCredentials() {
34
+ try {
35
+ await unlink(CREDENTIALS_FILE); // delete entirely, not overwrite with {} (GAP-26)
36
+ }
37
+ catch {
38
+ // file may not exist — that's fine
39
+ }
40
+ }
41
+ export async function requireCredentials() {
42
+ const creds = await loadCredentials();
43
+ if (!creds?.token) {
44
+ console.error("Not authenticated. Run: 1up auth login --keypair <path> or set ONEUP_API_KEY");
45
+ process.exit(1);
46
+ }
47
+ return creds;
48
+ }
49
+ //# sourceMappingURL=credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;AAC5D,MAAM,gBAAgB,GAAG,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;AAQ9D,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,KAAkB;IACtD,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,MAAM,SAAS,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;QAChE,IAAI,EAAE,KAAK;KACZ,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,0CAA0C;IAC1C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC5C,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC9C,IAAI,MAAM,IAAI,SAAS,EAAE,CAAC;QACxB,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;IACzE,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;QACtD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAgB,CAAC;QAC7C,IAAI,CAAC,KAAK,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QAC9B,uEAAuE;QACvE,IAAI,KAAK,CAAC,SAAS,KAAK,QAAQ,IAAI,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE;YAAE,OAAO,IAAI,CAAC;QAC9E,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,kDAAkD;IACpF,CAAC;IAAC,MAAM,CAAC;QACP,mCAAmC;IACrC,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,MAAM,KAAK,GAAG,MAAM,eAAe,EAAE,CAAC;IACtC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CACX,8EAA8E,CAC/E,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { registerAuth } from "./commands/auth.js";
4
+ import { registerTenant } from "./commands/tenant.js";
5
+ import { registerGameApiKeys } from "./commands/game-api-keys.js";
6
+ import { registerVersusConfig } from "./commands/versus/config.js";
7
+ import { registerVersusMatch } from "./commands/versus/match.js";
8
+ import { setJsonMode } from "./output.js";
9
+ const program = new Command();
10
+ program
11
+ .name("1up")
12
+ .description("1upmonster CLI — manage your game infrastructure from the terminal")
13
+ .version("0.1.0")
14
+ .option("--json", "Output as JSON (machine-readable, AI-agent friendly)")
15
+ .option("--quiet", "Suppress non-essential output")
16
+ .hook("preAction", (thisCommand) => {
17
+ const opts = thisCommand.opts();
18
+ if (opts.json)
19
+ setJsonMode(true);
20
+ });
21
+ registerAuth(program);
22
+ const game = registerTenant(program);
23
+ registerGameApiKeys(game);
24
+ // Versus service
25
+ const versus = program.command("versus").description("Versus — matchmaking service");
26
+ registerVersusConfig(versus);
27
+ registerVersusMatch(versus);
28
+ program.parseAsync(process.argv).catch((err) => {
29
+ console.error(err);
30
+ process.exit(1);
31
+ });
32
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,KAAK,CAAC;KACX,WAAW,CAAC,oEAAoE,CAAC;KACjF,OAAO,CAAC,OAAO,CAAC;KAChB,MAAM,CAAC,QAAQ,EAAE,sDAAsD,CAAC;KACxE,MAAM,CAAC,SAAS,EAAE,+BAA+B,CAAC;KAClD,IAAI,CAAC,WAAW,EAAE,CAAC,WAAW,EAAE,EAAE;IACjC,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,EAAsB,CAAC;IACpD,IAAI,IAAI,CAAC,IAAI;QAAE,WAAW,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC,CAAC,CAAC;AAEL,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;AACrC,mBAAmB,CAAC,IAAI,CAAC,CAAC;AAE1B,iBAAiB;AACjB,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,8BAA8B,CAAC,CAAC;AACrF,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAC7B,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAE5B,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IACtD,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function setJsonMode(val: boolean): void;
2
+ export declare function print(data: unknown): void;
3
+ export declare function printTable(rows: Record<string, unknown>[]): void;
4
+ export declare function fail(message: string, exitCode?: number): never;
5
+ //# sourceMappingURL=output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAE9C;AAED,wBAAgB,KAAK,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAUzC;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI,CAMhE;AAED,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,SAAI,GAAG,KAAK,CAOzD"}
package/dist/output.js ADDED
@@ -0,0 +1,34 @@
1
+ let jsonMode = false;
2
+ export function setJsonMode(val) {
3
+ jsonMode = val;
4
+ }
5
+ export function print(data) {
6
+ if (jsonMode) {
7
+ console.log(JSON.stringify(data, null, 2));
8
+ }
9
+ else {
10
+ if (typeof data === "string") {
11
+ console.log(data);
12
+ }
13
+ else {
14
+ console.log(JSON.stringify(data, null, 2));
15
+ }
16
+ }
17
+ }
18
+ export function printTable(rows) {
19
+ if (jsonMode || rows.length === 0) {
20
+ print(rows);
21
+ return;
22
+ }
23
+ console.table(rows);
24
+ }
25
+ export function fail(message, exitCode = 1) {
26
+ if (jsonMode) {
27
+ console.error(JSON.stringify({ error: message }));
28
+ }
29
+ else {
30
+ console.error(`Error: ${message}`);
31
+ }
32
+ process.exit(exitCode);
33
+ }
34
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA,IAAI,QAAQ,GAAG,KAAK,CAAC;AAErB,MAAM,UAAU,WAAW,CAAC,GAAY;IACtC,QAAQ,GAAG,GAAG,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,IAAa;IACjC,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;SAAM,CAAC;QACN,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAA+B;IACxD,IAAI,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,CAAC;QACZ,OAAO;IACT,CAAC;IACD,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,OAAe,EAAE,QAAQ,GAAG,CAAC;IAChD,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IACpD,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,UAAU,OAAO,EAAE,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACzB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@1upmonster/cli",
3
+ "version": "0.1.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "bin": {
7
+ "1up": "./dist/index.js"
8
+ },
9
+ "publishConfig": {
10
+ "access": "public"
11
+ },
12
+ "files": [
13
+ "dist"
14
+ ],
15
+ "dependencies": {
16
+ "@solana/kit": "^6.1.0",
17
+ "commander": "^12.1.0",
18
+ "@1upmonster/types": "0.1.0",
19
+ "@1upmonster/versus": "0.1.0",
20
+ "@1upmonster/sdk": "0.1.0"
21
+ },
22
+ "devDependencies": {
23
+ "@types/node": "^22.10.2",
24
+ "typescript": "^5.7.2"
25
+ },
26
+ "scripts": {
27
+ "build": "tsc",
28
+ "typecheck": "tsc --noEmit",
29
+ "clean": "rm -rf dist",
30
+ "dev": "node --watch dist/index.js"
31
+ }
32
+ }