guesty-cli 1.0.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 (47) hide show
  1. package/dist/auth.d.ts +2 -0
  2. package/dist/auth.js +156 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.js +46 -0
  5. package/dist/client.d.ts +7 -0
  6. package/dist/client.js +109 -0
  7. package/dist/commands/accounting.d.ts +2 -0
  8. package/dist/commands/accounting.js +102 -0
  9. package/dist/commands/calendar.d.ts +2 -0
  10. package/dist/commands/calendar.js +60 -0
  11. package/dist/commands/conversations.d.ts +2 -0
  12. package/dist/commands/conversations.js +40 -0
  13. package/dist/commands/financials.d.ts +2 -0
  14. package/dist/commands/financials.js +56 -0
  15. package/dist/commands/guests.d.ts +2 -0
  16. package/dist/commands/guests.js +57 -0
  17. package/dist/commands/init.d.ts +2 -0
  18. package/dist/commands/init.js +109 -0
  19. package/dist/commands/integrations.d.ts +2 -0
  20. package/dist/commands/integrations.js +62 -0
  21. package/dist/commands/listings.d.ts +2 -0
  22. package/dist/commands/listings.js +72 -0
  23. package/dist/commands/owners.d.ts +2 -0
  24. package/dist/commands/owners.js +76 -0
  25. package/dist/commands/properties.d.ts +2 -0
  26. package/dist/commands/properties.js +104 -0
  27. package/dist/commands/quotes.d.ts +2 -0
  28. package/dist/commands/quotes.js +31 -0
  29. package/dist/commands/raw.d.ts +2 -0
  30. package/dist/commands/raw.js +19 -0
  31. package/dist/commands/reservations.d.ts +2 -0
  32. package/dist/commands/reservations.js +126 -0
  33. package/dist/commands/reviews.d.ts +2 -0
  34. package/dist/commands/reviews.js +39 -0
  35. package/dist/commands/tasks.d.ts +2 -0
  36. package/dist/commands/tasks.js +60 -0
  37. package/dist/commands/users.d.ts +2 -0
  38. package/dist/commands/users.js +59 -0
  39. package/dist/commands/webhooks.d.ts +2 -0
  40. package/dist/commands/webhooks.js +52 -0
  41. package/dist/env.d.ts +1 -0
  42. package/dist/env.js +44 -0
  43. package/dist/output.d.ts +2 -0
  44. package/dist/output.js +22 -0
  45. package/dist/stdin.d.ts +1 -0
  46. package/dist/stdin.js +12 -0
  47. package/package.json +41 -0
