@studiometa/forge-sdk 0.2.3 → 0.2.5
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/README.md +80 -6
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +71 -0
- package/dist/index.js.map +1 -1
- package/dist/resources/servers.d.ts +37 -0
- package/dist/resources/servers.d.ts.map +1 -1
- package/dist/resources/sites.d.ts +18 -0
- package/dist/resources/sites.d.ts.map +1 -1
- package/dist/utils/name-matcher.d.ts +12 -0
- package/dist/utils/name-matcher.d.ts.map +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -48,6 +48,7 @@ forge.servers.create({ ... }) // Create a server
|
|
|
48
48
|
forge.servers.update(id, { ... }) // Update a server
|
|
49
49
|
forge.servers.delete(id) // Delete a server
|
|
50
50
|
forge.servers.reboot(id) // Reboot a server
|
|
51
|
+
forge.servers.resolve('prod') // Find servers by name
|
|
51
52
|
|
|
52
53
|
// Resource with nested access
|
|
53
54
|
forge.server(id).get() // Get server details
|
|
@@ -58,6 +59,26 @@ forge.server(id).databases.list() // List databases
|
|
|
58
59
|
forge.server(id).daemons.list() // List daemons
|
|
59
60
|
```
|
|
60
61
|
|
|
62
|
+
#### `servers.resolve(query)`
|
|
63
|
+
|
|
64
|
+
Find servers by name using **case-insensitive partial matching**. If exactly one server matches the query exactly (whole name), only that server is returned — otherwise all partial matches are returned.
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
const result = await forge.servers.resolve("prod");
|
|
68
|
+
// → { query: 'prod', matches: [{ id: 725393, name: 'wilo-grove-prod' }], total: 1 }
|
|
69
|
+
|
|
70
|
+
if (result.total === 1) {
|
|
71
|
+
const sites = await forge.server(result.matches[0].id).sites.list();
|
|
72
|
+
} else if (result.total === 0) {
|
|
73
|
+
console.error("No server found for:", result.query);
|
|
74
|
+
} else {
|
|
75
|
+
console.error(
|
|
76
|
+
"Ambiguous query, matched:",
|
|
77
|
+
result.matches.map((m) => m.name),
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
61
82
|
### Sites
|
|
62
83
|
|
|
63
84
|
```typescript
|
|
@@ -67,6 +88,7 @@ forge.server(id).sites.get(siteId) // Get a site
|
|
|
67
88
|
forge.server(id).sites.create({ domain: 'example.com', project_type: 'php' })
|
|
68
89
|
forge.server(id).sites.update(siteId, { ... })
|
|
69
90
|
forge.server(id).sites.delete(siteId)
|
|
91
|
+
forge.server(id).sites.resolve('example') // Find sites by domain name
|
|
70
92
|
|
|
71
93
|
// Resource with nested access
|
|
72
94
|
forge.server(id).site(siteId).get() // Get site details
|
|
@@ -78,6 +100,49 @@ forge.server(id).site(siteId).nginx.get() // Get Nginx config
|
|
|
78
100
|
forge.server(id).site(siteId).nginx.update('...') // Update Nginx
|
|
79
101
|
```
|
|
80
102
|
|
|
103
|
+
#### `sites.resolve(query)`
|
|
104
|
+
|
|
105
|
+
Find sites by domain name using **case-insensitive partial matching**. Same priority logic as `servers.resolve()`: an exact match wins if there is exactly one, otherwise all partial matches are returned.
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
const result = await forge.server(123).sites.resolve("example");
|
|
109
|
+
// → { query: 'example', matches: [{ id: 456, name: 'example.com' }], total: 1 }
|
|
110
|
+
|
|
111
|
+
if (result.total === 1) {
|
|
112
|
+
await forge.server(123).site(result.matches[0].id).deploy();
|
|
113
|
+
} else if (result.total === 0) {
|
|
114
|
+
console.error("No site found for:", result.query);
|
|
115
|
+
} else {
|
|
116
|
+
console.error(
|
|
117
|
+
"Ambiguous query, matched:",
|
|
118
|
+
result.matches.map((m) => m.name),
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Types: `ResolveResult` and `ResolveMatch`
|
|
124
|
+
|
|
125
|
+
Both `servers.resolve()` and `sites.resolve()` return a `ResolveResult`:
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
interface ResolveMatch {
|
|
129
|
+
id: number; // Forge resource ID
|
|
130
|
+
name: string; // Server name or site domain
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
interface ResolveResult {
|
|
134
|
+
query: string; // The original search query
|
|
135
|
+
matches: ResolveMatch[]; // Matched resources (empty if none)
|
|
136
|
+
total: number; // Number of matches (0, 1, or many)
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Both types are exported from the package:
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
import type { ResolveMatch, ResolveResult } from "@studiometa/forge-sdk";
|
|
144
|
+
```
|
|
145
|
+
|
|
81
146
|
### Deployments
|
|
82
147
|
|
|
83
148
|
```typescript
|
|
@@ -159,13 +224,22 @@ import { Forge } from "@studiometa/forge-sdk";
|
|
|
159
224
|
|
|
160
225
|
const forge = new Forge(process.env.FORGE_API_TOKEN);
|
|
161
226
|
|
|
162
|
-
// Deploy after successful CI
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
console.log("Deployment triggered!");
|
|
227
|
+
// Deploy after successful CI using resolve() to find the server and site by name
|
|
228
|
+
const serverResult = await forge.servers.resolve("prod");
|
|
229
|
+
if (serverResult.total !== 1) {
|
|
230
|
+
console.error("Could not uniquely resolve server:", serverResult);
|
|
231
|
+
process.exit(1);
|
|
168
232
|
}
|
|
233
|
+
|
|
234
|
+
const serverId = serverResult.matches[0].id;
|
|
235
|
+
const siteResult = await forge.server(serverId).sites.resolve("myapp.com");
|
|
236
|
+
if (siteResult.total !== 1) {
|
|
237
|
+
console.error("Could not uniquely resolve site:", siteResult);
|
|
238
|
+
process.exit(1);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
await forge.server(serverId).site(siteResult.matches[0].id).deploy();
|
|
242
|
+
console.log("Deployment triggered!");
|
|
169
243
|
```
|
|
170
244
|
|
|
171
245
|
## Requirements
|
package/dist/index.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export type { ScheduledJobListOptions } from "./resources/scheduled-jobs.ts";
|
|
|
31
31
|
export { SecurityRulesCollection } from "./resources/security-rules.ts";
|
|
32
32
|
export type { SecurityRuleListOptions } from "./resources/security-rules.ts";
|
|
33
33
|
export { ServersCollection, ServerResource } from "./resources/servers.ts";
|
|
34
|
-
export type { ServerListOptions } from "./resources/servers.ts";
|
|
34
|
+
export type { ServerListOptions, ResolveMatch, ResolveResult } from "./resources/servers.ts";
|
|
35
35
|
export { SshKeysCollection } from "./resources/ssh-keys.ts";
|
|
36
36
|
export type { SshKeyListOptions } from "./resources/ssh-keys.ts";
|
|
37
37
|
export { SiteEnvResource, SiteNginxResource, SiteResource, SitesCollection, } from "./resources/sites.ts";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,YAAY,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,YAAY,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,YAAY,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AACxE,YAAY,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,YAAY,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AACxE,YAAY,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAC1E,YAAY,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAC/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAClF,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AACxE,YAAY,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AACxE,YAAY,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AACxE,YAAY,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC3E,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -45,6 +45,16 @@ var AsyncPaginatedIterator = class {
|
|
|
45
45
|
}
|
|
46
46
|
};
|
|
47
47
|
/**
|
|
48
|
+
* Match items by name using case-insensitive exact and partial matching.
|
|
49
|
+
*/
|
|
50
|
+
function matchByName(items, query, getName) {
|
|
51
|
+
const lower = query.toLowerCase();
|
|
52
|
+
return {
|
|
53
|
+
exact: items.filter((item) => getName(item).toLowerCase() === lower),
|
|
54
|
+
partial: items.filter((item) => getName(item).toLowerCase().includes(lower))
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
48
58
|
* Abstract base class for resource collections.
|
|
49
59
|
* Provides a shared `client` property to avoid duplication across all collection classes.
|
|
50
60
|
*/
|
|
@@ -630,6 +640,34 @@ var SitesCollection = class extends BaseCollection {
|
|
|
630
640
|
async delete(siteId) {
|
|
631
641
|
await this.client.delete(`${this.basePath}/${siteId}`);
|
|
632
642
|
}
|
|
643
|
+
/**
|
|
644
|
+
* Find sites by domain name using case-insensitive partial matching.
|
|
645
|
+
*
|
|
646
|
+
* If exactly one site matches the query exactly, only that site is returned.
|
|
647
|
+
* Otherwise all partial matches are returned.
|
|
648
|
+
*
|
|
649
|
+
* @param query - The search query to match against site domain names.
|
|
650
|
+
* @returns Resolve result with matching sites.
|
|
651
|
+
*
|
|
652
|
+
* @example
|
|
653
|
+
* ```ts
|
|
654
|
+
* // Find sites matching "example"
|
|
655
|
+
* const result = await forge.server(123).sites.resolve('example');
|
|
656
|
+
* // → { query: 'example', matches: [{ id: 456, name: 'example.com' }], total: 1 }
|
|
657
|
+
* ```
|
|
658
|
+
*/
|
|
659
|
+
async resolve(query) {
|
|
660
|
+
const { exact, partial } = matchByName(await this.list(), query, (s) => s.name);
|
|
661
|
+
const matches = exact.length === 1 ? exact : partial;
|
|
662
|
+
return {
|
|
663
|
+
query,
|
|
664
|
+
matches: matches.map((s) => ({
|
|
665
|
+
id: s.id,
|
|
666
|
+
name: s.name
|
|
667
|
+
})),
|
|
668
|
+
total: matches.length
|
|
669
|
+
};
|
|
670
|
+
}
|
|
633
671
|
};
|
|
634
672
|
/**
|
|
635
673
|
* A specific site with nested resources and actions.
|
|
@@ -1744,6 +1782,39 @@ var ServersCollection = class extends BaseCollection {
|
|
|
1744
1782
|
async reboot(serverId) {
|
|
1745
1783
|
await this.client.post(`/servers/${serverId}/reboot`);
|
|
1746
1784
|
}
|
|
1785
|
+
/**
|
|
1786
|
+
* Find servers by name using case-insensitive partial matching.
|
|
1787
|
+
*
|
|
1788
|
+
* If exactly one server matches the query exactly, only that server is returned.
|
|
1789
|
+
* Otherwise all partial matches are returned.
|
|
1790
|
+
*
|
|
1791
|
+
* @param query - The search query to match against server names.
|
|
1792
|
+
* @returns Resolve result with matching servers.
|
|
1793
|
+
*
|
|
1794
|
+
* @example
|
|
1795
|
+
* ```ts
|
|
1796
|
+
* // Find servers matching "prod"
|
|
1797
|
+
* const result = await forge.servers.resolve('prod');
|
|
1798
|
+
* // → { query: 'prod', matches: [{ id: 725393, name: 'wilo-grove-prod' }], total: 1 }
|
|
1799
|
+
*
|
|
1800
|
+
* // Use the result to access a server
|
|
1801
|
+
* if (result.total === 1) {
|
|
1802
|
+
* const sites = await forge.server(result.matches[0].id).sites.list();
|
|
1803
|
+
* }
|
|
1804
|
+
* ```
|
|
1805
|
+
*/
|
|
1806
|
+
async resolve(query) {
|
|
1807
|
+
const { exact, partial } = matchByName(await this.list(), query, (s) => s.name);
|
|
1808
|
+
const matches = exact.length === 1 ? exact : partial;
|
|
1809
|
+
return {
|
|
1810
|
+
query,
|
|
1811
|
+
matches: matches.map((s) => ({
|
|
1812
|
+
id: s.id,
|
|
1813
|
+
name: s.name
|
|
1814
|
+
})),
|
|
1815
|
+
total: matches.length
|
|
1816
|
+
};
|
|
1817
|
+
}
|
|
1747
1818
|
};
|
|
1748
1819
|
/**
|
|
1749
1820
|
* A specific server with nested resources.
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/pagination.ts","../src/resources/base.ts","../src/resources/deployments.ts","../src/resources/certificates.ts","../src/resources/commands.ts","../src/resources/security-rules.ts","../src/resources/redirect-rules.ts","../src/resources/sites.ts","../src/resources/databases.ts","../src/resources/database-users.ts","../src/resources/daemons.ts","../src/resources/backups.ts","../src/resources/scheduled-jobs.ts","../src/resources/monitors.ts","../src/resources/firewall-rules.ts","../src/resources/ssh-keys.ts","../src/resources/nginx-templates.ts","../src/resources/servers.ts","../src/resources/recipes.ts","../src/forge.ts"],"sourcesContent":["/**\n * Function that fetches a page of results.\n */\nexport type PageFetcher<T> = (page: number) => Promise<T[]>;\n\n/**\n * Async paginated iterator that auto-fetches all pages.\n *\n * @example\n * ```ts\n * const iter = forge.server(123).site(456).deployments.all();\n * for await (const deployment of iter) {\n * console.log(deployment);\n * }\n *\n * // Or collect all items at once:\n * const deployments = await iter.toArray();\n * ```\n */\nexport class AsyncPaginatedIterator<T> {\n private fetchPage: PageFetcher<T>;\n private perPage: number;\n\n constructor(fetchPage: PageFetcher<T>, perPage = 200) {\n this.fetchPage = fetchPage;\n this.perPage = perPage;\n }\n\n async *[Symbol.asyncIterator](): AsyncGenerator<T, void, undefined> {\n let page = 1;\n let hasMore = true;\n\n while (hasMore) {\n const items = await this.fetchPage(page);\n\n for (const item of items) {\n yield item;\n }\n\n // If we got fewer items than perPage, we've reached the last page\n hasMore = items.length >= this.perPage;\n\n page++;\n }\n }\n\n /**\n * Collect all items into an array.\n *\n * @example\n * ```ts\n * const deployments = await forge.server(123).site(456).deployments.all().toArray();\n * ```\n */\n async toArray(): Promise<T[]> {\n const items: T[] = [];\n for await (const item of this) {\n items.push(item);\n }\n return items;\n }\n}\n","import type { HttpClient } from \"@studiometa/forge-api\";\n\n/**\n * Abstract base class for resource collections.\n * Provides a shared `client` property to avoid duplication across all collection classes.\n */\nexport abstract class BaseCollection {\n protected readonly client: HttpClient;\n\n constructor(client: HttpClient) {\n this.client = client;\n }\n}\n","import type {\n ForgeDeployment,\n HttpClient,\n DeploymentResponse,\n DeploymentsResponse,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing deployments.\n */\nexport interface DeploymentListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of deployments for a site.\n *\n * Access via `forge.server(id).site(id).deployments`.\n *\n * @example\n * ```ts\n * const deployments = await forge.server(123).site(456).deployments.list();\n * ```\n */\nexport class DeploymentsCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/sites/${this.siteId}/deployments`;\n }\n\n /**\n * List deployments for this site.\n *\n * @example\n * ```ts\n * const deployments = await forge.server(123).site(456).deployments.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).site(456).deployments.list({ page: 2 });\n * ```\n */\n async list(options: DeploymentListOptions = {}): Promise<ForgeDeployment[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<DeploymentsResponse>(`${this.basePath}${query}`);\n return response.deployments;\n }\n\n /**\n * Iterate over all deployments across all pages.\n *\n * @example\n * ```ts\n * for await (const deployment of forge.server(123).site(456).deployments.all()) {\n * console.log(deployment);\n * }\n *\n * // Or collect all at once:\n * const deployments = await forge.server(123).site(456).deployments.all().toArray();\n * ```\n */\n all(options: Omit<DeploymentListOptions, \"page\"> = {}): AsyncPaginatedIterator<ForgeDeployment> {\n return new AsyncPaginatedIterator<ForgeDeployment>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific deployment.\n *\n * @example\n * ```ts\n * const deployment = await forge.server(123).site(456).deployments.get(789);\n * ```\n */\n async get(deploymentId: number): Promise<ForgeDeployment> {\n const response = await this.client.get<DeploymentResponse>(`${this.basePath}/${deploymentId}`);\n return response.deployment;\n }\n\n /**\n * Get the output of a deployment.\n *\n * @example\n * ```ts\n * const output = await forge.server(123).site(456).deployments.output(789);\n * ```\n */\n async output(deploymentId: number): Promise<string> {\n return this.client.get<string>(`${this.basePath}/${deploymentId}/output`);\n }\n\n /**\n * Get the deployment script.\n *\n * @example\n * ```ts\n * const script = await forge.server(123).site(456).deployments.script();\n * ```\n */\n async script(): Promise<string> {\n return this.client.get<string>(\n `/servers/${this.serverId}/sites/${this.siteId}/deployment/script`,\n );\n }\n\n /**\n * Update the deployment script.\n *\n * @example\n * ```ts\n * await forge.server(123).site(456).deployments.updateScript('npm run build && ...');\n * ```\n */\n async updateScript(content: string): Promise<void> {\n await this.client.put(`/servers/${this.serverId}/sites/${this.siteId}/deployment/script`, {\n content,\n });\n }\n}\n","import type {\n CreateCertificateData,\n ForgeCertificate,\n HttpClient,\n CertificateResponse,\n CertificatesResponse,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing certificates.\n */\nexport interface CertificateListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of SSL certificates for a site.\n *\n * Access via `forge.server(id).site(id).certificates`.\n *\n * @example\n * ```ts\n * const certs = await forge.server(123).site(456).certificates.list();\n * ```\n */\nexport class CertificatesCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/sites/${this.siteId}/certificates`;\n }\n\n /**\n * List certificates for this site.\n *\n * @example\n * ```ts\n * const certs = await forge.server(123).site(456).certificates.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).site(456).certificates.list({ page: 2 });\n * ```\n */\n async list(options: CertificateListOptions = {}): Promise<ForgeCertificate[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<CertificatesResponse>(`${this.basePath}${query}`);\n return response.certificates;\n }\n\n /**\n * Iterate over all certificates across all pages.\n *\n * @example\n * ```ts\n * for await (const cert of forge.server(123).site(456).certificates.all()) {\n * console.log(cert);\n * }\n *\n * // Or collect all at once:\n * const certs = await forge.server(123).site(456).certificates.all().toArray();\n * ```\n */\n all(\n options: Omit<CertificateListOptions, \"page\"> = {},\n ): AsyncPaginatedIterator<ForgeCertificate> {\n return new AsyncPaginatedIterator<ForgeCertificate>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific certificate.\n *\n * @example\n * ```ts\n * const cert = await forge.server(123).site(456).certificates.get(789);\n * ```\n */\n async get(certificateId: number): Promise<ForgeCertificate> {\n const response = await this.client.get<CertificateResponse>(\n `${this.basePath}/${certificateId}`,\n );\n return response.certificate;\n }\n\n /**\n * Create a new SSL certificate.\n *\n * @example\n * ```ts\n * const cert = await forge.server(123).site(456).certificates.create({\n * type: 'new',\n * domain: 'example.com',\n * });\n * ```\n */\n async create(data: CreateCertificateData): Promise<ForgeCertificate> {\n const response = await this.client.post<CertificateResponse>(this.basePath, data);\n return response.certificate;\n }\n\n /**\n * Install a Let's Encrypt certificate.\n *\n * @example\n * ```ts\n * await forge.server(123).site(456).certificates.letsEncrypt(['example.com', 'www.example.com']);\n * ```\n */\n async letsEncrypt(domains: string[]): Promise<ForgeCertificate> {\n const response = await this.client.post<CertificateResponse>(`${this.basePath}/letsencrypt`, {\n domains,\n });\n return response.certificate;\n }\n\n /**\n * Delete a certificate.\n *\n * @example\n * ```ts\n * await forge.server(123).site(456).certificates.delete(789);\n * ```\n */\n async delete(certificateId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${certificateId}`);\n }\n\n /**\n * Activate a certificate.\n *\n * @example\n * ```ts\n * await forge.server(123).site(456).certificates.activate(789);\n * ```\n */\n async activate(certificateId: number): Promise<void> {\n await this.client.post(`${this.basePath}/${certificateId}/activate`);\n }\n}\n","import type {\n CommandResponse,\n CommandsResponse,\n CreateCommandData,\n ForgeCommand,\n HttpClient,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing site commands.\n */\nexport interface CommandListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of commands run on a site.\n *\n * Access via `forge.server(id).site(id).commands`.\n *\n * @example\n * ```ts\n * const commands = await forge.server(123).site(456).commands.list();\n * ```\n */\nexport class CommandsCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/sites/${this.siteId}/commands`;\n }\n\n /**\n * List commands run on this site.\n *\n * @example\n * ```ts\n * const commands = await forge.server(123).site(456).commands.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).site(456).commands.list({ page: 2 });\n * ```\n */\n async list(options: CommandListOptions = {}): Promise<ForgeCommand[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<CommandsResponse>(`${this.basePath}${query}`);\n return response.commands;\n }\n\n /**\n * Iterate over all commands across all pages.\n *\n * @example\n * ```ts\n * for await (const command of forge.server(123).site(456).commands.all()) {\n * console.log(command);\n * }\n *\n * // Or collect all at once:\n * const commands = await forge.server(123).site(456).commands.all().toArray();\n * ```\n */\n all(options: Omit<CommandListOptions, \"page\"> = {}): AsyncPaginatedIterator<ForgeCommand> {\n return new AsyncPaginatedIterator<ForgeCommand>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific command.\n *\n * @example\n * ```ts\n * const command = await forge.server(123).site(456).commands.get(789);\n * ```\n */\n async get(commandId: number): Promise<ForgeCommand> {\n const response = await this.client.get<CommandResponse>(`${this.basePath}/${commandId}`);\n return response.command;\n }\n\n /**\n * Run a command on this site.\n *\n * @example\n * ```ts\n * const command = await forge.server(123).site(456).commands.create({\n * command: 'php artisan migrate',\n * });\n * ```\n */\n async create(data: CreateCommandData): Promise<ForgeCommand> {\n const response = await this.client.post<CommandResponse>(this.basePath, data);\n return response.command;\n }\n}\n","import type {\n CreateSecurityRuleData,\n ForgeSecurityRule,\n HttpClient,\n SecurityRuleResponse,\n SecurityRulesResponse,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing security rules.\n */\nexport interface SecurityRuleListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of security rules on a site.\n *\n * Access via `forge.server(id).site(id).securityRules`.\n *\n * @example\n * ```ts\n * const rules = await forge.server(123).site(456).securityRules.list();\n * ```\n */\nexport class SecurityRulesCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/sites/${this.siteId}/security-rules`;\n }\n\n /**\n * List security rules on this site.\n *\n * @example\n * ```ts\n * const rules = await forge.server(123).site(456).securityRules.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).site(456).securityRules.list({ page: 2 });\n * ```\n */\n async list(options: SecurityRuleListOptions = {}): Promise<ForgeSecurityRule[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<SecurityRulesResponse>(`${this.basePath}${query}`);\n return response.security_rules;\n }\n\n /**\n * Iterate over all security rules across all pages.\n *\n * @example\n * ```ts\n * for await (const rule of forge.server(123).site(456).securityRules.all()) {\n * console.log(rule);\n * }\n *\n * // Or collect all at once:\n * const rules = await forge.server(123).site(456).securityRules.all().toArray();\n * ```\n */\n all(\n options: Omit<SecurityRuleListOptions, \"page\"> = {},\n ): AsyncPaginatedIterator<ForgeSecurityRule> {\n return new AsyncPaginatedIterator<ForgeSecurityRule>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific security rule.\n *\n * @example\n * ```ts\n * const rule = await forge.server(123).site(456).securityRules.get(789);\n * ```\n */\n async get(ruleId: number): Promise<ForgeSecurityRule> {\n const response = await this.client.get<SecurityRuleResponse>(`${this.basePath}/${ruleId}`);\n return response.security_rule;\n }\n\n /**\n * Create a new security rule.\n *\n * @example\n * ```ts\n * const rule = await forge.server(123).site(456).securityRules.create({\n * name: 'Admin Area',\n * path: '/admin',\n * credentials: [{ username: 'admin', password: 'secret' }],\n * });\n * ```\n */\n async create(data: CreateSecurityRuleData): Promise<ForgeSecurityRule> {\n const response = await this.client.post<SecurityRuleResponse>(this.basePath, data);\n return response.security_rule;\n }\n\n /**\n * Delete a security rule.\n *\n * @example\n * ```ts\n * await forge.server(123).site(456).securityRules.delete(789);\n * ```\n */\n async delete(ruleId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${ruleId}`);\n }\n}\n","import type {\n CreateRedirectRuleData,\n ForgeRedirectRule,\n HttpClient,\n RedirectRuleResponse,\n RedirectRulesResponse,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing redirect rules.\n */\nexport interface RedirectRuleListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of redirect rules on a site.\n *\n * Access via `forge.server(id).site(id).redirectRules`.\n *\n * @example\n * ```ts\n * const rules = await forge.server(123).site(456).redirectRules.list();\n * ```\n */\nexport class RedirectRulesCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/sites/${this.siteId}/redirect-rules`;\n }\n\n /**\n * List redirect rules on this site.\n *\n * @example\n * ```ts\n * const rules = await forge.server(123).site(456).redirectRules.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).site(456).redirectRules.list({ page: 2 });\n * ```\n */\n async list(options: RedirectRuleListOptions = {}): Promise<ForgeRedirectRule[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<RedirectRulesResponse>(`${this.basePath}${query}`);\n return response.redirect_rules;\n }\n\n /**\n * Iterate over all redirect rules across all pages.\n *\n * @example\n * ```ts\n * for await (const rule of forge.server(123).site(456).redirectRules.all()) {\n * console.log(rule);\n * }\n *\n * // Or collect all at once:\n * const rules = await forge.server(123).site(456).redirectRules.all().toArray();\n * ```\n */\n all(\n options: Omit<RedirectRuleListOptions, \"page\"> = {},\n ): AsyncPaginatedIterator<ForgeRedirectRule> {\n return new AsyncPaginatedIterator<ForgeRedirectRule>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific redirect rule.\n *\n * @example\n * ```ts\n * const rule = await forge.server(123).site(456).redirectRules.get(789);\n * ```\n */\n async get(ruleId: number): Promise<ForgeRedirectRule> {\n const response = await this.client.get<RedirectRuleResponse>(`${this.basePath}/${ruleId}`);\n return response.redirect_rule;\n }\n\n /**\n * Create a new redirect rule.\n *\n * @example\n * ```ts\n * const rule = await forge.server(123).site(456).redirectRules.create({\n * from: '/old-path',\n * to: '/new-path',\n * type: 'redirect',\n * });\n * ```\n */\n async create(data: CreateRedirectRuleData): Promise<ForgeRedirectRule> {\n const response = await this.client.post<RedirectRuleResponse>(this.basePath, data);\n return response.redirect_rule;\n }\n\n /**\n * Delete a redirect rule.\n *\n * @example\n * ```ts\n * await forge.server(123).site(456).redirectRules.delete(789);\n * ```\n */\n async delete(ruleId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${ruleId}`);\n }\n}\n","import type {\n CreateSiteData,\n ForgeSite,\n HttpClient,\n SiteResponse,\n SitesResponse,\n} from \"@studiometa/forge-api\";\n\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\nimport { DeploymentsCollection } from \"./deployments.ts\";\nimport { CertificatesCollection } from \"./certificates.ts\";\nimport { CommandsCollection } from \"./commands.ts\";\nimport { SecurityRulesCollection } from \"./security-rules.ts\";\nimport { RedirectRulesCollection } from \"./redirect-rules.ts\";\nimport { BaseCollection } from \"./base.ts\";\n\n/**\n * Options for listing sites.\n */\nexport interface SiteListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of sites on a server.\n *\n * Access via `forge.server(id).sites`.\n *\n * @example\n * ```ts\n * const sites = await forge.server(123).sites.list();\n * ```\n */\nexport class SitesCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/sites`;\n }\n\n /**\n * List sites on this server.\n *\n * @example\n * ```ts\n * const sites = await forge.server(123).sites.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).sites.list({ page: 2 });\n * ```\n */\n async list(options: SiteListOptions = {}): Promise<ForgeSite[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<SitesResponse>(`${this.basePath}${query}`);\n return response.sites;\n }\n\n /**\n * Iterate over all sites across all pages.\n *\n * @example\n * ```ts\n * for await (const site of forge.server(123).sites.all()) {\n * console.log(site);\n * }\n *\n * // Or collect all at once:\n * const sites = await forge.server(123).sites.all().toArray();\n * ```\n */\n all(options: Omit<SiteListOptions, \"page\"> = {}): AsyncPaginatedIterator<ForgeSite> {\n return new AsyncPaginatedIterator<ForgeSite>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific site by ID.\n *\n * @example\n * ```ts\n * const site = await forge.server(123).sites.get(456);\n * ```\n */\n async get(siteId: number): Promise<ForgeSite> {\n const response = await this.client.get<SiteResponse>(`${this.basePath}/${siteId}`);\n return response.site;\n }\n\n /**\n * Create a new site on this server.\n *\n * @example\n * ```ts\n * const site = await forge.server(123).sites.create({\n * domain: 'example.com',\n * project_type: 'php',\n * directory: '/public',\n * });\n * ```\n */\n async create(data: CreateSiteData): Promise<ForgeSite> {\n const response = await this.client.post<SiteResponse>(this.basePath, data);\n return response.site;\n }\n\n /**\n * Update a site.\n *\n * @example\n * ```ts\n * await forge.server(123).sites.update(456, { directory: '/public' });\n * ```\n */\n async update(siteId: number, data: Partial<CreateSiteData>): Promise<ForgeSite> {\n const response = await this.client.put<SiteResponse>(`${this.basePath}/${siteId}`, data);\n return response.site;\n }\n\n /**\n * Delete a site.\n *\n * @example\n * ```ts\n * await forge.server(123).sites.delete(456);\n * ```\n */\n async delete(siteId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${siteId}`);\n }\n}\n\n/**\n * A specific site with nested resources and actions.\n *\n * Access via `forge.server(id).site(id)`.\n *\n * @example\n * ```ts\n * // Deploy\n * await forge.server(123).site(456).deploy();\n *\n * // Get environment\n * const env = await forge.server(123).site(456).env.get();\n * ```\n */\nexport class SiteResource extends BaseCollection {\n /** Deployments for this site. */\n readonly deployments: DeploymentsCollection;\n\n /** SSL certificates for this site. */\n readonly certificates: CertificatesCollection;\n\n /** Environment variables for this site. */\n readonly env: SiteEnvResource;\n\n /** Nginx configuration for this site. */\n readonly nginx: SiteNginxResource;\n\n /** Commands run on this site. */\n readonly commands: CommandsCollection;\n\n /** Security rules for this site. */\n readonly securityRules: SecurityRulesCollection;\n\n /** Redirect rules for this site. */\n readonly redirectRules: RedirectRulesCollection;\n\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client);\n this.deployments = new DeploymentsCollection(client, serverId, siteId);\n this.certificates = new CertificatesCollection(client, serverId, siteId);\n this.env = new SiteEnvResource(client, serverId, siteId);\n this.nginx = new SiteNginxResource(client, serverId, siteId);\n this.commands = new CommandsCollection(client, serverId, siteId);\n this.securityRules = new SecurityRulesCollection(client, serverId, siteId);\n this.redirectRules = new RedirectRulesCollection(client, serverId, siteId);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/sites/${this.siteId}`;\n }\n\n /**\n * Get this site's details.\n *\n * @example\n * ```ts\n * const site = await forge.server(123).site(456).get();\n * ```\n */\n async get(): Promise<ForgeSite> {\n const response = await this.client.get<SiteResponse>(this.basePath);\n return response.site;\n }\n\n /**\n * Deploy this site.\n *\n * @example\n * ```ts\n * await forge.server(123).site(456).deploy();\n * ```\n */\n async deploy(): Promise<void> {\n await this.client.post(`${this.basePath}/deployment/deploy`);\n }\n\n /**\n * Delete this site.\n *\n * @example\n * ```ts\n * await forge.server(123).site(456).delete();\n * ```\n */\n async delete(): Promise<void> {\n await this.client.delete(this.basePath);\n }\n}\n\n/**\n * Environment variables for a site.\n *\n * @example\n * ```ts\n * const env = await forge.server(123).site(456).env.get();\n * await forge.server(123).site(456).env.update('APP_ENV=production\\n...');\n * ```\n */\nexport class SiteEnvResource extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/sites/${this.siteId}/env`;\n }\n\n /**\n * Get the environment file content.\n *\n * @returns The .env file content as a string.\n */\n async get(): Promise<string> {\n return this.client.get<string>(this.basePath);\n }\n\n /**\n * Update the environment file content.\n *\n * @param content The full .env file content.\n */\n async update(content: string): Promise<void> {\n await this.client.put(this.basePath, { content });\n }\n}\n\n/**\n * Nginx configuration for a site.\n *\n * @example\n * ```ts\n * const config = await forge.server(123).site(456).nginx.get();\n * await forge.server(123).site(456).nginx.update('server { ... }');\n * ```\n */\nexport class SiteNginxResource extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/sites/${this.siteId}/nginx`;\n }\n\n /**\n * Get the Nginx configuration.\n *\n * @returns The Nginx config content as a string.\n */\n async get(): Promise<string> {\n return this.client.get<string>(this.basePath);\n }\n\n /**\n * Update the Nginx configuration.\n *\n * @param content The full Nginx config content.\n */\n async update(content: string): Promise<void> {\n await this.client.put(this.basePath, { content });\n }\n}\n","import type {\n CreateDatabaseData,\n ForgeDatabase,\n HttpClient,\n DatabaseResponse,\n DatabasesResponse,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing databases.\n */\nexport interface DatabaseListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of databases on a server.\n *\n * Access via `forge.server(id).databases`.\n *\n * @example\n * ```ts\n * const dbs = await forge.server(123).databases.list();\n * ```\n */\nexport class DatabasesCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/databases`;\n }\n\n /**\n * List databases on this server.\n *\n * @example\n * ```ts\n * const dbs = await forge.server(123).databases.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).databases.list({ page: 2 });\n * ```\n */\n async list(options: DatabaseListOptions = {}): Promise<ForgeDatabase[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<DatabasesResponse>(`${this.basePath}${query}`);\n return response.databases;\n }\n\n /**\n * Iterate over all databases across all pages.\n *\n * @example\n * ```ts\n * for await (const db of forge.server(123).databases.all()) {\n * console.log(db);\n * }\n *\n * // Or collect all at once:\n * const dbs = await forge.server(123).databases.all().toArray();\n * ```\n */\n all(options: Omit<DatabaseListOptions, \"page\"> = {}): AsyncPaginatedIterator<ForgeDatabase> {\n return new AsyncPaginatedIterator<ForgeDatabase>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific database.\n *\n * @example\n * ```ts\n * const db = await forge.server(123).databases.get(789);\n * ```\n */\n async get(databaseId: number): Promise<ForgeDatabase> {\n const response = await this.client.get<DatabaseResponse>(`${this.basePath}/${databaseId}`);\n return response.database;\n }\n\n /**\n * Create a new database.\n *\n * @example\n * ```ts\n * const db = await forge.server(123).databases.create({\n * name: 'myapp',\n * user: 'admin',\n * password: 'secret',\n * });\n * ```\n */\n async create(data: CreateDatabaseData): Promise<ForgeDatabase> {\n const response = await this.client.post<DatabaseResponse>(this.basePath, data);\n return response.database;\n }\n\n /**\n * Delete a database.\n *\n * @example\n * ```ts\n * await forge.server(123).databases.delete(789);\n * ```\n */\n async delete(databaseId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${databaseId}`);\n }\n}\n","import type {\n CreateDatabaseUserData,\n DatabaseUserResponse,\n DatabaseUsersResponse,\n ForgeDatabaseUser,\n HttpClient,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing database users.\n */\nexport interface DatabaseUserListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of database users on a server.\n *\n * Access via `forge.server(id).databaseUsers`.\n *\n * @example\n * ```ts\n * const users = await forge.server(123).databaseUsers.list();\n * ```\n */\nexport class DatabaseUsersCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/database-users`;\n }\n\n /**\n * List database users on this server.\n *\n * @example\n * ```ts\n * const users = await forge.server(123).databaseUsers.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).databaseUsers.list({ page: 2 });\n * ```\n */\n async list(options: DatabaseUserListOptions = {}): Promise<ForgeDatabaseUser[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<DatabaseUsersResponse>(`${this.basePath}${query}`);\n return response.users;\n }\n\n /**\n * Iterate over all database users across all pages.\n *\n * @example\n * ```ts\n * for await (const user of forge.server(123).databaseUsers.all()) {\n * console.log(user);\n * }\n *\n * // Or collect all at once:\n * const users = await forge.server(123).databaseUsers.all().toArray();\n * ```\n */\n all(\n options: Omit<DatabaseUserListOptions, \"page\"> = {},\n ): AsyncPaginatedIterator<ForgeDatabaseUser> {\n return new AsyncPaginatedIterator<ForgeDatabaseUser>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific database user.\n *\n * @example\n * ```ts\n * const user = await forge.server(123).databaseUsers.get(789);\n * ```\n */\n async get(userId: number): Promise<ForgeDatabaseUser> {\n const response = await this.client.get<DatabaseUserResponse>(`${this.basePath}/${userId}`);\n return response.user;\n }\n\n /**\n * Create a new database user.\n *\n * @example\n * ```ts\n * const user = await forge.server(123).databaseUsers.create({\n * name: 'forge',\n * password: 'secret',\n * databases: [1, 2],\n * });\n * ```\n */\n async create(data: CreateDatabaseUserData): Promise<ForgeDatabaseUser> {\n const response = await this.client.post<DatabaseUserResponse>(this.basePath, data);\n return response.user;\n }\n\n /**\n * Delete a database user.\n *\n * @example\n * ```ts\n * await forge.server(123).databaseUsers.delete(789);\n * ```\n */\n async delete(userId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${userId}`);\n }\n}\n","import type {\n CreateDaemonData,\n ForgeDaemon,\n HttpClient,\n DaemonResponse,\n DaemonsResponse,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing daemons.\n */\nexport interface DaemonListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of daemons (background processes) on a server.\n *\n * Access via `forge.server(id).daemons`.\n *\n * @example\n * ```ts\n * const daemons = await forge.server(123).daemons.list();\n * ```\n */\nexport class DaemonsCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/daemons`;\n }\n\n /**\n * List daemons on this server.\n *\n * @example\n * ```ts\n * const daemons = await forge.server(123).daemons.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).daemons.list({ page: 2 });\n * ```\n */\n async list(options: DaemonListOptions = {}): Promise<ForgeDaemon[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<DaemonsResponse>(`${this.basePath}${query}`);\n return response.daemons;\n }\n\n /**\n * Iterate over all daemons across all pages.\n *\n * @example\n * ```ts\n * for await (const daemon of forge.server(123).daemons.all()) {\n * console.log(daemon);\n * }\n *\n * // Or collect all at once:\n * const daemons = await forge.server(123).daemons.all().toArray();\n * ```\n */\n all(options: Omit<DaemonListOptions, \"page\"> = {}): AsyncPaginatedIterator<ForgeDaemon> {\n return new AsyncPaginatedIterator<ForgeDaemon>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific daemon.\n *\n * @example\n * ```ts\n * const daemon = await forge.server(123).daemons.get(789);\n * ```\n */\n async get(daemonId: number): Promise<ForgeDaemon> {\n const response = await this.client.get<DaemonResponse>(`${this.basePath}/${daemonId}`);\n return response.daemon;\n }\n\n /**\n * Create a new daemon.\n *\n * @example\n * ```ts\n * const daemon = await forge.server(123).daemons.create({\n * command: 'php artisan queue:work',\n * user: 'forge',\n * });\n * ```\n */\n async create(data: CreateDaemonData): Promise<ForgeDaemon> {\n const response = await this.client.post<DaemonResponse>(this.basePath, data);\n return response.daemon;\n }\n\n /**\n * Delete a daemon.\n *\n * @example\n * ```ts\n * await forge.server(123).daemons.delete(789);\n * ```\n */\n async delete(daemonId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${daemonId}`);\n }\n\n /**\n * Restart a daemon.\n *\n * @example\n * ```ts\n * await forge.server(123).daemons.restart(789);\n * ```\n */\n async restart(daemonId: number): Promise<void> {\n await this.client.post(`${this.basePath}/${daemonId}/restart`);\n }\n}\n","import type {\n BackupConfigResponse,\n BackupConfigsResponse,\n CreateBackupConfigData,\n ForgeBackupConfig,\n HttpClient,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing backup configurations.\n */\nexport interface BackupConfigListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of backup configurations on a server.\n *\n * Access via `forge.server(id).backups`.\n *\n * @example\n * ```ts\n * const backups = await forge.server(123).backups.list();\n * ```\n */\nexport class BackupsCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/backup-configs`;\n }\n\n /**\n * List backup configurations on this server.\n *\n * @example\n * ```ts\n * const backups = await forge.server(123).backups.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).backups.list({ page: 2 });\n * ```\n */\n async list(options: BackupConfigListOptions = {}): Promise<ForgeBackupConfig[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<BackupConfigsResponse>(`${this.basePath}${query}`);\n return response.backups;\n }\n\n /**\n * Iterate over all backup configurations across all pages.\n *\n * @example\n * ```ts\n * for await (const backup of forge.server(123).backups.all()) {\n * console.log(backup);\n * }\n *\n * // Or collect all at once:\n * const backups = await forge.server(123).backups.all().toArray();\n * ```\n */\n all(\n options: Omit<BackupConfigListOptions, \"page\"> = {},\n ): AsyncPaginatedIterator<ForgeBackupConfig> {\n return new AsyncPaginatedIterator<ForgeBackupConfig>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific backup configuration.\n *\n * @example\n * ```ts\n * const backup = await forge.server(123).backups.get(789);\n * ```\n */\n async get(backupId: number): Promise<ForgeBackupConfig> {\n const response = await this.client.get<BackupConfigResponse>(`${this.basePath}/${backupId}`);\n return response.backup;\n }\n\n /**\n * Create a new backup configuration.\n *\n * @example\n * ```ts\n * const backup = await forge.server(123).backups.create({\n * provider: 's3',\n * credentials: { key: 'ACCESS_KEY', secret: 'SECRET_KEY', region: 'us-east-1', bucket: 'my-bucket' },\n * frequency: 'weekly',\n * retention: 7,\n * databases: [1, 2],\n * });\n * ```\n */\n async create(data: CreateBackupConfigData): Promise<ForgeBackupConfig> {\n const response = await this.client.post<BackupConfigResponse>(this.basePath, data);\n return response.backup;\n }\n\n /**\n * Delete a backup configuration.\n *\n * @example\n * ```ts\n * await forge.server(123).backups.delete(789);\n * ```\n */\n async delete(backupId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${backupId}`);\n }\n}\n","import type {\n CreateScheduledJobData,\n ForgeScheduledJob,\n HttpClient,\n ScheduledJobResponse,\n ScheduledJobsResponse,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing scheduled jobs.\n */\nexport interface ScheduledJobListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of scheduled jobs (cron jobs) on a server.\n *\n * Access via `forge.server(id).scheduledJobs`.\n *\n * @example\n * ```ts\n * const jobs = await forge.server(123).scheduledJobs.list();\n * ```\n */\nexport class ScheduledJobsCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/jobs`;\n }\n\n /**\n * List scheduled jobs on this server.\n *\n * @example\n * ```ts\n * const jobs = await forge.server(123).scheduledJobs.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).scheduledJobs.list({ page: 2 });\n * ```\n */\n async list(options: ScheduledJobListOptions = {}): Promise<ForgeScheduledJob[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<ScheduledJobsResponse>(`${this.basePath}${query}`);\n return response.jobs;\n }\n\n /**\n * Iterate over all scheduled jobs across all pages.\n *\n * @example\n * ```ts\n * for await (const job of forge.server(123).scheduledJobs.all()) {\n * console.log(job);\n * }\n *\n * // Or collect all at once:\n * const jobs = await forge.server(123).scheduledJobs.all().toArray();\n * ```\n */\n all(\n options: Omit<ScheduledJobListOptions, \"page\"> = {},\n ): AsyncPaginatedIterator<ForgeScheduledJob> {\n return new AsyncPaginatedIterator<ForgeScheduledJob>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific scheduled job.\n *\n * @example\n * ```ts\n * const job = await forge.server(123).scheduledJobs.get(789);\n * ```\n */\n async get(jobId: number): Promise<ForgeScheduledJob> {\n const response = await this.client.get<ScheduledJobResponse>(`${this.basePath}/${jobId}`);\n return response.job;\n }\n\n /**\n * Create a new scheduled job.\n *\n * @example\n * ```ts\n * const job = await forge.server(123).scheduledJobs.create({\n * command: 'php /home/forge/artisan schedule:run',\n * user: 'forge',\n * frequency: 'minutely',\n * });\n * ```\n */\n async create(data: CreateScheduledJobData): Promise<ForgeScheduledJob> {\n const response = await this.client.post<ScheduledJobResponse>(this.basePath, data);\n return response.job;\n }\n\n /**\n * Delete a scheduled job.\n *\n * @example\n * ```ts\n * await forge.server(123).scheduledJobs.delete(789);\n * ```\n */\n async delete(jobId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${jobId}`);\n }\n}\n","import type {\n CreateMonitorData,\n ForgeMonitor,\n HttpClient,\n MonitorResponse,\n MonitorsResponse,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing monitors.\n */\nexport interface MonitorListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of server monitors.\n *\n * Access via `forge.server(id).monitors`.\n *\n * @example\n * ```ts\n * const monitors = await forge.server(123).monitors.list();\n * ```\n */\nexport class MonitorsCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/monitors`;\n }\n\n /**\n * List monitors on this server.\n *\n * @example\n * ```ts\n * const monitors = await forge.server(123).monitors.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).monitors.list({ page: 2 });\n * ```\n */\n async list(options: MonitorListOptions = {}): Promise<ForgeMonitor[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<MonitorsResponse>(`${this.basePath}${query}`);\n return response.monitors;\n }\n\n /**\n * Iterate over all monitors across all pages.\n *\n * @example\n * ```ts\n * for await (const monitor of forge.server(123).monitors.all()) {\n * console.log(monitor);\n * }\n *\n * // Or collect all at once:\n * const monitors = await forge.server(123).monitors.all().toArray();\n * ```\n */\n all(options: Omit<MonitorListOptions, \"page\"> = {}): AsyncPaginatedIterator<ForgeMonitor> {\n return new AsyncPaginatedIterator<ForgeMonitor>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific monitor.\n *\n * @example\n * ```ts\n * const monitor = await forge.server(123).monitors.get(789);\n * ```\n */\n async get(monitorId: number): Promise<ForgeMonitor> {\n const response = await this.client.get<MonitorResponse>(`${this.basePath}/${monitorId}`);\n return response.monitor;\n }\n\n /**\n * Create a new monitor.\n *\n * @example\n * ```ts\n * const monitor = await forge.server(123).monitors.create({\n * type: 'cpu_load',\n * operator: 'gte',\n * threshold: 80,\n * minutes: 5,\n * });\n * ```\n */\n async create(data: CreateMonitorData): Promise<ForgeMonitor> {\n const response = await this.client.post<MonitorResponse>(this.basePath, data);\n return response.monitor;\n }\n\n /**\n * Delete a monitor.\n *\n * @example\n * ```ts\n * await forge.server(123).monitors.delete(789);\n * ```\n */\n async delete(monitorId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${monitorId}`);\n }\n}\n","import type {\n CreateFirewallRuleData,\n FirewallRuleResponse,\n FirewallRulesResponse,\n ForgeFirewallRule,\n HttpClient,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing firewall rules.\n */\nexport interface FirewallRuleListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of firewall rules on a server.\n *\n * Access via `forge.server(id).firewallRules`.\n *\n * @example\n * ```ts\n * const rules = await forge.server(123).firewallRules.list();\n * ```\n */\nexport class FirewallRulesCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/firewall-rules`;\n }\n\n /**\n * List firewall rules on this server.\n *\n * @example\n * ```ts\n * const rules = await forge.server(123).firewallRules.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).firewallRules.list({ page: 2 });\n * ```\n */\n async list(options: FirewallRuleListOptions = {}): Promise<ForgeFirewallRule[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<FirewallRulesResponse>(`${this.basePath}${query}`);\n return response.rules;\n }\n\n /**\n * Iterate over all firewall rules across all pages.\n *\n * @example\n * ```ts\n * for await (const rule of forge.server(123).firewallRules.all()) {\n * console.log(rule);\n * }\n *\n * // Or collect all at once:\n * const rules = await forge.server(123).firewallRules.all().toArray();\n * ```\n */\n all(\n options: Omit<FirewallRuleListOptions, \"page\"> = {},\n ): AsyncPaginatedIterator<ForgeFirewallRule> {\n return new AsyncPaginatedIterator<ForgeFirewallRule>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific firewall rule.\n *\n * @example\n * ```ts\n * const rule = await forge.server(123).firewallRules.get(789);\n * ```\n */\n async get(ruleId: number): Promise<ForgeFirewallRule> {\n const response = await this.client.get<FirewallRuleResponse>(`${this.basePath}/${ruleId}`);\n return response.rule;\n }\n\n /**\n * Create a new firewall rule.\n *\n * @example\n * ```ts\n * const rule = await forge.server(123).firewallRules.create({\n * name: 'Allow HTTP',\n * port: 80,\n * type: 'allow',\n * });\n * ```\n */\n async create(data: CreateFirewallRuleData): Promise<ForgeFirewallRule> {\n const response = await this.client.post<FirewallRuleResponse>(this.basePath, data);\n return response.rule;\n }\n\n /**\n * Delete a firewall rule.\n *\n * @example\n * ```ts\n * await forge.server(123).firewallRules.delete(789);\n * ```\n */\n async delete(ruleId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${ruleId}`);\n }\n}\n","import type {\n CreateSshKeyData,\n ForgeSshKey,\n HttpClient,\n SshKeyResponse,\n SshKeysResponse,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing SSH keys.\n */\nexport interface SshKeyListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of SSH keys on a server.\n *\n * Access via `forge.server(id).sshKeys`.\n *\n * @example\n * ```ts\n * const keys = await forge.server(123).sshKeys.list();\n * ```\n */\nexport class SshKeysCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/keys`;\n }\n\n /**\n * List SSH keys on this server.\n *\n * @example\n * ```ts\n * const keys = await forge.server(123).sshKeys.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).sshKeys.list({ page: 2 });\n * ```\n */\n async list(options: SshKeyListOptions = {}): Promise<ForgeSshKey[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<SshKeysResponse>(`${this.basePath}${query}`);\n return response.keys;\n }\n\n /**\n * Iterate over all SSH keys across all pages.\n *\n * @example\n * ```ts\n * for await (const key of forge.server(123).sshKeys.all()) {\n * console.log(key);\n * }\n *\n * // Or collect all at once:\n * const keys = await forge.server(123).sshKeys.all().toArray();\n * ```\n */\n all(options: Omit<SshKeyListOptions, \"page\"> = {}): AsyncPaginatedIterator<ForgeSshKey> {\n return new AsyncPaginatedIterator<ForgeSshKey>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific SSH key.\n *\n * @example\n * ```ts\n * const key = await forge.server(123).sshKeys.get(789);\n * ```\n */\n async get(keyId: number): Promise<ForgeSshKey> {\n const response = await this.client.get<SshKeyResponse>(`${this.basePath}/${keyId}`);\n return response.key;\n }\n\n /**\n * Create a new SSH key.\n *\n * @example\n * ```ts\n * const key = await forge.server(123).sshKeys.create({\n * name: 'deploy-key',\n * key: 'ssh-rsa AAAA...',\n * });\n * ```\n */\n async create(data: CreateSshKeyData): Promise<ForgeSshKey> {\n const response = await this.client.post<SshKeyResponse>(this.basePath, data);\n return response.key;\n }\n\n /**\n * Delete an SSH key.\n *\n * @example\n * ```ts\n * await forge.server(123).sshKeys.delete(789);\n * ```\n */\n async delete(keyId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${keyId}`);\n }\n}\n","import type {\n CreateNginxTemplateData,\n ForgeNginxTemplate,\n HttpClient,\n NginxTemplateResponse,\n NginxTemplatesResponse,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing Nginx templates.\n */\nexport interface NginxTemplateListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of Nginx templates on a server.\n *\n * Access via `forge.server(id).nginxTemplates`.\n *\n * @example\n * ```ts\n * const templates = await forge.server(123).nginxTemplates.list();\n * ```\n */\nexport class NginxTemplatesCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/nginx/templates`;\n }\n\n /**\n * List Nginx templates on this server.\n *\n * @example\n * ```ts\n * const templates = await forge.server(123).nginxTemplates.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).nginxTemplates.list({ page: 2 });\n * ```\n */\n async list(options: NginxTemplateListOptions = {}): Promise<ForgeNginxTemplate[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<NginxTemplatesResponse>(`${this.basePath}${query}`);\n return response.templates;\n }\n\n /**\n * Iterate over all Nginx templates across all pages.\n *\n * @example\n * ```ts\n * for await (const template of forge.server(123).nginxTemplates.all()) {\n * console.log(template);\n * }\n *\n * // Or collect all at once:\n * const templates = await forge.server(123).nginxTemplates.all().toArray();\n * ```\n */\n all(\n options: Omit<NginxTemplateListOptions, \"page\"> = {},\n ): AsyncPaginatedIterator<ForgeNginxTemplate> {\n return new AsyncPaginatedIterator<ForgeNginxTemplate>((page) =>\n this.list({ ...options, page }),\n );\n }\n\n /**\n * Get a specific Nginx template.\n *\n * @example\n * ```ts\n * const template = await forge.server(123).nginxTemplates.get(789);\n * ```\n */\n async get(templateId: number): Promise<ForgeNginxTemplate> {\n const response = await this.client.get<NginxTemplateResponse>(`${this.basePath}/${templateId}`);\n return response.template;\n }\n\n /**\n * Create a new Nginx template.\n *\n * @example\n * ```ts\n * const template = await forge.server(123).nginxTemplates.create({\n * name: 'Laravel Template',\n * content: 'server { ... }',\n * });\n * ```\n */\n async create(data: CreateNginxTemplateData): Promise<ForgeNginxTemplate> {\n const response = await this.client.post<NginxTemplateResponse>(this.basePath, data);\n return response.template;\n }\n\n /**\n * Update an existing Nginx template.\n *\n * @example\n * ```ts\n * const template = await forge.server(123).nginxTemplates.update(789, {\n * name: 'Updated Template',\n * content: 'server { ... }',\n * });\n * ```\n */\n async update(\n templateId: number,\n data: Partial<CreateNginxTemplateData>,\n ): Promise<ForgeNginxTemplate> {\n const response = await this.client.put<NginxTemplateResponse>(\n `${this.basePath}/${templateId}`,\n data,\n );\n return response.template;\n }\n\n /**\n * Delete a Nginx template.\n *\n * @example\n * ```ts\n * await forge.server(123).nginxTemplates.delete(789);\n * ```\n */\n async delete(templateId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${templateId}`);\n }\n}\n","import type {\n CreateServerData,\n ForgeServer,\n HttpClient,\n ServerResponse,\n ServersResponse,\n} from \"@studiometa/forge-api\";\n\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\nimport { SitesCollection, SiteResource } from \"./sites.ts\";\nimport { DatabasesCollection } from \"./databases.ts\";\nimport { DatabaseUsersCollection } from \"./database-users.ts\";\nimport { DaemonsCollection } from \"./daemons.ts\";\nimport { BackupsCollection } from \"./backups.ts\";\nimport { ScheduledJobsCollection } from \"./scheduled-jobs.ts\";\nimport { MonitorsCollection } from \"./monitors.ts\";\nimport { FirewallRulesCollection } from \"./firewall-rules.ts\";\nimport { SshKeysCollection } from \"./ssh-keys.ts\";\nimport { NginxTemplatesCollection } from \"./nginx-templates.ts\";\nimport { BaseCollection } from \"./base.ts\";\n\n/**\n * Options for listing servers.\n */\nexport interface ServerListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of servers.\n *\n * Access via `forge.servers`.\n *\n * @example\n * ```ts\n * // List all servers\n * const servers = await forge.servers.list();\n *\n * // Get a specific server\n * const server = await forge.servers.get(123);\n *\n * // Create a new server\n * const server = await forge.servers.create({ ... });\n * ```\n */\nexport class ServersCollection extends BaseCollection {\n /** @internal */\n constructor(client: HttpClient) {\n super(client);\n }\n\n /**\n * List servers.\n *\n * @example\n * ```ts\n * const servers = await forge.servers.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.servers.list({ page: 2 });\n * ```\n */\n async list(options: ServerListOptions = {}): Promise<ForgeServer[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<ServersResponse>(`/servers${query}`);\n return response.servers;\n }\n\n /**\n * Iterate over all servers across all pages.\n *\n * @example\n * ```ts\n * for await (const server of forge.servers.all()) {\n * console.log(server);\n * }\n *\n * // Or collect all at once:\n * const servers = await forge.servers.all().toArray();\n * ```\n */\n all(options: Omit<ServerListOptions, \"page\"> = {}): AsyncPaginatedIterator<ForgeServer> {\n return new AsyncPaginatedIterator<ForgeServer>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific server by ID.\n *\n * @example\n * ```ts\n * const server = await forge.servers.get(123);\n * ```\n */\n async get(serverId: number): Promise<ForgeServer> {\n const response = await this.client.get<ServerResponse>(`/servers/${serverId}`);\n return response.server;\n }\n\n /**\n * Create a new server.\n *\n * @example\n * ```ts\n * const server = await forge.servers.create({\n * provider: 'ocean2',\n * credential_id: 1,\n * name: 'web-1',\n * type: 'app',\n * size: '01',\n * region: 'ams3',\n * });\n * ```\n */\n async create(data: CreateServerData): Promise<ForgeServer> {\n const response = await this.client.post<ServerResponse>(\"/servers\", data);\n return response.server;\n }\n\n /**\n * Update a server.\n *\n * @example\n * ```ts\n * await forge.servers.update(123, { name: 'web-1-renamed' });\n * ```\n */\n async update(serverId: number, data: Partial<CreateServerData>): Promise<ForgeServer> {\n const response = await this.client.put<ServerResponse>(`/servers/${serverId}`, data);\n return response.server;\n }\n\n /**\n * Delete a server.\n *\n * @example\n * ```ts\n * await forge.servers.delete(123);\n * ```\n */\n async delete(serverId: number): Promise<void> {\n await this.client.delete(`/servers/${serverId}`);\n }\n\n /**\n * Reboot a server.\n *\n * @example\n * ```ts\n * await forge.servers.reboot(123);\n * ```\n */\n async reboot(serverId: number): Promise<void> {\n await this.client.post(`/servers/${serverId}/reboot`);\n }\n}\n\n/**\n * A specific server with nested resources.\n *\n * Access via `forge.server(id)`.\n *\n * @example\n * ```ts\n * // Access sites on a server\n * const sites = await forge.server(123).sites.list();\n *\n * // Access databases on a server\n * const dbs = await forge.server(123).databases.list();\n * ```\n */\nexport class ServerResource extends BaseCollection {\n /** Sites on this server. */\n readonly sites: SitesCollection;\n\n /** Databases on this server. */\n readonly databases: DatabasesCollection;\n\n /** Database users on this server. */\n readonly databaseUsers: DatabaseUsersCollection;\n\n /** Daemons (background processes) on this server. */\n readonly daemons: DaemonsCollection;\n\n /** Backup configurations on this server. */\n readonly backups: BackupsCollection;\n\n /** Scheduled jobs (cron jobs) on this server. */\n readonly scheduledJobs: ScheduledJobsCollection;\n\n /** Monitors on this server. */\n readonly monitors: MonitorsCollection;\n\n /** Firewall rules on this server. */\n readonly firewallRules: FirewallRulesCollection;\n\n /** SSH keys on this server. */\n readonly sshKeys: SshKeysCollection;\n\n /** Nginx templates on this server. */\n readonly nginxTemplates: NginxTemplatesCollection;\n\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n ) {\n super(client);\n this.sites = new SitesCollection(client, serverId);\n this.databases = new DatabasesCollection(client, serverId);\n this.databaseUsers = new DatabaseUsersCollection(client, serverId);\n this.daemons = new DaemonsCollection(client, serverId);\n this.backups = new BackupsCollection(client, serverId);\n this.scheduledJobs = new ScheduledJobsCollection(client, serverId);\n this.monitors = new MonitorsCollection(client, serverId);\n this.firewallRules = new FirewallRulesCollection(client, serverId);\n this.sshKeys = new SshKeysCollection(client, serverId);\n this.nginxTemplates = new NginxTemplatesCollection(client, serverId);\n }\n\n /**\n * Access a specific site on this server, with nested resources.\n *\n * @example\n * ```ts\n * // Deploy a site\n * await forge.server(123).site(456).deploy();\n *\n * // Get environment variables\n * const env = await forge.server(123).site(456).env.get();\n * ```\n */\n site(siteId: number): SiteResource {\n return new SiteResource(this.client, this.serverId, siteId);\n }\n\n /**\n * Get this server's details.\n *\n * @example\n * ```ts\n * const server = await forge.server(123).get();\n * ```\n */\n async get(): Promise<ForgeServer> {\n const response = await this.client.get<ServerResponse>(`/servers/${this.serverId}`);\n return response.server;\n }\n\n /**\n * Reboot this server.\n *\n * @example\n * ```ts\n * await forge.server(123).reboot();\n * ```\n */\n async reboot(): Promise<void> {\n await this.client.post(`/servers/${this.serverId}/reboot`);\n }\n\n /**\n * Delete this server.\n *\n * @example\n * ```ts\n * await forge.server(123).delete();\n * ```\n */\n async delete(): Promise<void> {\n await this.client.delete(`/servers/${this.serverId}`);\n }\n}\n","import type {\n CreateRecipeData,\n ForgeRecipe,\n HttpClient,\n RecipeResponse,\n RecipesResponse,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing recipes.\n */\nexport interface RecipeListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Options for running a recipe.\n */\nexport interface RunRecipeOptions {\n /** Server IDs to run the recipe on. */\n servers: number[];\n}\n\n/**\n * Collection of recipes.\n *\n * Access via `forge.recipes`.\n *\n * @example\n * ```ts\n * const recipes = await forge.recipes.list();\n * ```\n */\nexport class RecipesCollection extends BaseCollection {\n /** @internal */\n constructor(client: HttpClient) {\n super(client);\n }\n\n private get basePath(): string {\n return `/recipes`;\n }\n\n /**\n * List all recipes.\n *\n * @example\n * ```ts\n * const recipes = await forge.recipes.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.recipes.list({ page: 2 });\n * ```\n */\n async list(options: RecipeListOptions = {}): Promise<ForgeRecipe[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<RecipesResponse>(`${this.basePath}${query}`);\n return response.recipes;\n }\n\n /**\n * Iterate over all recipes across all pages.\n *\n * @example\n * ```ts\n * for await (const recipe of forge.recipes.all()) {\n * console.log(recipe);\n * }\n *\n * // Or collect all at once:\n * const recipes = await forge.recipes.all().toArray();\n * ```\n */\n all(options: Omit<RecipeListOptions, \"page\"> = {}): AsyncPaginatedIterator<ForgeRecipe> {\n return new AsyncPaginatedIterator<ForgeRecipe>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific recipe.\n *\n * @example\n * ```ts\n * const recipe = await forge.recipes.get(789);\n * ```\n */\n async get(recipeId: number): Promise<ForgeRecipe> {\n const response = await this.client.get<RecipeResponse>(`${this.basePath}/${recipeId}`);\n return response.recipe;\n }\n\n /**\n * Create a new recipe.\n *\n * @example\n * ```ts\n * const recipe = await forge.recipes.create({\n * name: 'Install Node',\n * user: 'root',\n * script: 'curl -fsSL https://deb.nodesource.com/setup_20.x | bash -',\n * });\n * ```\n */\n async create(data: CreateRecipeData): Promise<ForgeRecipe> {\n const response = await this.client.post<RecipeResponse>(this.basePath, data);\n return response.recipe;\n }\n\n /**\n * Delete a recipe.\n *\n * @example\n * ```ts\n * await forge.recipes.delete(789);\n * ```\n */\n async delete(recipeId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${recipeId}`);\n }\n\n /**\n * Run a recipe on one or more servers.\n *\n * @example\n * ```ts\n * await forge.recipes.run(789, { servers: [123, 456] });\n * ```\n */\n async run(recipeId: number, options: RunRecipeOptions): Promise<void> {\n await this.client.post(`${this.basePath}/${recipeId}/run`, options);\n }\n}\n","import type { ForgeOptions, ForgeUser, UserResponse } from \"@studiometa/forge-api\";\n\nimport { HttpClient } from \"@studiometa/forge-api\";\n\nimport { ServersCollection, ServerResource } from \"./resources/servers.ts\";\nimport { RecipesCollection } from \"./resources/recipes.ts\";\n\n/**\n * Laravel Forge TypeScript SDK.\n *\n * Provides a fluent, chainable API for managing Laravel Forge servers,\n * sites, deployments, and more.\n *\n * @example\n * ```ts\n * import { Forge } from '@studiometa/forge-sdk';\n *\n * const forge = new Forge('your-api-token');\n *\n * // List all servers\n * const servers = await forge.servers.list();\n *\n * // Deploy a site\n * await forge.server(123).site(456).deploy();\n *\n * // Get environment variables\n * const env = await forge.server(123).site(456).env.get();\n *\n * // Manage databases\n * const dbs = await forge.server(123).databases.list();\n * ```\n */\nexport class Forge {\n /** @internal */\n readonly client: HttpClient;\n\n /** Server operations (list, get, create, update, delete, reboot). */\n readonly servers: ServersCollection;\n\n /** Recipe operations (list, get, create, delete, run). */\n readonly recipes: RecipesCollection;\n\n /**\n * Create a new Forge SDK instance.\n *\n * @param token Your Laravel Forge API token.\n * @param options Optional configuration (custom fetch, base URL, rate limiting).\n *\n * @example\n * ```ts\n * // Basic usage\n * const forge = new Forge('your-api-token');\n *\n * // With custom options\n * const forge = new Forge('your-api-token', {\n * baseUrl: 'https://custom-forge-instance.com/api/v1',\n * });\n *\n * // With mock fetch for testing\n * const forge = new Forge('test-token', { fetch: mockFetch });\n * ```\n */\n constructor(token: string, options?: ForgeOptions) {\n this.client = new HttpClient({ token, ...options });\n this.servers = new ServersCollection(this.client);\n this.recipes = new RecipesCollection(this.client);\n }\n\n /**\n * Access a specific server by ID, with nested resources.\n *\n * Returns a `ServerResource` that provides access to sites, databases,\n * daemons, and other server-level resources.\n *\n * @param serverId The server ID.\n *\n * @example\n * ```ts\n * // List sites on a server\n * const sites = await forge.server(123).sites.list();\n *\n * // Access a specific site\n * const site = await forge.server(123).site(456);\n *\n * // Deploy a site\n * await forge.server(123).site(456).deploy();\n *\n * // Manage databases\n * const dbs = await forge.server(123).databases.list();\n * ```\n */\n server(serverId: number): ServerResource {\n return new ServerResource(this.client, serverId);\n }\n\n /**\n * Get the currently authenticated user.\n *\n * @example\n * ```ts\n * const user = await forge.user();\n * console.log(user.name, user.email);\n * ```\n */\n async user(): Promise<ForgeUser> {\n const response = await this.client.get<UserResponse>(\"/user\");\n return response.user;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/pagination.ts","../src/utils/name-matcher.ts","../src/resources/base.ts","../src/resources/deployments.ts","../src/resources/certificates.ts","../src/resources/commands.ts","../src/resources/security-rules.ts","../src/resources/redirect-rules.ts","../src/resources/sites.ts","../src/resources/databases.ts","../src/resources/database-users.ts","../src/resources/daemons.ts","../src/resources/backups.ts","../src/resources/scheduled-jobs.ts","../src/resources/monitors.ts","../src/resources/firewall-rules.ts","../src/resources/ssh-keys.ts","../src/resources/nginx-templates.ts","../src/resources/servers.ts","../src/resources/recipes.ts","../src/forge.ts"],"sourcesContent":["/**\n * Function that fetches a page of results.\n */\nexport type PageFetcher<T> = (page: number) => Promise<T[]>;\n\n/**\n * Async paginated iterator that auto-fetches all pages.\n *\n * @example\n * ```ts\n * const iter = forge.server(123).site(456).deployments.all();\n * for await (const deployment of iter) {\n * console.log(deployment);\n * }\n *\n * // Or collect all items at once:\n * const deployments = await iter.toArray();\n * ```\n */\nexport class AsyncPaginatedIterator<T> {\n private fetchPage: PageFetcher<T>;\n private perPage: number;\n\n constructor(fetchPage: PageFetcher<T>, perPage = 200) {\n this.fetchPage = fetchPage;\n this.perPage = perPage;\n }\n\n async *[Symbol.asyncIterator](): AsyncGenerator<T, void, undefined> {\n let page = 1;\n let hasMore = true;\n\n while (hasMore) {\n const items = await this.fetchPage(page);\n\n for (const item of items) {\n yield item;\n }\n\n // If we got fewer items than perPage, we've reached the last page\n hasMore = items.length >= this.perPage;\n\n page++;\n }\n }\n\n /**\n * Collect all items into an array.\n *\n * @example\n * ```ts\n * const deployments = await forge.server(123).site(456).deployments.all().toArray();\n * ```\n */\n async toArray(): Promise<T[]> {\n const items: T[] = [];\n for await (const item of this) {\n items.push(item);\n }\n return items;\n }\n}\n","/**\n * Result of a name matching operation.\n */\nexport interface NameMatch<T> {\n exact: T[];\n partial: T[];\n}\n\n/**\n * Match items by name using case-insensitive exact and partial matching.\n */\nexport function matchByName<T>(\n items: T[],\n query: string,\n getName: (item: T) => string,\n): NameMatch<T> {\n const lower = query.toLowerCase();\n const exact = items.filter((item) => getName(item).toLowerCase() === lower);\n const partial = items.filter((item) => getName(item).toLowerCase().includes(lower));\n return { exact, partial };\n}\n","import type { HttpClient } from \"@studiometa/forge-api\";\n\n/**\n * Abstract base class for resource collections.\n * Provides a shared `client` property to avoid duplication across all collection classes.\n */\nexport abstract class BaseCollection {\n protected readonly client: HttpClient;\n\n constructor(client: HttpClient) {\n this.client = client;\n }\n}\n","import type {\n ForgeDeployment,\n HttpClient,\n DeploymentResponse,\n DeploymentsResponse,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing deployments.\n */\nexport interface DeploymentListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of deployments for a site.\n *\n * Access via `forge.server(id).site(id).deployments`.\n *\n * @example\n * ```ts\n * const deployments = await forge.server(123).site(456).deployments.list();\n * ```\n */\nexport class DeploymentsCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/sites/${this.siteId}/deployments`;\n }\n\n /**\n * List deployments for this site.\n *\n * @example\n * ```ts\n * const deployments = await forge.server(123).site(456).deployments.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).site(456).deployments.list({ page: 2 });\n * ```\n */\n async list(options: DeploymentListOptions = {}): Promise<ForgeDeployment[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<DeploymentsResponse>(`${this.basePath}${query}`);\n return response.deployments;\n }\n\n /**\n * Iterate over all deployments across all pages.\n *\n * @example\n * ```ts\n * for await (const deployment of forge.server(123).site(456).deployments.all()) {\n * console.log(deployment);\n * }\n *\n * // Or collect all at once:\n * const deployments = await forge.server(123).site(456).deployments.all().toArray();\n * ```\n */\n all(options: Omit<DeploymentListOptions, \"page\"> = {}): AsyncPaginatedIterator<ForgeDeployment> {\n return new AsyncPaginatedIterator<ForgeDeployment>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific deployment.\n *\n * @example\n * ```ts\n * const deployment = await forge.server(123).site(456).deployments.get(789);\n * ```\n */\n async get(deploymentId: number): Promise<ForgeDeployment> {\n const response = await this.client.get<DeploymentResponse>(`${this.basePath}/${deploymentId}`);\n return response.deployment;\n }\n\n /**\n * Get the output of a deployment.\n *\n * @example\n * ```ts\n * const output = await forge.server(123).site(456).deployments.output(789);\n * ```\n */\n async output(deploymentId: number): Promise<string> {\n return this.client.get<string>(`${this.basePath}/${deploymentId}/output`);\n }\n\n /**\n * Get the deployment script.\n *\n * @example\n * ```ts\n * const script = await forge.server(123).site(456).deployments.script();\n * ```\n */\n async script(): Promise<string> {\n return this.client.get<string>(\n `/servers/${this.serverId}/sites/${this.siteId}/deployment/script`,\n );\n }\n\n /**\n * Update the deployment script.\n *\n * @example\n * ```ts\n * await forge.server(123).site(456).deployments.updateScript('npm run build && ...');\n * ```\n */\n async updateScript(content: string): Promise<void> {\n await this.client.put(`/servers/${this.serverId}/sites/${this.siteId}/deployment/script`, {\n content,\n });\n }\n}\n","import type {\n CreateCertificateData,\n ForgeCertificate,\n HttpClient,\n CertificateResponse,\n CertificatesResponse,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing certificates.\n */\nexport interface CertificateListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of SSL certificates for a site.\n *\n * Access via `forge.server(id).site(id).certificates`.\n *\n * @example\n * ```ts\n * const certs = await forge.server(123).site(456).certificates.list();\n * ```\n */\nexport class CertificatesCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/sites/${this.siteId}/certificates`;\n }\n\n /**\n * List certificates for this site.\n *\n * @example\n * ```ts\n * const certs = await forge.server(123).site(456).certificates.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).site(456).certificates.list({ page: 2 });\n * ```\n */\n async list(options: CertificateListOptions = {}): Promise<ForgeCertificate[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<CertificatesResponse>(`${this.basePath}${query}`);\n return response.certificates;\n }\n\n /**\n * Iterate over all certificates across all pages.\n *\n * @example\n * ```ts\n * for await (const cert of forge.server(123).site(456).certificates.all()) {\n * console.log(cert);\n * }\n *\n * // Or collect all at once:\n * const certs = await forge.server(123).site(456).certificates.all().toArray();\n * ```\n */\n all(\n options: Omit<CertificateListOptions, \"page\"> = {},\n ): AsyncPaginatedIterator<ForgeCertificate> {\n return new AsyncPaginatedIterator<ForgeCertificate>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific certificate.\n *\n * @example\n * ```ts\n * const cert = await forge.server(123).site(456).certificates.get(789);\n * ```\n */\n async get(certificateId: number): Promise<ForgeCertificate> {\n const response = await this.client.get<CertificateResponse>(\n `${this.basePath}/${certificateId}`,\n );\n return response.certificate;\n }\n\n /**\n * Create a new SSL certificate.\n *\n * @example\n * ```ts\n * const cert = await forge.server(123).site(456).certificates.create({\n * type: 'new',\n * domain: 'example.com',\n * });\n * ```\n */\n async create(data: CreateCertificateData): Promise<ForgeCertificate> {\n const response = await this.client.post<CertificateResponse>(this.basePath, data);\n return response.certificate;\n }\n\n /**\n * Install a Let's Encrypt certificate.\n *\n * @example\n * ```ts\n * await forge.server(123).site(456).certificates.letsEncrypt(['example.com', 'www.example.com']);\n * ```\n */\n async letsEncrypt(domains: string[]): Promise<ForgeCertificate> {\n const response = await this.client.post<CertificateResponse>(`${this.basePath}/letsencrypt`, {\n domains,\n });\n return response.certificate;\n }\n\n /**\n * Delete a certificate.\n *\n * @example\n * ```ts\n * await forge.server(123).site(456).certificates.delete(789);\n * ```\n */\n async delete(certificateId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${certificateId}`);\n }\n\n /**\n * Activate a certificate.\n *\n * @example\n * ```ts\n * await forge.server(123).site(456).certificates.activate(789);\n * ```\n */\n async activate(certificateId: number): Promise<void> {\n await this.client.post(`${this.basePath}/${certificateId}/activate`);\n }\n}\n","import type {\n CommandResponse,\n CommandsResponse,\n CreateCommandData,\n ForgeCommand,\n HttpClient,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing site commands.\n */\nexport interface CommandListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of commands run on a site.\n *\n * Access via `forge.server(id).site(id).commands`.\n *\n * @example\n * ```ts\n * const commands = await forge.server(123).site(456).commands.list();\n * ```\n */\nexport class CommandsCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/sites/${this.siteId}/commands`;\n }\n\n /**\n * List commands run on this site.\n *\n * @example\n * ```ts\n * const commands = await forge.server(123).site(456).commands.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).site(456).commands.list({ page: 2 });\n * ```\n */\n async list(options: CommandListOptions = {}): Promise<ForgeCommand[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<CommandsResponse>(`${this.basePath}${query}`);\n return response.commands;\n }\n\n /**\n * Iterate over all commands across all pages.\n *\n * @example\n * ```ts\n * for await (const command of forge.server(123).site(456).commands.all()) {\n * console.log(command);\n * }\n *\n * // Or collect all at once:\n * const commands = await forge.server(123).site(456).commands.all().toArray();\n * ```\n */\n all(options: Omit<CommandListOptions, \"page\"> = {}): AsyncPaginatedIterator<ForgeCommand> {\n return new AsyncPaginatedIterator<ForgeCommand>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific command.\n *\n * @example\n * ```ts\n * const command = await forge.server(123).site(456).commands.get(789);\n * ```\n */\n async get(commandId: number): Promise<ForgeCommand> {\n const response = await this.client.get<CommandResponse>(`${this.basePath}/${commandId}`);\n return response.command;\n }\n\n /**\n * Run a command on this site.\n *\n * @example\n * ```ts\n * const command = await forge.server(123).site(456).commands.create({\n * command: 'php artisan migrate',\n * });\n * ```\n */\n async create(data: CreateCommandData): Promise<ForgeCommand> {\n const response = await this.client.post<CommandResponse>(this.basePath, data);\n return response.command;\n }\n}\n","import type {\n CreateSecurityRuleData,\n ForgeSecurityRule,\n HttpClient,\n SecurityRuleResponse,\n SecurityRulesResponse,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing security rules.\n */\nexport interface SecurityRuleListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of security rules on a site.\n *\n * Access via `forge.server(id).site(id).securityRules`.\n *\n * @example\n * ```ts\n * const rules = await forge.server(123).site(456).securityRules.list();\n * ```\n */\nexport class SecurityRulesCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/sites/${this.siteId}/security-rules`;\n }\n\n /**\n * List security rules on this site.\n *\n * @example\n * ```ts\n * const rules = await forge.server(123).site(456).securityRules.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).site(456).securityRules.list({ page: 2 });\n * ```\n */\n async list(options: SecurityRuleListOptions = {}): Promise<ForgeSecurityRule[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<SecurityRulesResponse>(`${this.basePath}${query}`);\n return response.security_rules;\n }\n\n /**\n * Iterate over all security rules across all pages.\n *\n * @example\n * ```ts\n * for await (const rule of forge.server(123).site(456).securityRules.all()) {\n * console.log(rule);\n * }\n *\n * // Or collect all at once:\n * const rules = await forge.server(123).site(456).securityRules.all().toArray();\n * ```\n */\n all(\n options: Omit<SecurityRuleListOptions, \"page\"> = {},\n ): AsyncPaginatedIterator<ForgeSecurityRule> {\n return new AsyncPaginatedIterator<ForgeSecurityRule>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific security rule.\n *\n * @example\n * ```ts\n * const rule = await forge.server(123).site(456).securityRules.get(789);\n * ```\n */\n async get(ruleId: number): Promise<ForgeSecurityRule> {\n const response = await this.client.get<SecurityRuleResponse>(`${this.basePath}/${ruleId}`);\n return response.security_rule;\n }\n\n /**\n * Create a new security rule.\n *\n * @example\n * ```ts\n * const rule = await forge.server(123).site(456).securityRules.create({\n * name: 'Admin Area',\n * path: '/admin',\n * credentials: [{ username: 'admin', password: 'secret' }],\n * });\n * ```\n */\n async create(data: CreateSecurityRuleData): Promise<ForgeSecurityRule> {\n const response = await this.client.post<SecurityRuleResponse>(this.basePath, data);\n return response.security_rule;\n }\n\n /**\n * Delete a security rule.\n *\n * @example\n * ```ts\n * await forge.server(123).site(456).securityRules.delete(789);\n * ```\n */\n async delete(ruleId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${ruleId}`);\n }\n}\n","import type {\n CreateRedirectRuleData,\n ForgeRedirectRule,\n HttpClient,\n RedirectRuleResponse,\n RedirectRulesResponse,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing redirect rules.\n */\nexport interface RedirectRuleListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of redirect rules on a site.\n *\n * Access via `forge.server(id).site(id).redirectRules`.\n *\n * @example\n * ```ts\n * const rules = await forge.server(123).site(456).redirectRules.list();\n * ```\n */\nexport class RedirectRulesCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/sites/${this.siteId}/redirect-rules`;\n }\n\n /**\n * List redirect rules on this site.\n *\n * @example\n * ```ts\n * const rules = await forge.server(123).site(456).redirectRules.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).site(456).redirectRules.list({ page: 2 });\n * ```\n */\n async list(options: RedirectRuleListOptions = {}): Promise<ForgeRedirectRule[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<RedirectRulesResponse>(`${this.basePath}${query}`);\n return response.redirect_rules;\n }\n\n /**\n * Iterate over all redirect rules across all pages.\n *\n * @example\n * ```ts\n * for await (const rule of forge.server(123).site(456).redirectRules.all()) {\n * console.log(rule);\n * }\n *\n * // Or collect all at once:\n * const rules = await forge.server(123).site(456).redirectRules.all().toArray();\n * ```\n */\n all(\n options: Omit<RedirectRuleListOptions, \"page\"> = {},\n ): AsyncPaginatedIterator<ForgeRedirectRule> {\n return new AsyncPaginatedIterator<ForgeRedirectRule>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific redirect rule.\n *\n * @example\n * ```ts\n * const rule = await forge.server(123).site(456).redirectRules.get(789);\n * ```\n */\n async get(ruleId: number): Promise<ForgeRedirectRule> {\n const response = await this.client.get<RedirectRuleResponse>(`${this.basePath}/${ruleId}`);\n return response.redirect_rule;\n }\n\n /**\n * Create a new redirect rule.\n *\n * @example\n * ```ts\n * const rule = await forge.server(123).site(456).redirectRules.create({\n * from: '/old-path',\n * to: '/new-path',\n * type: 'redirect',\n * });\n * ```\n */\n async create(data: CreateRedirectRuleData): Promise<ForgeRedirectRule> {\n const response = await this.client.post<RedirectRuleResponse>(this.basePath, data);\n return response.redirect_rule;\n }\n\n /**\n * Delete a redirect rule.\n *\n * @example\n * ```ts\n * await forge.server(123).site(456).redirectRules.delete(789);\n * ```\n */\n async delete(ruleId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${ruleId}`);\n }\n}\n","import type {\n CreateSiteData,\n ForgeSite,\n HttpClient,\n SiteResponse,\n SitesResponse,\n} from \"@studiometa/forge-api\";\n\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\nimport { matchByName } from \"../utils/name-matcher.ts\";\nimport type { ResolveResult } from \"./servers.ts\";\nimport { DeploymentsCollection } from \"./deployments.ts\";\nimport { CertificatesCollection } from \"./certificates.ts\";\nimport { CommandsCollection } from \"./commands.ts\";\nimport { SecurityRulesCollection } from \"./security-rules.ts\";\nimport { RedirectRulesCollection } from \"./redirect-rules.ts\";\nimport { BaseCollection } from \"./base.ts\";\n\n/**\n * Options for listing sites.\n */\nexport interface SiteListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of sites on a server.\n *\n * Access via `forge.server(id).sites`.\n *\n * @example\n * ```ts\n * const sites = await forge.server(123).sites.list();\n * ```\n */\nexport class SitesCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/sites`;\n }\n\n /**\n * List sites on this server.\n *\n * @example\n * ```ts\n * const sites = await forge.server(123).sites.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).sites.list({ page: 2 });\n * ```\n */\n async list(options: SiteListOptions = {}): Promise<ForgeSite[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<SitesResponse>(`${this.basePath}${query}`);\n return response.sites;\n }\n\n /**\n * Iterate over all sites across all pages.\n *\n * @example\n * ```ts\n * for await (const site of forge.server(123).sites.all()) {\n * console.log(site);\n * }\n *\n * // Or collect all at once:\n * const sites = await forge.server(123).sites.all().toArray();\n * ```\n */\n all(options: Omit<SiteListOptions, \"page\"> = {}): AsyncPaginatedIterator<ForgeSite> {\n return new AsyncPaginatedIterator<ForgeSite>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific site by ID.\n *\n * @example\n * ```ts\n * const site = await forge.server(123).sites.get(456);\n * ```\n */\n async get(siteId: number): Promise<ForgeSite> {\n const response = await this.client.get<SiteResponse>(`${this.basePath}/${siteId}`);\n return response.site;\n }\n\n /**\n * Create a new site on this server.\n *\n * @example\n * ```ts\n * const site = await forge.server(123).sites.create({\n * domain: 'example.com',\n * project_type: 'php',\n * directory: '/public',\n * });\n * ```\n */\n async create(data: CreateSiteData): Promise<ForgeSite> {\n const response = await this.client.post<SiteResponse>(this.basePath, data);\n return response.site;\n }\n\n /**\n * Update a site.\n *\n * @example\n * ```ts\n * await forge.server(123).sites.update(456, { directory: '/public' });\n * ```\n */\n async update(siteId: number, data: Partial<CreateSiteData>): Promise<ForgeSite> {\n const response = await this.client.put<SiteResponse>(`${this.basePath}/${siteId}`, data);\n return response.site;\n }\n\n /**\n * Delete a site.\n *\n * @example\n * ```ts\n * await forge.server(123).sites.delete(456);\n * ```\n */\n async delete(siteId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${siteId}`);\n }\n\n /**\n * Find sites by domain name using case-insensitive partial matching.\n *\n * If exactly one site matches the query exactly, only that site is returned.\n * Otherwise all partial matches are returned.\n *\n * @param query - The search query to match against site domain names.\n * @returns Resolve result with matching sites.\n *\n * @example\n * ```ts\n * // Find sites matching \"example\"\n * const result = await forge.server(123).sites.resolve('example');\n * // → { query: 'example', matches: [{ id: 456, name: 'example.com' }], total: 1 }\n * ```\n */\n async resolve(query: string): Promise<ResolveResult> {\n const sites = await this.list();\n const { exact, partial } = matchByName(sites, query, (s) => s.name);\n const matches = exact.length === 1 ? exact : partial;\n return {\n query,\n matches: matches.map((s) => ({ id: s.id, name: s.name })),\n total: matches.length,\n };\n }\n}\n\n/**\n * A specific site with nested resources and actions.\n *\n * Access via `forge.server(id).site(id)`.\n *\n * @example\n * ```ts\n * // Deploy\n * await forge.server(123).site(456).deploy();\n *\n * // Get environment\n * const env = await forge.server(123).site(456).env.get();\n * ```\n */\nexport class SiteResource extends BaseCollection {\n /** Deployments for this site. */\n readonly deployments: DeploymentsCollection;\n\n /** SSL certificates for this site. */\n readonly certificates: CertificatesCollection;\n\n /** Environment variables for this site. */\n readonly env: SiteEnvResource;\n\n /** Nginx configuration for this site. */\n readonly nginx: SiteNginxResource;\n\n /** Commands run on this site. */\n readonly commands: CommandsCollection;\n\n /** Security rules for this site. */\n readonly securityRules: SecurityRulesCollection;\n\n /** Redirect rules for this site. */\n readonly redirectRules: RedirectRulesCollection;\n\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client);\n this.deployments = new DeploymentsCollection(client, serverId, siteId);\n this.certificates = new CertificatesCollection(client, serverId, siteId);\n this.env = new SiteEnvResource(client, serverId, siteId);\n this.nginx = new SiteNginxResource(client, serverId, siteId);\n this.commands = new CommandsCollection(client, serverId, siteId);\n this.securityRules = new SecurityRulesCollection(client, serverId, siteId);\n this.redirectRules = new RedirectRulesCollection(client, serverId, siteId);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/sites/${this.siteId}`;\n }\n\n /**\n * Get this site's details.\n *\n * @example\n * ```ts\n * const site = await forge.server(123).site(456).get();\n * ```\n */\n async get(): Promise<ForgeSite> {\n const response = await this.client.get<SiteResponse>(this.basePath);\n return response.site;\n }\n\n /**\n * Deploy this site.\n *\n * @example\n * ```ts\n * await forge.server(123).site(456).deploy();\n * ```\n */\n async deploy(): Promise<void> {\n await this.client.post(`${this.basePath}/deployment/deploy`);\n }\n\n /**\n * Delete this site.\n *\n * @example\n * ```ts\n * await forge.server(123).site(456).delete();\n * ```\n */\n async delete(): Promise<void> {\n await this.client.delete(this.basePath);\n }\n}\n\n/**\n * Environment variables for a site.\n *\n * @example\n * ```ts\n * const env = await forge.server(123).site(456).env.get();\n * await forge.server(123).site(456).env.update('APP_ENV=production\\n...');\n * ```\n */\nexport class SiteEnvResource extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/sites/${this.siteId}/env`;\n }\n\n /**\n * Get the environment file content.\n *\n * @returns The .env file content as a string.\n */\n async get(): Promise<string> {\n return this.client.get<string>(this.basePath);\n }\n\n /**\n * Update the environment file content.\n *\n * @param content The full .env file content.\n */\n async update(content: string): Promise<void> {\n await this.client.put(this.basePath, { content });\n }\n}\n\n/**\n * Nginx configuration for a site.\n *\n * @example\n * ```ts\n * const config = await forge.server(123).site(456).nginx.get();\n * await forge.server(123).site(456).nginx.update('server { ... }');\n * ```\n */\nexport class SiteNginxResource extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/sites/${this.siteId}/nginx`;\n }\n\n /**\n * Get the Nginx configuration.\n *\n * @returns The Nginx config content as a string.\n */\n async get(): Promise<string> {\n return this.client.get<string>(this.basePath);\n }\n\n /**\n * Update the Nginx configuration.\n *\n * @param content The full Nginx config content.\n */\n async update(content: string): Promise<void> {\n await this.client.put(this.basePath, { content });\n }\n}\n","import type {\n CreateDatabaseData,\n ForgeDatabase,\n HttpClient,\n DatabaseResponse,\n DatabasesResponse,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing databases.\n */\nexport interface DatabaseListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of databases on a server.\n *\n * Access via `forge.server(id).databases`.\n *\n * @example\n * ```ts\n * const dbs = await forge.server(123).databases.list();\n * ```\n */\nexport class DatabasesCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/databases`;\n }\n\n /**\n * List databases on this server.\n *\n * @example\n * ```ts\n * const dbs = await forge.server(123).databases.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).databases.list({ page: 2 });\n * ```\n */\n async list(options: DatabaseListOptions = {}): Promise<ForgeDatabase[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<DatabasesResponse>(`${this.basePath}${query}`);\n return response.databases;\n }\n\n /**\n * Iterate over all databases across all pages.\n *\n * @example\n * ```ts\n * for await (const db of forge.server(123).databases.all()) {\n * console.log(db);\n * }\n *\n * // Or collect all at once:\n * const dbs = await forge.server(123).databases.all().toArray();\n * ```\n */\n all(options: Omit<DatabaseListOptions, \"page\"> = {}): AsyncPaginatedIterator<ForgeDatabase> {\n return new AsyncPaginatedIterator<ForgeDatabase>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific database.\n *\n * @example\n * ```ts\n * const db = await forge.server(123).databases.get(789);\n * ```\n */\n async get(databaseId: number): Promise<ForgeDatabase> {\n const response = await this.client.get<DatabaseResponse>(`${this.basePath}/${databaseId}`);\n return response.database;\n }\n\n /**\n * Create a new database.\n *\n * @example\n * ```ts\n * const db = await forge.server(123).databases.create({\n * name: 'myapp',\n * user: 'admin',\n * password: 'secret',\n * });\n * ```\n */\n async create(data: CreateDatabaseData): Promise<ForgeDatabase> {\n const response = await this.client.post<DatabaseResponse>(this.basePath, data);\n return response.database;\n }\n\n /**\n * Delete a database.\n *\n * @example\n * ```ts\n * await forge.server(123).databases.delete(789);\n * ```\n */\n async delete(databaseId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${databaseId}`);\n }\n}\n","import type {\n CreateDatabaseUserData,\n DatabaseUserResponse,\n DatabaseUsersResponse,\n ForgeDatabaseUser,\n HttpClient,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing database users.\n */\nexport interface DatabaseUserListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of database users on a server.\n *\n * Access via `forge.server(id).databaseUsers`.\n *\n * @example\n * ```ts\n * const users = await forge.server(123).databaseUsers.list();\n * ```\n */\nexport class DatabaseUsersCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/database-users`;\n }\n\n /**\n * List database users on this server.\n *\n * @example\n * ```ts\n * const users = await forge.server(123).databaseUsers.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).databaseUsers.list({ page: 2 });\n * ```\n */\n async list(options: DatabaseUserListOptions = {}): Promise<ForgeDatabaseUser[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<DatabaseUsersResponse>(`${this.basePath}${query}`);\n return response.users;\n }\n\n /**\n * Iterate over all database users across all pages.\n *\n * @example\n * ```ts\n * for await (const user of forge.server(123).databaseUsers.all()) {\n * console.log(user);\n * }\n *\n * // Or collect all at once:\n * const users = await forge.server(123).databaseUsers.all().toArray();\n * ```\n */\n all(\n options: Omit<DatabaseUserListOptions, \"page\"> = {},\n ): AsyncPaginatedIterator<ForgeDatabaseUser> {\n return new AsyncPaginatedIterator<ForgeDatabaseUser>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific database user.\n *\n * @example\n * ```ts\n * const user = await forge.server(123).databaseUsers.get(789);\n * ```\n */\n async get(userId: number): Promise<ForgeDatabaseUser> {\n const response = await this.client.get<DatabaseUserResponse>(`${this.basePath}/${userId}`);\n return response.user;\n }\n\n /**\n * Create a new database user.\n *\n * @example\n * ```ts\n * const user = await forge.server(123).databaseUsers.create({\n * name: 'forge',\n * password: 'secret',\n * databases: [1, 2],\n * });\n * ```\n */\n async create(data: CreateDatabaseUserData): Promise<ForgeDatabaseUser> {\n const response = await this.client.post<DatabaseUserResponse>(this.basePath, data);\n return response.user;\n }\n\n /**\n * Delete a database user.\n *\n * @example\n * ```ts\n * await forge.server(123).databaseUsers.delete(789);\n * ```\n */\n async delete(userId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${userId}`);\n }\n}\n","import type {\n CreateDaemonData,\n ForgeDaemon,\n HttpClient,\n DaemonResponse,\n DaemonsResponse,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing daemons.\n */\nexport interface DaemonListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of daemons (background processes) on a server.\n *\n * Access via `forge.server(id).daemons`.\n *\n * @example\n * ```ts\n * const daemons = await forge.server(123).daemons.list();\n * ```\n */\nexport class DaemonsCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/daemons`;\n }\n\n /**\n * List daemons on this server.\n *\n * @example\n * ```ts\n * const daemons = await forge.server(123).daemons.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).daemons.list({ page: 2 });\n * ```\n */\n async list(options: DaemonListOptions = {}): Promise<ForgeDaemon[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<DaemonsResponse>(`${this.basePath}${query}`);\n return response.daemons;\n }\n\n /**\n * Iterate over all daemons across all pages.\n *\n * @example\n * ```ts\n * for await (const daemon of forge.server(123).daemons.all()) {\n * console.log(daemon);\n * }\n *\n * // Or collect all at once:\n * const daemons = await forge.server(123).daemons.all().toArray();\n * ```\n */\n all(options: Omit<DaemonListOptions, \"page\"> = {}): AsyncPaginatedIterator<ForgeDaemon> {\n return new AsyncPaginatedIterator<ForgeDaemon>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific daemon.\n *\n * @example\n * ```ts\n * const daemon = await forge.server(123).daemons.get(789);\n * ```\n */\n async get(daemonId: number): Promise<ForgeDaemon> {\n const response = await this.client.get<DaemonResponse>(`${this.basePath}/${daemonId}`);\n return response.daemon;\n }\n\n /**\n * Create a new daemon.\n *\n * @example\n * ```ts\n * const daemon = await forge.server(123).daemons.create({\n * command: 'php artisan queue:work',\n * user: 'forge',\n * });\n * ```\n */\n async create(data: CreateDaemonData): Promise<ForgeDaemon> {\n const response = await this.client.post<DaemonResponse>(this.basePath, data);\n return response.daemon;\n }\n\n /**\n * Delete a daemon.\n *\n * @example\n * ```ts\n * await forge.server(123).daemons.delete(789);\n * ```\n */\n async delete(daemonId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${daemonId}`);\n }\n\n /**\n * Restart a daemon.\n *\n * @example\n * ```ts\n * await forge.server(123).daemons.restart(789);\n * ```\n */\n async restart(daemonId: number): Promise<void> {\n await this.client.post(`${this.basePath}/${daemonId}/restart`);\n }\n}\n","import type {\n BackupConfigResponse,\n BackupConfigsResponse,\n CreateBackupConfigData,\n ForgeBackupConfig,\n HttpClient,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing backup configurations.\n */\nexport interface BackupConfigListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of backup configurations on a server.\n *\n * Access via `forge.server(id).backups`.\n *\n * @example\n * ```ts\n * const backups = await forge.server(123).backups.list();\n * ```\n */\nexport class BackupsCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/backup-configs`;\n }\n\n /**\n * List backup configurations on this server.\n *\n * @example\n * ```ts\n * const backups = await forge.server(123).backups.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).backups.list({ page: 2 });\n * ```\n */\n async list(options: BackupConfigListOptions = {}): Promise<ForgeBackupConfig[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<BackupConfigsResponse>(`${this.basePath}${query}`);\n return response.backups;\n }\n\n /**\n * Iterate over all backup configurations across all pages.\n *\n * @example\n * ```ts\n * for await (const backup of forge.server(123).backups.all()) {\n * console.log(backup);\n * }\n *\n * // Or collect all at once:\n * const backups = await forge.server(123).backups.all().toArray();\n * ```\n */\n all(\n options: Omit<BackupConfigListOptions, \"page\"> = {},\n ): AsyncPaginatedIterator<ForgeBackupConfig> {\n return new AsyncPaginatedIterator<ForgeBackupConfig>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific backup configuration.\n *\n * @example\n * ```ts\n * const backup = await forge.server(123).backups.get(789);\n * ```\n */\n async get(backupId: number): Promise<ForgeBackupConfig> {\n const response = await this.client.get<BackupConfigResponse>(`${this.basePath}/${backupId}`);\n return response.backup;\n }\n\n /**\n * Create a new backup configuration.\n *\n * @example\n * ```ts\n * const backup = await forge.server(123).backups.create({\n * provider: 's3',\n * credentials: { key: 'ACCESS_KEY', secret: 'SECRET_KEY', region: 'us-east-1', bucket: 'my-bucket' },\n * frequency: 'weekly',\n * retention: 7,\n * databases: [1, 2],\n * });\n * ```\n */\n async create(data: CreateBackupConfigData): Promise<ForgeBackupConfig> {\n const response = await this.client.post<BackupConfigResponse>(this.basePath, data);\n return response.backup;\n }\n\n /**\n * Delete a backup configuration.\n *\n * @example\n * ```ts\n * await forge.server(123).backups.delete(789);\n * ```\n */\n async delete(backupId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${backupId}`);\n }\n}\n","import type {\n CreateScheduledJobData,\n ForgeScheduledJob,\n HttpClient,\n ScheduledJobResponse,\n ScheduledJobsResponse,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing scheduled jobs.\n */\nexport interface ScheduledJobListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of scheduled jobs (cron jobs) on a server.\n *\n * Access via `forge.server(id).scheduledJobs`.\n *\n * @example\n * ```ts\n * const jobs = await forge.server(123).scheduledJobs.list();\n * ```\n */\nexport class ScheduledJobsCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/jobs`;\n }\n\n /**\n * List scheduled jobs on this server.\n *\n * @example\n * ```ts\n * const jobs = await forge.server(123).scheduledJobs.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).scheduledJobs.list({ page: 2 });\n * ```\n */\n async list(options: ScheduledJobListOptions = {}): Promise<ForgeScheduledJob[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<ScheduledJobsResponse>(`${this.basePath}${query}`);\n return response.jobs;\n }\n\n /**\n * Iterate over all scheduled jobs across all pages.\n *\n * @example\n * ```ts\n * for await (const job of forge.server(123).scheduledJobs.all()) {\n * console.log(job);\n * }\n *\n * // Or collect all at once:\n * const jobs = await forge.server(123).scheduledJobs.all().toArray();\n * ```\n */\n all(\n options: Omit<ScheduledJobListOptions, \"page\"> = {},\n ): AsyncPaginatedIterator<ForgeScheduledJob> {\n return new AsyncPaginatedIterator<ForgeScheduledJob>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific scheduled job.\n *\n * @example\n * ```ts\n * const job = await forge.server(123).scheduledJobs.get(789);\n * ```\n */\n async get(jobId: number): Promise<ForgeScheduledJob> {\n const response = await this.client.get<ScheduledJobResponse>(`${this.basePath}/${jobId}`);\n return response.job;\n }\n\n /**\n * Create a new scheduled job.\n *\n * @example\n * ```ts\n * const job = await forge.server(123).scheduledJobs.create({\n * command: 'php /home/forge/artisan schedule:run',\n * user: 'forge',\n * frequency: 'minutely',\n * });\n * ```\n */\n async create(data: CreateScheduledJobData): Promise<ForgeScheduledJob> {\n const response = await this.client.post<ScheduledJobResponse>(this.basePath, data);\n return response.job;\n }\n\n /**\n * Delete a scheduled job.\n *\n * @example\n * ```ts\n * await forge.server(123).scheduledJobs.delete(789);\n * ```\n */\n async delete(jobId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${jobId}`);\n }\n}\n","import type {\n CreateMonitorData,\n ForgeMonitor,\n HttpClient,\n MonitorResponse,\n MonitorsResponse,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing monitors.\n */\nexport interface MonitorListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of server monitors.\n *\n * Access via `forge.server(id).monitors`.\n *\n * @example\n * ```ts\n * const monitors = await forge.server(123).monitors.list();\n * ```\n */\nexport class MonitorsCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/monitors`;\n }\n\n /**\n * List monitors on this server.\n *\n * @example\n * ```ts\n * const monitors = await forge.server(123).monitors.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).monitors.list({ page: 2 });\n * ```\n */\n async list(options: MonitorListOptions = {}): Promise<ForgeMonitor[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<MonitorsResponse>(`${this.basePath}${query}`);\n return response.monitors;\n }\n\n /**\n * Iterate over all monitors across all pages.\n *\n * @example\n * ```ts\n * for await (const monitor of forge.server(123).monitors.all()) {\n * console.log(monitor);\n * }\n *\n * // Or collect all at once:\n * const monitors = await forge.server(123).monitors.all().toArray();\n * ```\n */\n all(options: Omit<MonitorListOptions, \"page\"> = {}): AsyncPaginatedIterator<ForgeMonitor> {\n return new AsyncPaginatedIterator<ForgeMonitor>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific monitor.\n *\n * @example\n * ```ts\n * const monitor = await forge.server(123).monitors.get(789);\n * ```\n */\n async get(monitorId: number): Promise<ForgeMonitor> {\n const response = await this.client.get<MonitorResponse>(`${this.basePath}/${monitorId}`);\n return response.monitor;\n }\n\n /**\n * Create a new monitor.\n *\n * @example\n * ```ts\n * const monitor = await forge.server(123).monitors.create({\n * type: 'cpu_load',\n * operator: 'gte',\n * threshold: 80,\n * minutes: 5,\n * });\n * ```\n */\n async create(data: CreateMonitorData): Promise<ForgeMonitor> {\n const response = await this.client.post<MonitorResponse>(this.basePath, data);\n return response.monitor;\n }\n\n /**\n * Delete a monitor.\n *\n * @example\n * ```ts\n * await forge.server(123).monitors.delete(789);\n * ```\n */\n async delete(monitorId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${monitorId}`);\n }\n}\n","import type {\n CreateFirewallRuleData,\n FirewallRuleResponse,\n FirewallRulesResponse,\n ForgeFirewallRule,\n HttpClient,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing firewall rules.\n */\nexport interface FirewallRuleListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of firewall rules on a server.\n *\n * Access via `forge.server(id).firewallRules`.\n *\n * @example\n * ```ts\n * const rules = await forge.server(123).firewallRules.list();\n * ```\n */\nexport class FirewallRulesCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/firewall-rules`;\n }\n\n /**\n * List firewall rules on this server.\n *\n * @example\n * ```ts\n * const rules = await forge.server(123).firewallRules.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).firewallRules.list({ page: 2 });\n * ```\n */\n async list(options: FirewallRuleListOptions = {}): Promise<ForgeFirewallRule[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<FirewallRulesResponse>(`${this.basePath}${query}`);\n return response.rules;\n }\n\n /**\n * Iterate over all firewall rules across all pages.\n *\n * @example\n * ```ts\n * for await (const rule of forge.server(123).firewallRules.all()) {\n * console.log(rule);\n * }\n *\n * // Or collect all at once:\n * const rules = await forge.server(123).firewallRules.all().toArray();\n * ```\n */\n all(\n options: Omit<FirewallRuleListOptions, \"page\"> = {},\n ): AsyncPaginatedIterator<ForgeFirewallRule> {\n return new AsyncPaginatedIterator<ForgeFirewallRule>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific firewall rule.\n *\n * @example\n * ```ts\n * const rule = await forge.server(123).firewallRules.get(789);\n * ```\n */\n async get(ruleId: number): Promise<ForgeFirewallRule> {\n const response = await this.client.get<FirewallRuleResponse>(`${this.basePath}/${ruleId}`);\n return response.rule;\n }\n\n /**\n * Create a new firewall rule.\n *\n * @example\n * ```ts\n * const rule = await forge.server(123).firewallRules.create({\n * name: 'Allow HTTP',\n * port: 80,\n * type: 'allow',\n * });\n * ```\n */\n async create(data: CreateFirewallRuleData): Promise<ForgeFirewallRule> {\n const response = await this.client.post<FirewallRuleResponse>(this.basePath, data);\n return response.rule;\n }\n\n /**\n * Delete a firewall rule.\n *\n * @example\n * ```ts\n * await forge.server(123).firewallRules.delete(789);\n * ```\n */\n async delete(ruleId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${ruleId}`);\n }\n}\n","import type {\n CreateSshKeyData,\n ForgeSshKey,\n HttpClient,\n SshKeyResponse,\n SshKeysResponse,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing SSH keys.\n */\nexport interface SshKeyListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of SSH keys on a server.\n *\n * Access via `forge.server(id).sshKeys`.\n *\n * @example\n * ```ts\n * const keys = await forge.server(123).sshKeys.list();\n * ```\n */\nexport class SshKeysCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/keys`;\n }\n\n /**\n * List SSH keys on this server.\n *\n * @example\n * ```ts\n * const keys = await forge.server(123).sshKeys.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).sshKeys.list({ page: 2 });\n * ```\n */\n async list(options: SshKeyListOptions = {}): Promise<ForgeSshKey[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<SshKeysResponse>(`${this.basePath}${query}`);\n return response.keys;\n }\n\n /**\n * Iterate over all SSH keys across all pages.\n *\n * @example\n * ```ts\n * for await (const key of forge.server(123).sshKeys.all()) {\n * console.log(key);\n * }\n *\n * // Or collect all at once:\n * const keys = await forge.server(123).sshKeys.all().toArray();\n * ```\n */\n all(options: Omit<SshKeyListOptions, \"page\"> = {}): AsyncPaginatedIterator<ForgeSshKey> {\n return new AsyncPaginatedIterator<ForgeSshKey>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific SSH key.\n *\n * @example\n * ```ts\n * const key = await forge.server(123).sshKeys.get(789);\n * ```\n */\n async get(keyId: number): Promise<ForgeSshKey> {\n const response = await this.client.get<SshKeyResponse>(`${this.basePath}/${keyId}`);\n return response.key;\n }\n\n /**\n * Create a new SSH key.\n *\n * @example\n * ```ts\n * const key = await forge.server(123).sshKeys.create({\n * name: 'deploy-key',\n * key: 'ssh-rsa AAAA...',\n * });\n * ```\n */\n async create(data: CreateSshKeyData): Promise<ForgeSshKey> {\n const response = await this.client.post<SshKeyResponse>(this.basePath, data);\n return response.key;\n }\n\n /**\n * Delete an SSH key.\n *\n * @example\n * ```ts\n * await forge.server(123).sshKeys.delete(789);\n * ```\n */\n async delete(keyId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${keyId}`);\n }\n}\n","import type {\n CreateNginxTemplateData,\n ForgeNginxTemplate,\n HttpClient,\n NginxTemplateResponse,\n NginxTemplatesResponse,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing Nginx templates.\n */\nexport interface NginxTemplateListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of Nginx templates on a server.\n *\n * Access via `forge.server(id).nginxTemplates`.\n *\n * @example\n * ```ts\n * const templates = await forge.server(123).nginxTemplates.list();\n * ```\n */\nexport class NginxTemplatesCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n ) {\n super(client);\n }\n\n private get basePath(): string {\n return `/servers/${this.serverId}/nginx/templates`;\n }\n\n /**\n * List Nginx templates on this server.\n *\n * @example\n * ```ts\n * const templates = await forge.server(123).nginxTemplates.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.server(123).nginxTemplates.list({ page: 2 });\n * ```\n */\n async list(options: NginxTemplateListOptions = {}): Promise<ForgeNginxTemplate[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<NginxTemplatesResponse>(`${this.basePath}${query}`);\n return response.templates;\n }\n\n /**\n * Iterate over all Nginx templates across all pages.\n *\n * @example\n * ```ts\n * for await (const template of forge.server(123).nginxTemplates.all()) {\n * console.log(template);\n * }\n *\n * // Or collect all at once:\n * const templates = await forge.server(123).nginxTemplates.all().toArray();\n * ```\n */\n all(\n options: Omit<NginxTemplateListOptions, \"page\"> = {},\n ): AsyncPaginatedIterator<ForgeNginxTemplate> {\n return new AsyncPaginatedIterator<ForgeNginxTemplate>((page) =>\n this.list({ ...options, page }),\n );\n }\n\n /**\n * Get a specific Nginx template.\n *\n * @example\n * ```ts\n * const template = await forge.server(123).nginxTemplates.get(789);\n * ```\n */\n async get(templateId: number): Promise<ForgeNginxTemplate> {\n const response = await this.client.get<NginxTemplateResponse>(`${this.basePath}/${templateId}`);\n return response.template;\n }\n\n /**\n * Create a new Nginx template.\n *\n * @example\n * ```ts\n * const template = await forge.server(123).nginxTemplates.create({\n * name: 'Laravel Template',\n * content: 'server { ... }',\n * });\n * ```\n */\n async create(data: CreateNginxTemplateData): Promise<ForgeNginxTemplate> {\n const response = await this.client.post<NginxTemplateResponse>(this.basePath, data);\n return response.template;\n }\n\n /**\n * Update an existing Nginx template.\n *\n * @example\n * ```ts\n * const template = await forge.server(123).nginxTemplates.update(789, {\n * name: 'Updated Template',\n * content: 'server { ... }',\n * });\n * ```\n */\n async update(\n templateId: number,\n data: Partial<CreateNginxTemplateData>,\n ): Promise<ForgeNginxTemplate> {\n const response = await this.client.put<NginxTemplateResponse>(\n `${this.basePath}/${templateId}`,\n data,\n );\n return response.template;\n }\n\n /**\n * Delete a Nginx template.\n *\n * @example\n * ```ts\n * await forge.server(123).nginxTemplates.delete(789);\n * ```\n */\n async delete(templateId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${templateId}`);\n }\n}\n","import type {\n CreateServerData,\n ForgeServer,\n HttpClient,\n ServerResponse,\n ServersResponse,\n} from \"@studiometa/forge-api\";\n\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\nimport { matchByName } from \"../utils/name-matcher.ts\";\nimport { SitesCollection, SiteResource } from \"./sites.ts\";\nimport { DatabasesCollection } from \"./databases.ts\";\nimport { DatabaseUsersCollection } from \"./database-users.ts\";\nimport { DaemonsCollection } from \"./daemons.ts\";\nimport { BackupsCollection } from \"./backups.ts\";\nimport { ScheduledJobsCollection } from \"./scheduled-jobs.ts\";\nimport { MonitorsCollection } from \"./monitors.ts\";\nimport { FirewallRulesCollection } from \"./firewall-rules.ts\";\nimport { SshKeysCollection } from \"./ssh-keys.ts\";\nimport { NginxTemplatesCollection } from \"./nginx-templates.ts\";\nimport { BaseCollection } from \"./base.ts\";\n\n/**\n * A matched resource item with ID and name.\n */\nexport interface ResolveMatch {\n id: number;\n name: string;\n}\n\n/**\n * Result of a resolve operation.\n */\nexport interface ResolveResult {\n query: string;\n matches: ResolveMatch[];\n total: number;\n}\n\n/**\n * Options for listing servers.\n */\nexport interface ServerListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Collection of servers.\n *\n * Access via `forge.servers`.\n *\n * @example\n * ```ts\n * // List all servers\n * const servers = await forge.servers.list();\n *\n * // Get a specific server\n * const server = await forge.servers.get(123);\n *\n * // Create a new server\n * const server = await forge.servers.create({ ... });\n * ```\n */\nexport class ServersCollection extends BaseCollection {\n /** @internal */\n constructor(client: HttpClient) {\n super(client);\n }\n\n /**\n * List servers.\n *\n * @example\n * ```ts\n * const servers = await forge.servers.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.servers.list({ page: 2 });\n * ```\n */\n async list(options: ServerListOptions = {}): Promise<ForgeServer[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<ServersResponse>(`/servers${query}`);\n return response.servers;\n }\n\n /**\n * Iterate over all servers across all pages.\n *\n * @example\n * ```ts\n * for await (const server of forge.servers.all()) {\n * console.log(server);\n * }\n *\n * // Or collect all at once:\n * const servers = await forge.servers.all().toArray();\n * ```\n */\n all(options: Omit<ServerListOptions, \"page\"> = {}): AsyncPaginatedIterator<ForgeServer> {\n return new AsyncPaginatedIterator<ForgeServer>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific server by ID.\n *\n * @example\n * ```ts\n * const server = await forge.servers.get(123);\n * ```\n */\n async get(serverId: number): Promise<ForgeServer> {\n const response = await this.client.get<ServerResponse>(`/servers/${serverId}`);\n return response.server;\n }\n\n /**\n * Create a new server.\n *\n * @example\n * ```ts\n * const server = await forge.servers.create({\n * provider: 'ocean2',\n * credential_id: 1,\n * name: 'web-1',\n * type: 'app',\n * size: '01',\n * region: 'ams3',\n * });\n * ```\n */\n async create(data: CreateServerData): Promise<ForgeServer> {\n const response = await this.client.post<ServerResponse>(\"/servers\", data);\n return response.server;\n }\n\n /**\n * Update a server.\n *\n * @example\n * ```ts\n * await forge.servers.update(123, { name: 'web-1-renamed' });\n * ```\n */\n async update(serverId: number, data: Partial<CreateServerData>): Promise<ForgeServer> {\n const response = await this.client.put<ServerResponse>(`/servers/${serverId}`, data);\n return response.server;\n }\n\n /**\n * Delete a server.\n *\n * @example\n * ```ts\n * await forge.servers.delete(123);\n * ```\n */\n async delete(serverId: number): Promise<void> {\n await this.client.delete(`/servers/${serverId}`);\n }\n\n /**\n * Reboot a server.\n *\n * @example\n * ```ts\n * await forge.servers.reboot(123);\n * ```\n */\n async reboot(serverId: number): Promise<void> {\n await this.client.post(`/servers/${serverId}/reboot`);\n }\n\n /**\n * Find servers by name using case-insensitive partial matching.\n *\n * If exactly one server matches the query exactly, only that server is returned.\n * Otherwise all partial matches are returned.\n *\n * @param query - The search query to match against server names.\n * @returns Resolve result with matching servers.\n *\n * @example\n * ```ts\n * // Find servers matching \"prod\"\n * const result = await forge.servers.resolve('prod');\n * // → { query: 'prod', matches: [{ id: 725393, name: 'wilo-grove-prod' }], total: 1 }\n *\n * // Use the result to access a server\n * if (result.total === 1) {\n * const sites = await forge.server(result.matches[0].id).sites.list();\n * }\n * ```\n */\n async resolve(query: string): Promise<ResolveResult> {\n const servers = await this.list();\n const { exact, partial } = matchByName(servers, query, (s) => s.name);\n const matches = exact.length === 1 ? exact : partial;\n return {\n query,\n matches: matches.map((s) => ({ id: s.id, name: s.name })),\n total: matches.length,\n };\n }\n}\n\n/**\n * A specific server with nested resources.\n *\n * Access via `forge.server(id)`.\n *\n * @example\n * ```ts\n * // Access sites on a server\n * const sites = await forge.server(123).sites.list();\n *\n * // Access databases on a server\n * const dbs = await forge.server(123).databases.list();\n * ```\n */\nexport class ServerResource extends BaseCollection {\n /** Sites on this server. */\n readonly sites: SitesCollection;\n\n /** Databases on this server. */\n readonly databases: DatabasesCollection;\n\n /** Database users on this server. */\n readonly databaseUsers: DatabaseUsersCollection;\n\n /** Daemons (background processes) on this server. */\n readonly daemons: DaemonsCollection;\n\n /** Backup configurations on this server. */\n readonly backups: BackupsCollection;\n\n /** Scheduled jobs (cron jobs) on this server. */\n readonly scheduledJobs: ScheduledJobsCollection;\n\n /** Monitors on this server. */\n readonly monitors: MonitorsCollection;\n\n /** Firewall rules on this server. */\n readonly firewallRules: FirewallRulesCollection;\n\n /** SSH keys on this server. */\n readonly sshKeys: SshKeysCollection;\n\n /** Nginx templates on this server. */\n readonly nginxTemplates: NginxTemplatesCollection;\n\n /** @internal */\n constructor(\n client: HttpClient,\n private readonly serverId: number,\n ) {\n super(client);\n this.sites = new SitesCollection(client, serverId);\n this.databases = new DatabasesCollection(client, serverId);\n this.databaseUsers = new DatabaseUsersCollection(client, serverId);\n this.daemons = new DaemonsCollection(client, serverId);\n this.backups = new BackupsCollection(client, serverId);\n this.scheduledJobs = new ScheduledJobsCollection(client, serverId);\n this.monitors = new MonitorsCollection(client, serverId);\n this.firewallRules = new FirewallRulesCollection(client, serverId);\n this.sshKeys = new SshKeysCollection(client, serverId);\n this.nginxTemplates = new NginxTemplatesCollection(client, serverId);\n }\n\n /**\n * Access a specific site on this server, with nested resources.\n *\n * @example\n * ```ts\n * // Deploy a site\n * await forge.server(123).site(456).deploy();\n *\n * // Get environment variables\n * const env = await forge.server(123).site(456).env.get();\n * ```\n */\n site(siteId: number): SiteResource {\n return new SiteResource(this.client, this.serverId, siteId);\n }\n\n /**\n * Get this server's details.\n *\n * @example\n * ```ts\n * const server = await forge.server(123).get();\n * ```\n */\n async get(): Promise<ForgeServer> {\n const response = await this.client.get<ServerResponse>(`/servers/${this.serverId}`);\n return response.server;\n }\n\n /**\n * Reboot this server.\n *\n * @example\n * ```ts\n * await forge.server(123).reboot();\n * ```\n */\n async reboot(): Promise<void> {\n await this.client.post(`/servers/${this.serverId}/reboot`);\n }\n\n /**\n * Delete this server.\n *\n * @example\n * ```ts\n * await forge.server(123).delete();\n * ```\n */\n async delete(): Promise<void> {\n await this.client.delete(`/servers/${this.serverId}`);\n }\n}\n","import type {\n CreateRecipeData,\n ForgeRecipe,\n HttpClient,\n RecipeResponse,\n RecipesResponse,\n} from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing recipes.\n */\nexport interface RecipeListOptions {\n /** Page number to fetch (1-indexed). */\n page?: number;\n}\n\n/**\n * Options for running a recipe.\n */\nexport interface RunRecipeOptions {\n /** Server IDs to run the recipe on. */\n servers: number[];\n}\n\n/**\n * Collection of recipes.\n *\n * Access via `forge.recipes`.\n *\n * @example\n * ```ts\n * const recipes = await forge.recipes.list();\n * ```\n */\nexport class RecipesCollection extends BaseCollection {\n /** @internal */\n constructor(client: HttpClient) {\n super(client);\n }\n\n private get basePath(): string {\n return `/recipes`;\n }\n\n /**\n * List all recipes.\n *\n * @example\n * ```ts\n * const recipes = await forge.recipes.list();\n *\n * // Fetch a specific page:\n * const page2 = await forge.recipes.list({ page: 2 });\n * ```\n */\n async list(options: RecipeListOptions = {}): Promise<ForgeRecipe[]> {\n const query = options.page !== undefined ? `?page=${options.page}` : \"\";\n const response = await this.client.get<RecipesResponse>(`${this.basePath}${query}`);\n return response.recipes;\n }\n\n /**\n * Iterate over all recipes across all pages.\n *\n * @example\n * ```ts\n * for await (const recipe of forge.recipes.all()) {\n * console.log(recipe);\n * }\n *\n * // Or collect all at once:\n * const recipes = await forge.recipes.all().toArray();\n * ```\n */\n all(options: Omit<RecipeListOptions, \"page\"> = {}): AsyncPaginatedIterator<ForgeRecipe> {\n return new AsyncPaginatedIterator<ForgeRecipe>((page) => this.list({ ...options, page }));\n }\n\n /**\n * Get a specific recipe.\n *\n * @example\n * ```ts\n * const recipe = await forge.recipes.get(789);\n * ```\n */\n async get(recipeId: number): Promise<ForgeRecipe> {\n const response = await this.client.get<RecipeResponse>(`${this.basePath}/${recipeId}`);\n return response.recipe;\n }\n\n /**\n * Create a new recipe.\n *\n * @example\n * ```ts\n * const recipe = await forge.recipes.create({\n * name: 'Install Node',\n * user: 'root',\n * script: 'curl -fsSL https://deb.nodesource.com/setup_20.x | bash -',\n * });\n * ```\n */\n async create(data: CreateRecipeData): Promise<ForgeRecipe> {\n const response = await this.client.post<RecipeResponse>(this.basePath, data);\n return response.recipe;\n }\n\n /**\n * Delete a recipe.\n *\n * @example\n * ```ts\n * await forge.recipes.delete(789);\n * ```\n */\n async delete(recipeId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${recipeId}`);\n }\n\n /**\n * Run a recipe on one or more servers.\n *\n * @example\n * ```ts\n * await forge.recipes.run(789, { servers: [123, 456] });\n * ```\n */\n async run(recipeId: number, options: RunRecipeOptions): Promise<void> {\n await this.client.post(`${this.basePath}/${recipeId}/run`, options);\n }\n}\n","import type { ForgeOptions, ForgeUser, UserResponse } from \"@studiometa/forge-api\";\n\nimport { HttpClient } from \"@studiometa/forge-api\";\n\nimport { ServersCollection, ServerResource } from \"./resources/servers.ts\";\nimport { RecipesCollection } from \"./resources/recipes.ts\";\n\n/**\n * Laravel Forge TypeScript SDK.\n *\n * Provides a fluent, chainable API for managing Laravel Forge servers,\n * sites, deployments, and more.\n *\n * @example\n * ```ts\n * import { Forge } from '@studiometa/forge-sdk';\n *\n * const forge = new Forge('your-api-token');\n *\n * // List all servers\n * const servers = await forge.servers.list();\n *\n * // Deploy a site\n * await forge.server(123).site(456).deploy();\n *\n * // Get environment variables\n * const env = await forge.server(123).site(456).env.get();\n *\n * // Manage databases\n * const dbs = await forge.server(123).databases.list();\n * ```\n */\nexport class Forge {\n /** @internal */\n readonly client: HttpClient;\n\n /** Server operations (list, get, create, update, delete, reboot). */\n readonly servers: ServersCollection;\n\n /** Recipe operations (list, get, create, delete, run). */\n readonly recipes: RecipesCollection;\n\n /**\n * Create a new Forge SDK instance.\n *\n * @param token Your Laravel Forge API token.\n * @param options Optional configuration (custom fetch, base URL, rate limiting).\n *\n * @example\n * ```ts\n * // Basic usage\n * const forge = new Forge('your-api-token');\n *\n * // With custom options\n * const forge = new Forge('your-api-token', {\n * baseUrl: 'https://custom-forge-instance.com/api/v1',\n * });\n *\n * // With mock fetch for testing\n * const forge = new Forge('test-token', { fetch: mockFetch });\n * ```\n */\n constructor(token: string, options?: ForgeOptions) {\n this.client = new HttpClient({ token, ...options });\n this.servers = new ServersCollection(this.client);\n this.recipes = new RecipesCollection(this.client);\n }\n\n /**\n * Access a specific server by ID, with nested resources.\n *\n * Returns a `ServerResource` that provides access to sites, databases,\n * daemons, and other server-level resources.\n *\n * @param serverId The server ID.\n *\n * @example\n * ```ts\n * // List sites on a server\n * const sites = await forge.server(123).sites.list();\n *\n * // Access a specific site\n * const site = await forge.server(123).site(456);\n *\n * // Deploy a site\n * await forge.server(123).site(456).deploy();\n *\n * // Manage databases\n * const dbs = await forge.server(123).databases.list();\n * ```\n */\n server(serverId: number): ServerResource {\n return new ServerResource(this.client, serverId);\n }\n\n /**\n * Get the currently authenticated user.\n *\n * @example\n * ```ts\n * const user = await forge.user();\n * console.log(user.name, user.email);\n * ```\n */\n async user(): Promise<ForgeUser> {\n const response = await this.client.get<UserResponse>(\"/user\");\n return response.user;\n }\n}\n"],"mappings":"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"}
|
|
@@ -11,6 +11,21 @@ import { FirewallRulesCollection } from "./firewall-rules.ts";
|
|
|
11
11
|
import { SshKeysCollection } from "./ssh-keys.ts";
|
|
12
12
|
import { NginxTemplatesCollection } from "./nginx-templates.ts";
|
|
13
13
|
import { BaseCollection } from "./base.ts";
|
|
14
|
+
/**
|
|
15
|
+
* A matched resource item with ID and name.
|
|
16
|
+
*/
|
|
17
|
+
export interface ResolveMatch {
|
|
18
|
+
id: number;
|
|
19
|
+
name: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Result of a resolve operation.
|
|
23
|
+
*/
|
|
24
|
+
export interface ResolveResult {
|
|
25
|
+
query: string;
|
|
26
|
+
matches: ResolveMatch[];
|
|
27
|
+
total: number;
|
|
28
|
+
}
|
|
14
29
|
/**
|
|
15
30
|
* Options for listing servers.
|
|
16
31
|
*/
|
|
@@ -116,6 +131,28 @@ export declare class ServersCollection extends BaseCollection {
|
|
|
116
131
|
* ```
|
|
117
132
|
*/
|
|
118
133
|
reboot(serverId: number): Promise<void>;
|
|
134
|
+
/**
|
|
135
|
+
* Find servers by name using case-insensitive partial matching.
|
|
136
|
+
*
|
|
137
|
+
* If exactly one server matches the query exactly, only that server is returned.
|
|
138
|
+
* Otherwise all partial matches are returned.
|
|
139
|
+
*
|
|
140
|
+
* @param query - The search query to match against server names.
|
|
141
|
+
* @returns Resolve result with matching servers.
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```ts
|
|
145
|
+
* // Find servers matching "prod"
|
|
146
|
+
* const result = await forge.servers.resolve('prod');
|
|
147
|
+
* // → { query: 'prod', matches: [{ id: 725393, name: 'wilo-grove-prod' }], total: 1 }
|
|
148
|
+
*
|
|
149
|
+
* // Use the result to access a server
|
|
150
|
+
* if (result.total === 1) {
|
|
151
|
+
* const sites = await forge.server(result.matches[0].id).sites.list();
|
|
152
|
+
* }
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
resolve(query: string): Promise<ResolveResult>;
|
|
119
156
|
}
|
|
120
157
|
/**
|
|
121
158
|
* A specific server with nested resources.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"servers.d.ts","sourceRoot":"","sources":["../../src/resources/servers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,WAAW,EACX,UAAU,EAGX,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"servers.d.ts","sourceRoot":"","sources":["../../src/resources/servers.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { CreateSiteData, ForgeSite, HttpClient } from "@studiometa/forge-api";
|
|
2
2
|
import { AsyncPaginatedIterator } from "../pagination.ts";
|
|
3
|
+
import type { ResolveResult } from "./servers.ts";
|
|
3
4
|
import { DeploymentsCollection } from "./deployments.ts";
|
|
4
5
|
import { CertificatesCollection } from "./certificates.ts";
|
|
5
6
|
import { CommandsCollection } from "./commands.ts";
|
|
@@ -94,6 +95,23 @@ export declare class SitesCollection extends BaseCollection {
|
|
|
94
95
|
* ```
|
|
95
96
|
*/
|
|
96
97
|
delete(siteId: number): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* Find sites by domain name using case-insensitive partial matching.
|
|
100
|
+
*
|
|
101
|
+
* If exactly one site matches the query exactly, only that site is returned.
|
|
102
|
+
* Otherwise all partial matches are returned.
|
|
103
|
+
*
|
|
104
|
+
* @param query - The search query to match against site domain names.
|
|
105
|
+
* @returns Resolve result with matching sites.
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```ts
|
|
109
|
+
* // Find sites matching "example"
|
|
110
|
+
* const result = await forge.server(123).sites.resolve('example');
|
|
111
|
+
* // → { query: 'example', matches: [{ id: 456, name: 'example.com' }], total: 1 }
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
resolve(query: string): Promise<ResolveResult>;
|
|
97
115
|
}
|
|
98
116
|
/**
|
|
99
117
|
* A specific site with nested resources and actions.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sites.d.ts","sourceRoot":"","sources":["../../src/resources/sites.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,SAAS,EACT,UAAU,EAGX,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"sites.d.ts","sourceRoot":"","sources":["../../src/resources/sites.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result of a name matching operation.
|
|
3
|
+
*/
|
|
4
|
+
export interface NameMatch<T> {
|
|
5
|
+
exact: T[];
|
|
6
|
+
partial: T[];
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Match items by name using case-insensitive exact and partial matching.
|
|
10
|
+
*/
|
|
11
|
+
export declare function matchByName<T>(items: T[], query: string, getName: (item: T) => string): NameMatch<T>;
|
|
12
|
+
//# sourceMappingURL=name-matcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"name-matcher.d.ts","sourceRoot":"","sources":["../../src/utils/name-matcher.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,SAAS,CAAC,CAAC;IAC1B,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,OAAO,EAAE,CAAC,EAAE,CAAC;CACd;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAC3B,KAAK,EAAE,CAAC,EAAE,EACV,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,GAC3B,SAAS,CAAC,CAAC,CAAC,CAKd"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@studiometa/forge-sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "Laravel Forge TypeScript SDK — fluent, chainable, fully-typed API client",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"api-client",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"typecheck": "tsc --noEmit"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@studiometa/forge-api": "
|
|
47
|
+
"@studiometa/forge-api": "0.2.5"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@vitest/coverage-v8": "^4.1.0-beta.4",
|