@@ -0,0 +1,109 @@
1
+ import { Command } from "commander";
2
+ import { createInterface } from "node:readline";
3
+ import { writeFileSync, mkdirSync, existsSync, readFileSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ import { homedir } from "node:os";
6
+ const CONFIG_DIR = join(homedir(), ".guesty-cli");
7
+ const ENV_FILE = join(CONFIG_DIR, ".env");
8
+ function prompt(question, mask = false) {
9
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
10
+ return new Promise((resolve) => {
11
+ if (mask && process.stdin.isTTY) {
12
+ process.stdout.write(question);
13
+ let value = "";
14
+ process.stdin.setRawMode(true);
15
+ process.stdin.resume();
16
+ process.stdin.setEncoding("utf8");
17
+ const onData = (ch) => {
18
+ if (ch === "\r" || ch === "\n") {
19
+ process.stdin.setRawMode(false);
20
+ process.stdin.pause();
21
+ process.stdin.removeListener("data", onData);
22
+ rl.close();
23
+ process.stdout.write("\n");
24
+ resolve(value);
25
+ }
26
+ else if (ch === "\u0003") {
27
+ process.exit(1);
28
+ }
29
+ else if (ch === "\u007F" || ch === "\b") {
30
+ if (value.length > 0) {
31
+ value = value.slice(0, -1);
32
+ process.stdout.write("\b \b");
33
+ }
34
+ }
35
+ else {
36
+ value += ch;
37
+ process.stdout.write("*");
38
+ }
39
+ };
40
+ process.stdin.on("data", onData);
41
+ }
42
+ else {
43
+ rl.question(question, (answer) => {
44
+ rl.close();
45
+ resolve(answer.trim());
46
+ });
47
+ }
48
+ });
49
+ }
50
+ async function testCredentials(clientId, clientSecret) {
51
+ try {
52
+ const res = await fetch("https://open-api.guesty.com/oauth2/token", {
53
+ method: "POST",
54
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
55
+ body: new URLSearchParams({
56
+ grant_type: "client_credentials",
57
+ scope: "open-api",
58
+ client_id: clientId,
59
+ client_secret: clientSecret,
60
+ }),
61
+ });
62
+ return res.ok;
63
+ }
64
+ catch {
65
+ return false;
66
+ }
67
+ }
68
+ export const init = new Command("init")
69
+ .description("Set up Guesty CLI with your API credentials")
70
+ .option("--force", "Overwrite existing configuration")
71
+ .action(async (opts) => {
72
+ process.stdout.write("\n Guesty CLI Setup\n");
73
+ process.stdout.write(" ================\n\n");
74
+ if (existsSync(ENV_FILE) && !opts.force) {
75
+ const existing = readFileSync(ENV_FILE, "utf8");
76
+ if (existing.includes("GUESTY_CLIENT_ID")) {
77
+ process.stdout.write(" Already configured. Run 'guesty init --force' to reconfigure.\n\n");
78
+ return;
79
+ }
80
+ }
81
+ process.stdout.write(" You'll need your Guesty Open API credentials.\n");
82
+ process.stdout.write(" Get them from: Guesty Dashboard > Marketplace > Open API\n\n");
83
+ const clientId = await prompt(" Client ID: ");
84
+ if (!clientId) {
85
+ process.stderr.write("\n Error: Client ID is required.\n\n");
86
+ process.exit(1);
87
+ }
88
+ const clientSecret = await prompt(" Client Secret: ", true);
89
+ if (!clientSecret) {
90
+ process.stderr.write("\n Error: Client Secret is required.\n\n");
91
+ process.exit(1);
92
+ }
93
+ process.stdout.write("\n Verifying credentials...");
94
+ const valid = await testCredentials(clientId, clientSecret);
95
+ if (!valid) {
96
+ process.stdout.write(" failed.\n\n");
97
+ process.stderr.write(" Error: Invalid credentials. Check your Client ID and Secret.\n");
98
+ process.stderr.write(" Note: This uses 1 of your 5 daily token requests for verification.\n\n");
99
+ process.exit(1);
100
+ }
101
+ process.stdout.write(" verified.\n");
102
+ if (!existsSync(CONFIG_DIR)) {
103
+ mkdirSync(CONFIG_DIR, { recursive: true });
104
+ }
105
+ const envContent = `GUESTY_CLIENT_ID=${clientId}\nGUESTY_CLIENT_SECRET=${clientSecret}\n`;
106
+ writeFileSync(ENV_FILE, envContent);
107
+ process.stdout.write(`\n Configuration saved to ${ENV_FILE}\n`);
108
+ process.stdout.write(" You're all set! Try: guesty res list --limit 1\n\n");
109
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const integrations: Command;
@@ -0,0 +1,62 @@
1
+ import { Command } from "commander";
2
+ import { guestyFetch } from "../client.js";
3
+ import { print } from "../output.js";
4
+ export const integrations = new Command("integrations")
5
+ .alias("int")
6
+ .description("Manage integrations and channels");
7
+ integrations
8
+ .command("list")
9
+ .description("List all integrations")
10
+ .action(async () => {
11
+ const data = await guestyFetch("/v1/integrations");
12
+ print(data);
13
+ });
14
+ integrations
15
+ .command("get <id>")
16
+ .description("Get an integration by ID")
17
+ .action(async (id) => {
18
+ const data = await guestyFetch(`/v1/integrations/${id}`);
19
+ print(data);
20
+ });
21
+ integrations
22
+ .command("channels")
23
+ .description("List supported marketing channels")
24
+ .action(async () => {
25
+ const data = await guestyFetch("/v1/marketing/channels");
26
+ print(data);
27
+ });
28
+ integrations
29
+ .command("promotions")
30
+ .description("List all promotions")
31
+ .action(async () => {
32
+ const data = await guestyFetch("/v1/rm-promotions/promotions");
33
+ print(data);
34
+ });
35
+ integrations
36
+ .command("rate-plans")
37
+ .description("List all rate plans")
38
+ .action(async () => {
39
+ const data = await guestyFetch("/v1/rm-rate-plans-ext/rate-plans");
40
+ print(data);
41
+ });
42
+ integrations
43
+ .command("rate-plan <id>")
44
+ .description("Get a rate plan by ID")
45
+ .action(async (id) => {
46
+ const data = await guestyFetch(`/v1/rm-rate-plans-ext/rate-plans/${id}`);
47
+ print(data);
48
+ });
49
+ integrations
50
+ .command("views")
51
+ .description("List all views")
52
+ .action(async () => {
53
+ const data = await guestyFetch("/v1/views");
54
+ print(data);
55
+ });
56
+ integrations
57
+ .command("view <id>")
58
+ .description("Get a view by ID")
59
+ .action(async (id) => {
60
+ const data = await guestyFetch(`/v1/views/${id}`);
61
+ print(data);
62
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const listings: Command;
@@ -0,0 +1,72 @@
1
+ import { Command } from "commander";
2
+ import { guestyFetch, paginateAll } from "../client.js";
3
+ import { print } from "../output.js";
4
+ import { readStdin } from "../stdin.js";
5
+ export const listings = new Command("listings")
6
+ .alias("ls")
7
+ .description("Manage listings");
8
+ listings
9
+ .command("list")
10
+ .description("List all listings")
11
+ .option("--fields <fields>", "Comma-separated fields to return")
12
+ .option("--limit <n>", "Max results", "100")
13
+ .option("--skip <n>", "Offset", "0")
14
+ .option("--all", "Fetch all pages")
15
+ .option("--active", "Only active listings")
16
+ .action(async (opts) => {
17
+ const params = {
18
+ limit: parseInt(opts.limit),
19
+ skip: parseInt(opts.skip),
20
+ };
21
+ if (opts.fields)
22
+ params.fields = opts.fields;
23
+ if (opts.active)
24
+ params.active = true;
25
+ if (opts.all) {
26
+ const results = await paginateAll("/v1/listings", params, "results");
27
+ print(results);
28
+ }
29
+ else {
30
+ const data = await guestyFetch("/v1/listings", { params });
31
+ print(data);
32
+ }
33
+ });
34
+ listings
35
+ .command("get <id>")
36
+ .description("Get a single listing by ID")
37
+ .option("--fields <fields>", "Comma-separated fields to return")
38
+ .action(async (id, opts) => {
39
+ const params = {};
40
+ if (opts.fields)
41
+ params.fields = opts.fields;
42
+ const data = await guestyFetch(`/v1/listings/${id}`, { params });
43
+ print(data);
44
+ });
45
+ listings
46
+ .command("update <id>")
47
+ .description("Update a listing (--data or stdin)")
48
+ .option("--data <json>", "JSON body")
49
+ .action(async (id, opts) => {
50
+ const body = opts.data
51
+ ? JSON.parse(opts.data)
52
+ : JSON.parse(await readStdin());
53
+ const data = await guestyFetch(`/v1/listings/${id}`, {
54
+ method: "PUT",
55
+ body,
56
+ });
57
+ print(data);
58
+ });
59
+ listings
60
+ .command("custom-fields <id>")
61
+ .description("Get custom fields for a listing")
62
+ .action(async (id) => {
63
+ const data = await guestyFetch(`/v1/listings/${id}/custom-fields`);
64
+ print(data);
65
+ });
66
+ listings
67
+ .command("financials <id>")
68
+ .description("Get financial settings for a listing")
69
+ .action(async (id) => {
70
+ const data = await guestyFetch(`/v1/financials/${id}`);
71
+ print(data);
72
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const owners: Command;
@@ -0,0 +1,76 @@
1
+ import { Command } from "commander";
2
+ import { guestyFetch } from "../client.js";
3
+ import { print } from "../output.js";
4
+ import { readStdin } from "../stdin.js";
5
+ export const owners = new Command("owners")
6
+ .description("Manage owners and ownerships");
7
+ owners
8
+ .command("list")
9
+ .description("List all owners")
10
+ .option("--limit <n>", "Max results", "25")
11
+ .option("--skip <n>", "Offset", "0")
12
+ .action(async (opts) => {
13
+ const data = await guestyFetch("/v1/owners", {
14
+ params: { limit: parseInt(opts.limit), skip: parseInt(opts.skip) },
15
+ });
16
+ print(data);
17
+ });
18
+ owners
19
+ .command("get <ownerId>")
20
+ .description("Get a single owner")
21
+ .action(async (ownerId) => {
22
+ const data = await guestyFetch(`/v1/owners/${ownerId}`);
23
+ print(data);
24
+ });
25
+ owners
26
+ .command("create")
27
+ .description("Create an owner (--data or stdin)")
28
+ .option("--data <json>", "JSON body")
29
+ .action(async (opts) => {
30
+ const body = opts.data ? JSON.parse(opts.data) : JSON.parse(await readStdin());
31
+ const data = await guestyFetch("/v1/owners", { method: "POST", body });
32
+ print(data);
33
+ });
34
+ owners
35
+ .command("update <ownerId>")
36
+ .description("Update an owner (--data or stdin)")
37
+ .option("--data <json>", "JSON body")
38
+ .action(async (ownerId, opts) => {
39
+ const body = opts.data ? JSON.parse(opts.data) : JSON.parse(await readStdin());
40
+ const data = await guestyFetch(`/v1/owners/${ownerId}`, { method: "PUT", body });
41
+ print(data);
42
+ });
43
+ owners
44
+ .command("delete <ownerId>")
45
+ .description("Delete an owner")
46
+ .action(async (ownerId) => {
47
+ const data = await guestyFetch(`/v1/owners/${ownerId}`, { method: "DELETE" });
48
+ print(data);
49
+ });
50
+ owners
51
+ .command("ownerships <listingId>")
52
+ .description("Get ownerships for a listing")
53
+ .action(async (listingId) => {
54
+ const data = await guestyFetch(`/v1/owners/listings/${listingId}/ownerships`);
55
+ print(data);
56
+ });
57
+ owners
58
+ .command("set-ownerships <listingId>")
59
+ .description("Set ownerships for a listing (--data or stdin)")
60
+ .option("--data <json>", "JSON body")
61
+ .action(async (listingId, opts) => {
62
+ const body = opts.data ? JSON.parse(opts.data) : JSON.parse(await readStdin());
63
+ const data = await guestyFetch(`/v1/owners/listings/${listingId}/ownerships`, { method: "PUT", body });
64
+ print(data);
65
+ });
66
+ owners
67
+ .command("reservations")
68
+ .description("List owner reservations")
69
+ .option("--limit <n>", "Max results", "25")
70
+ .option("--skip <n>", "Offset", "0")
71
+ .action(async (opts) => {
72
+ const data = await guestyFetch("/v1/owners-reservations", {
73
+ params: { limit: parseInt(opts.limit), skip: parseInt(opts.skip) },
74
+ });
75
+ print(data);
76
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const properties: Command;
@@ -0,0 +1,104 @@
1
+ import { Command } from "commander";
2
+ import { guestyFetch } from "../client.js";
3
+ import { print } from "../output.js";
4
+ import { readStdin } from "../stdin.js";
5
+ export const properties = new Command("properties")
6
+ .alias("prop")
7
+ .description("Property settings: amenities, photos, spaces, house rules, complexes");
8
+ properties
9
+ .command("amenities <propertyId>")
10
+ .description("Get amenities for a property")
11
+ .action(async (id) => {
12
+ const data = await guestyFetch(`/v1/properties-api/amenities/${id}`);
13
+ print(data);
14
+ });
15
+ properties
16
+ .command("set-amenities <propertyId>")
17
+ .description("Set amenities for a property (--data or stdin)")
18
+ .option("--data <json>", "JSON body")
19
+ .action(async (id, opts) => {
20
+ const body = opts.data ? JSON.parse(opts.data) : JSON.parse(await readStdin());
21
+ const data = await guestyFetch(`/v1/properties-api/amenities/${id}`, { method: "PUT", body });
22
+ print(data);
23
+ });
24
+ properties
25
+ .command("supported-amenities")
26
+ .description("List all supported amenities")
27
+ .action(async () => {
28
+ const data = await guestyFetch("/v1/properties-api/amenities/supported");
29
+ print(data);
30
+ });
31
+ properties
32
+ .command("photos <propertyId>")
33
+ .description("Get all photos for a property")
34
+ .action(async (id) => {
35
+ const data = await guestyFetch(`/v1/properties-api/property-photos/property-photos/${id}`);
36
+ print(data);
37
+ });
38
+ properties
39
+ .command("add-photos <propertyId>")
40
+ .description("Add photos to a property (--data or stdin)")
41
+ .option("--data <json>", "JSON body")
42
+ .action(async (id, opts) => {
43
+ const body = opts.data ? JSON.parse(opts.data) : JSON.parse(await readStdin());
44
+ const data = await guestyFetch(`/v1/properties-api/property-photos/property-photos/${id}`, { method: "POST", body });
45
+ print(data);
46
+ });
47
+ properties
48
+ .command("spaces <unitTypeId>")
49
+ .description("Get spaces for a unit type")
50
+ .action(async (id) => {
51
+ const data = await guestyFetch(`/v1/properties/spaces/unit-type/${id}`);
52
+ print(data);
53
+ });
54
+ properties
55
+ .command("house-rules <unitTypeId>")
56
+ .description("Get house rules for a unit type")
57
+ .action(async (id) => {
58
+ const data = await guestyFetch(`/v1/properties/house-rules/unit-type/${id}`);
59
+ print(data);
60
+ });
61
+ properties
62
+ .command("set-house-rules <unitTypeId>")
63
+ .description("Update house rules (--data or stdin)")
64
+ .option("--data <json>", "JSON body")
65
+ .action(async (id, opts) => {
66
+ const body = opts.data ? JSON.parse(opts.data) : JSON.parse(await readStdin());
67
+ const data = await guestyFetch(`/v1/properties/house-rules/unit-type/${id}`, { method: "PUT", body });
68
+ print(data);
69
+ });
70
+ properties
71
+ .command("address <propertyId>")
72
+ .description("Get property address")
73
+ .action(async (id) => {
74
+ const data = await guestyFetch(`/v1/address/${id}`);
75
+ print(data);
76
+ });
77
+ properties
78
+ .command("complexes")
79
+ .description("List all complexes")
80
+ .action(async () => {
81
+ const data = await guestyFetch("/v1/properties-api/complexes");
82
+ print(data);
83
+ });
84
+ properties
85
+ .command("complex <id>")
86
+ .description("Get a complex by ID")
87
+ .action(async (id) => {
88
+ const data = await guestyFetch(`/v1/properties-api/complexes/${id}`);
89
+ print(data);
90
+ });
91
+ properties
92
+ .command("logs <propertyId>")
93
+ .description("Get property logs")
94
+ .action(async (id) => {
95
+ const data = await guestyFetch(`/v1/property-logs/${id}`);
96
+ print(data);
97
+ });
98
+ properties
99
+ .command("custom-fields <propertyId>")
100
+ .description("Get custom fields for a property")
101
+ .action(async (id) => {
102
+ const data = await guestyFetch(`/v1/properties-api/custom-fields/${id}`);
103
+ print(data);
104
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const quotes: Command;
@@ -0,0 +1,31 @@
1
+ import { Command } from "commander";
2
+ import { guestyFetch } from "../client.js";
3
+ import { print } from "../output.js";
4
+ import { readStdin } from "../stdin.js";
5
+ export const quotes = new Command("quotes")
6
+ .description("Manage quotes");
7
+ quotes
8
+ .command("get <quoteId>")
9
+ .description("Get a quote by ID")
10
+ .action(async (id) => {
11
+ const data = await guestyFetch(`/v1/quotes/${id}`);
12
+ print(data);
13
+ });
14
+ quotes
15
+ .command("create")
16
+ .description("Create a quote (--data or stdin)")
17
+ .option("--data <json>", "JSON body")
18
+ .action(async (opts) => {
19
+ const body = opts.data ? JSON.parse(opts.data) : JSON.parse(await readStdin());
20
+ const data = await guestyFetch("/v1/quotes", { method: "POST", body });
21
+ print(data);
22
+ });
23
+ quotes
24
+ .command("create-multiple")
25
+ .description("Create multiple quotes (--data or stdin)")
26
+ .option("--data <json>", "JSON body")
27
+ .action(async (opts) => {
28
+ const body = opts.data ? JSON.parse(opts.data) : JSON.parse(await readStdin());
29
+ const data = await guestyFetch("/v1/quotes/multiple", { method: "POST", body });
30
+ print(data);
31
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const raw: Command;
@@ -0,0 +1,19 @@
1
+ import { Command } from "commander";
2
+ import { guestyFetch } from "../client.js";
3
+ import { print } from "../output.js";
4
+ export const raw = new Command("raw")
5
+ .description("Make a raw API call to any Guesty endpoint")
6
+ .argument("<method>", "HTTP method (GET, POST, PUT, DELETE, PATCH)")
7
+ .argument("<path>", "API path (e.g. /v1/listings)")
8
+ .option("--data <json>", "JSON body")
9
+ .option("--params <json>", "Query params as JSON")
10
+ .action(async (method, path, opts) => {
11
+ const body = opts.data ? JSON.parse(opts.data) : undefined;
12
+ const params = opts.params ? JSON.parse(opts.params) : undefined;
13
+ const data = await guestyFetch(path, {
14
+ method: method.toUpperCase(),
15
+ body,
16
+ params,
17
+ });
18
+ print(data);
19
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const reservations: Command;
@@ -0,0 +1,126 @@
1
+ import { Command } from "commander";
2
+ import { guestyFetch, paginateAll } from "../client.js";
3
+ import { print } from "../output.js";
4
+ import { readStdin } from "../stdin.js";
5
+ export const reservations = new Command("reservations")
6
+ .alias("res")
7
+ .description("Manage reservations");
8
+ reservations
9
+ .command("list")
10
+ .description("List reservations with optional filters")
11
+ .option("--from <date>", "Check-in from date (YYYY-MM-DD)")
12
+ .option("--to <date>", "Check-in to date (YYYY-MM-DD)")
13
+ .option("--status <status>", "Filter by status (confirmed, canceled, inquiry, etc.)")
14
+ .option("--listing <id>", "Filter by listing ID")
15
+ .option("--guest <name>", "Filter by guest name")
16
+ .option("--source <source>", "Filter by source (Airbnb, Booking.com, etc.)")
17
+ .option("--limit <n>", "Max results", "25")
18
+ .option("--skip <n>", "Offset", "0")
19
+ .option("--sort <field>", "Sort field", "checkIn")
20
+ .option("--fields <fields>", "Comma-separated fields to return")
21
+ .option("--all", "Fetch all pages (up to 10k)")
22
+ .action(async (opts) => {
23
+ const params = {
24
+ limit: parseInt(opts.limit),
25
+ skip: parseInt(opts.skip),
26
+ sort: opts.sort,
27
+ };
28
+ if (opts.fields)
29
+ params.fields = opts.fields;
30
+ if (opts.status)
31
+ params.status = opts.status;
32
+ if (opts.listing)
33
+ params.listingId = opts.listing;
34
+ if (opts.source)
35
+ params.source = opts.source;
36
+ const filters = [];
37
+ if (opts.from)
38
+ filters.push(`checkIn>=${opts.from}`);
39
+ if (opts.to)
40
+ filters.push(`checkIn<=${opts.to}`);
41
+ if (opts.guest)
42
+ filters.push(`guestName=${opts.guest}`);
43
+ if (filters.length > 0)
44
+ params.filters = filters.join(",");
45
+ if (opts.all) {
46
+ const results = await paginateAll("/v1/reservations", params, "results");
47
+ print(results);
48
+ }
49
+ else {
50
+ const data = await guestyFetch("/v1/reservations", { params });
51
+ print(data);
52
+ }
53
+ });
54
+ reservations
55
+ .command("get <id>")
56
+ .description("Get a single reservation by ID")
57
+ .option("--fields <fields>", "Comma-separated fields to return")
58
+ .action(async (id, opts) => {
59
+ const params = {};
60
+ if (opts.fields)
61
+ params.fields = opts.fields;
62
+ const data = await guestyFetch(`/v1/reservations/${id}`, { params });
63
+ print(data);
64
+ });
65
+ reservations
66
+ .command("search <query>")
67
+ .description("Search reservations by guest name or confirmation code")
68
+ .option("--limit <n>", "Max results", "25")
69
+ .action(async (query, opts) => {
70
+ const data = await guestyFetch("/v1/reservations", {
71
+ params: {
72
+ q: query,
73
+ limit: parseInt(opts.limit),
74
+ },
75
+ });
76
+ print(data);
77
+ });
78
+ reservations
79
+ .command("update <id>")
80
+ .description("Update a reservation (pass JSON body via stdin or --data)")
81
+ .option("--data <json>", "JSON body")
82
+ .action(async (id, opts) => {
83
+ const body = opts.data
84
+ ? JSON.parse(opts.data)
85
+ : JSON.parse(await readStdin());
86
+ const data = await guestyFetch(`/v1/reservations/${id}`, {
87
+ method: "PUT",
88
+ body,
89
+ });
90
+ print(data);
91
+ });
92
+ reservations
93
+ .command("create")
94
+ .description("Create a reservation (pass JSON body via stdin or --data)")
95
+ .option("--data <json>", "JSON body")
96
+ .action(async (opts) => {
97
+ const body = opts.data
98
+ ? JSON.parse(opts.data)
99
+ : JSON.parse(await readStdin());
100
+ const data = await guestyFetch("/v1/reservations", {
101
+ method: "POST",
102
+ body,
103
+ });
104
+ print(data);
105
+ });
106
+ reservations
107
+ .command("balance <id>")
108
+ .description("Get the folio/balance for a reservation")
109
+ .action(async (id) => {
110
+ const data = await guestyFetch(`/v1/accounting-api/reservations/${id}/balance`);
111
+ print(data);
112
+ });
113
+ reservations
114
+ .command("add-payment <id>")
115
+ .description("Add a payment to a reservation (--data or stdin)")
116
+ .option("--data <json>", "JSON body")
117
+ .action(async (id, opts) => {
118
+ const body = opts.data
119
+ ? JSON.parse(opts.data)
120
+ : JSON.parse(await readStdin());
121
+ const data = await guestyFetch(`/v1/reservations/${id}/payments`, {
122
+ method: "POST",
123
+ body,
124
+ });
125
+ print(data);
126
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const reviews: Command;
@@ -0,0 +1,39 @@
1
+ import { Command } from "commander";
2
+ import { guestyFetch } from "../client.js";
3
+ import { print } from "../output.js";
4
+ export const reviews = new Command("reviews")
5
+ .description("Manage reviews");
6
+ reviews
7
+ .command("list")
8
+ .description("List reviews")
9
+ .option("--listing <id>", "Filter by listing ID")
10
+ .option("--limit <n>", "Max results", "25")
11
+ .option("--skip <n>", "Offset", "0")
12
+ .action(async (opts) => {
13
+ const params = {
14
+ limit: parseInt(opts.limit),
15
+ skip: parseInt(opts.skip),
16
+ };
17
+ if (opts.listing)
18
+ params.listingId = opts.listing;
19
+ const data = await guestyFetch("/v1/reviews", { params });
20
+ print(data);
21
+ });
22
+ reviews
23
+ .command("get <id>")
24
+ .description("Get a single review")
25
+ .action(async (id) => {
26
+ const data = await guestyFetch(`/v1/reviews/${id}`);
27
+ print(data);
28
+ });
29
+ reviews
30
+ .command("reply <id>")
31
+ .description("Reply to a review")
32
+ .requiredOption("--body <text>", "Reply text")
33
+ .action(async (id, opts) => {
34
+ const data = await guestyFetch(`/v1/reviews/${id}/reply`, {
35
+ method: "POST",
36
+ body: { body: opts.body },
37
+ });
38
+ print(data);
39
+ });