@studiometa/forge-sdk 0.4.8 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -0
- package/dist/forge.d.ts +3 -0
- package/dist/forge.d.ts.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +96 -1
- package/dist/index.js.map +1 -1
- package/dist/resources/storage-providers.d.ts +89 -0
- package/dist/resources/storage-providers.d.ts.map +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -204,6 +204,25 @@ forge.server(id).php.enableOpcache();
|
|
|
204
204
|
forge.server(id).php.disableOpcache();
|
|
205
205
|
```
|
|
206
206
|
|
|
207
|
+
### Storage Providers
|
|
208
|
+
|
|
209
|
+
Storage providers are the organization's S3-compatible buckets for database backups.
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
forge.storageProviders.list();
|
|
213
|
+
forge.storageProviders.get(providerId);
|
|
214
|
+
forge.storageProviders.create({
|
|
215
|
+
name: "Backups",
|
|
216
|
+
provider: "custom", // "s3", "spaces", "hetzner", "ovh", "scaleway" or "custom"
|
|
217
|
+
endpoint: "https://s3.example.com",
|
|
218
|
+
region: "eu-west-1",
|
|
219
|
+
bucket: "my-bucket",
|
|
220
|
+
access_key: "AKIA...",
|
|
221
|
+
secret_key: process.env.S3_SECRET_KEY,
|
|
222
|
+
});
|
|
223
|
+
forge.storageProviders.delete(providerId);
|
|
224
|
+
```
|
|
225
|
+
|
|
207
226
|
### User
|
|
208
227
|
|
|
209
228
|
```typescript
|
package/dist/forge.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { ForgeOptions, UserAttributes } from "@studiometa/forge-api";
|
|
|
2
2
|
import { HttpClient } from "@studiometa/forge-api";
|
|
3
3
|
import { ServersCollection, ServerResource } from "./resources/servers.ts";
|
|
4
4
|
import { RecipesCollection } from "./resources/recipes.ts";
|
|
5
|
+
import { StorageProvidersCollection } from "./resources/storage-providers.ts";
|
|
5
6
|
/**
|
|
6
7
|
* Laravel Forge TypeScript SDK.
|
|
7
8
|
*
|
|
@@ -36,6 +37,8 @@ export declare class Forge {
|
|
|
36
37
|
readonly servers: ServersCollection;
|
|
37
38
|
/** Recipe operations (list, get, create, delete, run). */
|
|
38
39
|
readonly recipes: RecipesCollection;
|
|
40
|
+
/** Storage provider operations (list, get, create, delete), used by database backups. */
|
|
41
|
+
readonly storageProviders: StorageProvidersCollection;
|
|
39
42
|
/**
|
|
40
43
|
* Create a new Forge SDK instance.
|
|
41
44
|
*
|
package/dist/forge.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forge.d.ts","sourceRoot":"","sources":["../src/forge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAmB,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE3F,OAAO,EAAE,UAAU,EAAkB,MAAM,uBAAuB,CAAC;AAEnE,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"forge.d.ts","sourceRoot":"","sources":["../src/forge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAmB,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE3F,OAAO,EAAE,UAAU,EAAkB,MAAM,uBAAuB,CAAC;AAEnE,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AAE9E;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,KAAK;IAChB,gBAAgB;IAChB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAE5B,2DAA2D;IAC3D,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAElC,qEAAqE;IACrE,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;IAEpC,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;IAEpC,yFAAyF;IACzF,QAAQ,CAAC,gBAAgB,EAAE,0BAA0B,CAAC;IAEtD;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,YAAY,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,EAM1E;IAED;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,CAEvC;IAED;;;;;;;;OAQG;IACG,IAAI,IAAI,OAAO,CAAC,cAAc,GAAG;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAGrD;CACF"}
|
package/dist/index.d.ts
CHANGED
|
@@ -37,10 +37,12 @@ export { ServicesCollection, RESTARTABLE_SERVICES } from "./resources/services.t
|
|
|
37
37
|
export type { RestartableService, RestartServiceOptions, ServiceStatus, } from "./resources/services.ts";
|
|
38
38
|
export { SshKeysCollection } from "./resources/ssh-keys.ts";
|
|
39
39
|
export type { SshKeyListOptions } from "./resources/ssh-keys.ts";
|
|
40
|
+
export { StorageProvidersCollection } from "./resources/storage-providers.ts";
|
|
41
|
+
export type { StorageProviderListOptions } from "./resources/storage-providers.ts";
|
|
40
42
|
export { SiteEnvResource, SiteNginxResource, SiteResource, SitesCollection, } from "./resources/sites.ts";
|
|
41
43
|
export type { SiteListOptions } from "./resources/sites.ts";
|
|
42
44
|
export type { JsonApiDocument, JsonApiListDocument, JsonApiResource, JsonApiPaginationLinks, JsonApiPaginationMeta, } from "@studiometa/forge-api";
|
|
43
45
|
export { unwrapDocument, unwrapListDocument, unwrapResource } from "@studiometa/forge-api";
|
|
44
|
-
export type { UserAttributes, ServerAttributes, SiteAttributes, DeploymentAttributes, DeploymentCommit, DeploymentOutputAttributes, DeploymentScriptAttributes, DatabaseAttributes, DatabaseUserAttributes, BackgroundProcessAttributes, CertificateAttributes, FirewallRuleAttributes, SshKeyAttributes, SecurityRuleAttributes, RedirectRuleAttributes, MonitorAttributes, NginxTemplateAttributes, RecipeAttributes, ScheduledJobAttributes, CommandAttributes, BackupConfigAttributes, BackupAttributes, OrganizationAttributes, } from "@studiometa/forge-api";
|
|
45
|
-
export type { CreateBackupConfigData, CreateCertificateData, CreateCommandData, CreateDaemonData, CreateDatabaseData, CreateDatabaseUserData, CreateFirewallRuleData, CreateMonitorData, CreateNginxTemplateData, CreateRecipeData, CreateRedirectRuleData, CreateScheduledJobData, CreateSecurityRuleData, CreateServerData, CreateSiteData, CreateSshKeyData, ForgeOptions, } from "@studiometa/forge-api";
|
|
46
|
+
export type { UserAttributes, ServerAttributes, SiteAttributes, DeploymentAttributes, DeploymentCommit, DeploymentOutputAttributes, DeploymentScriptAttributes, DatabaseAttributes, DatabaseUserAttributes, BackgroundProcessAttributes, CertificateAttributes, FirewallRuleAttributes, SshKeyAttributes, SecurityRuleAttributes, RedirectRuleAttributes, MonitorAttributes, NginxTemplateAttributes, RecipeAttributes, ScheduledJobAttributes, CommandAttributes, BackupConfigAttributes, BackupAttributes, StorageProviderAttributes, OrganizationAttributes, } from "@studiometa/forge-api";
|
|
47
|
+
export type { CreateBackupConfigData, CreateCertificateData, CreateCommandData, CreateDaemonData, CreateDatabaseData, CreateDatabaseUserData, CreateFirewallRuleData, CreateMonitorData, CreateNginxTemplateData, CreateRecipeData, CreateRedirectRuleData, CreateScheduledJobData, CreateSecurityRuleData, CreateServerData, CreateSiteData, CreateSshKeyData, CreateStorageProviderData, ForgeOptions, } from "@studiometa/forge-api";
|
|
46
48
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -2405,6 +2405,98 @@ var RecipesCollection = class extends BaseCollection {
|
|
|
2405
2405
|
}
|
|
2406
2406
|
};
|
|
2407
2407
|
//#endregion
|
|
2408
|
+
//#region src/resources/storage-providers.ts
|
|
2409
|
+
/**
|
|
2410
|
+
* Collection of storage providers: the S3-compatible buckets that database backups use.
|
|
2411
|
+
*
|
|
2412
|
+
* Access via `forge.storageProviders`.
|
|
2413
|
+
*
|
|
2414
|
+
* @example
|
|
2415
|
+
* ```ts
|
|
2416
|
+
* const providers = await forge.storageProviders.list();
|
|
2417
|
+
* ```
|
|
2418
|
+
*/
|
|
2419
|
+
var StorageProvidersCollection = class extends BaseCollection {
|
|
2420
|
+
/** @internal */
|
|
2421
|
+
get basePath() {
|
|
2422
|
+
return `/orgs/${this.orgSlug}/storage-providers`;
|
|
2423
|
+
}
|
|
2424
|
+
/**
|
|
2425
|
+
* List storage providers.
|
|
2426
|
+
*
|
|
2427
|
+
* @example
|
|
2428
|
+
* ```ts
|
|
2429
|
+
* const providers = await forge.storageProviders.list();
|
|
2430
|
+
*
|
|
2431
|
+
* // Fetch a specific cursor page:
|
|
2432
|
+
* const page2 = await forge.storageProviders.list({ cursor: 'next-cursor-value' });
|
|
2433
|
+
* ```
|
|
2434
|
+
*/
|
|
2435
|
+
async list(options = {}) {
|
|
2436
|
+
const query = options.cursor !== void 0 ? `?page[cursor]=${options.cursor}` : "";
|
|
2437
|
+
return unwrapListDocument$1(await this.client.get(`${this.basePath}${query}`));
|
|
2438
|
+
}
|
|
2439
|
+
/**
|
|
2440
|
+
* Iterate over all storage providers across all pages.
|
|
2441
|
+
*
|
|
2442
|
+
* @example
|
|
2443
|
+
* ```ts
|
|
2444
|
+
* const providers = await forge.storageProviders.all().toArray();
|
|
2445
|
+
* ```
|
|
2446
|
+
*/
|
|
2447
|
+
all() {
|
|
2448
|
+
return new AsyncPaginatedIterator(async (cursor) => {
|
|
2449
|
+
const query = cursor !== null ? `?page[cursor]=${cursor}` : "";
|
|
2450
|
+
const response = await this.client.get(`${this.basePath}${query}`);
|
|
2451
|
+
return {
|
|
2452
|
+
items: unwrapListDocument$1(response),
|
|
2453
|
+
nextCursor: response.meta.next_cursor ?? null
|
|
2454
|
+
};
|
|
2455
|
+
});
|
|
2456
|
+
}
|
|
2457
|
+
/**
|
|
2458
|
+
* Get a specific storage provider.
|
|
2459
|
+
*
|
|
2460
|
+
* @example
|
|
2461
|
+
* ```ts
|
|
2462
|
+
* const provider = await forge.storageProviders.get(12);
|
|
2463
|
+
* ```
|
|
2464
|
+
*/
|
|
2465
|
+
async get(providerId) {
|
|
2466
|
+
return unwrapDocument$1(await this.client.get(`${this.basePath}/${providerId}`));
|
|
2467
|
+
}
|
|
2468
|
+
/**
|
|
2469
|
+
* Create a storage provider.
|
|
2470
|
+
*
|
|
2471
|
+
* @example
|
|
2472
|
+
* ```ts
|
|
2473
|
+
* const provider = await forge.storageProviders.create({
|
|
2474
|
+
* name: 'Backups',
|
|
2475
|
+
* provider: 'custom',
|
|
2476
|
+
* endpoint: 'https://s3.example.com',
|
|
2477
|
+
* region: 'eu-west-1',
|
|
2478
|
+
* bucket: 'my-bucket',
|
|
2479
|
+
* access_key: 'AKIA...',
|
|
2480
|
+
* secret_key: process.env.S3_SECRET_KEY,
|
|
2481
|
+
* });
|
|
2482
|
+
* ```
|
|
2483
|
+
*/
|
|
2484
|
+
async create(data) {
|
|
2485
|
+
return unwrapDocument$1(await this.client.post(this.basePath, data));
|
|
2486
|
+
}
|
|
2487
|
+
/**
|
|
2488
|
+
* Delete a storage provider. Forge refuses when a backup configuration uses it.
|
|
2489
|
+
*
|
|
2490
|
+
* @example
|
|
2491
|
+
* ```ts
|
|
2492
|
+
* await forge.storageProviders.delete(12);
|
|
2493
|
+
* ```
|
|
2494
|
+
*/
|
|
2495
|
+
async delete(providerId) {
|
|
2496
|
+
await this.client.delete(`${this.basePath}/${providerId}`);
|
|
2497
|
+
}
|
|
2498
|
+
};
|
|
2499
|
+
//#endregion
|
|
2408
2500
|
//#region src/forge.ts
|
|
2409
2501
|
/**
|
|
2410
2502
|
* Laravel Forge TypeScript SDK.
|
|
@@ -2440,6 +2532,8 @@ var Forge = class {
|
|
|
2440
2532
|
servers;
|
|
2441
2533
|
/** Recipe operations (list, get, create, delete, run). */
|
|
2442
2534
|
recipes;
|
|
2535
|
+
/** Storage provider operations (list, get, create, delete), used by database backups. */
|
|
2536
|
+
storageProviders;
|
|
2443
2537
|
/**
|
|
2444
2538
|
* Create a new Forge SDK instance.
|
|
2445
2539
|
*
|
|
@@ -2469,6 +2563,7 @@ var Forge = class {
|
|
|
2469
2563
|
this.organizationSlug = organizationSlug;
|
|
2470
2564
|
this.servers = new ServersCollection(this.client, organizationSlug);
|
|
2471
2565
|
this.recipes = new RecipesCollection(this.client, organizationSlug);
|
|
2566
|
+
this.storageProviders = new StorageProvidersCollection(this.client, organizationSlug);
|
|
2472
2567
|
}
|
|
2473
2568
|
/**
|
|
2474
2569
|
* Access a specific server by ID, with nested resources.
|
|
@@ -2510,6 +2605,6 @@ var Forge = class {
|
|
|
2510
2605
|
}
|
|
2511
2606
|
};
|
|
2512
2607
|
//#endregion
|
|
2513
|
-
export { AsyncPaginatedIterator, BackupsCollection, BaseCollection, CertificatesCollection, CommandsCollection, DaemonsCollection, DatabaseUsersCollection, DatabasesCollection, DeploymentsCollection, FirewallRulesCollection, Forge, MonitorsCollection, NginxTemplatesCollection, PHP_CONFIG_TYPES, PhpResource, RESTARTABLE_SERVICES, RecipesCollection, RedirectRulesCollection, ScheduledJobsCollection, SecurityRulesCollection, ServerResource, ServersCollection, ServicesCollection, SiteEnvResource, SiteNginxResource, SiteResource, SitesCollection, SshKeysCollection, unwrapDocument, unwrapListDocument, unwrapResource };
|
|
2608
|
+
export { AsyncPaginatedIterator, BackupsCollection, BaseCollection, CertificatesCollection, CommandsCollection, DaemonsCollection, DatabaseUsersCollection, DatabasesCollection, DeploymentsCollection, FirewallRulesCollection, Forge, MonitorsCollection, NginxTemplatesCollection, PHP_CONFIG_TYPES, PhpResource, RESTARTABLE_SERVICES, RecipesCollection, RedirectRulesCollection, ScheduledJobsCollection, SecurityRulesCollection, ServerResource, ServersCollection, ServicesCollection, SiteEnvResource, SiteNginxResource, SiteResource, SitesCollection, SshKeysCollection, StorageProvidersCollection, unwrapDocument, unwrapListDocument, unwrapResource };
|
|
2514
2609
|
|
|
2515
2610
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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/services.ts","../src/resources/php.ts","../src/resources/servers.ts","../src/resources/recipes.ts","../src/forge.ts"],"sourcesContent":["/**\n * Function that fetches a page of results using cursor-based pagination.\n * Pass `null` for the first page, or a cursor string for subsequent pages.\n */\nexport type PageFetcher<T> = (\n cursor: string | null,\n) => Promise<{ items: T[]; nextCursor: string | null }>;\n\n/**\n * Async paginated iterator that auto-fetches all pages using cursor-based pagination.\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\n constructor(fetchPage: PageFetcher<T>) {\n this.fetchPage = fetchPage;\n }\n\n async *[Symbol.asyncIterator](): AsyncGenerator<T, void, undefined> {\n let cursor: string | null = null;\n let hasMore = true;\n\n while (hasMore) {\n const { items, nextCursor } = await this.fetchPage(cursor);\n\n for (const item of items) {\n yield item;\n }\n\n if (nextCursor) {\n cursor = nextCursor;\n } else {\n hasMore = false;\n }\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 shared `client` and `orgSlug` properties to avoid duplication across all collection classes.\n */\nexport abstract class BaseCollection {\n protected readonly client: HttpClient;\n protected readonly orgSlug: string;\n\n constructor(client: HttpClient, orgSlug: string) {\n this.client = client;\n this.orgSlug = orgSlug;\n }\n}\n","import type {\n HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n DeploymentAttributes,\n DeploymentOutputAttributes,\n DeploymentScriptAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/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 cursor page:\n * const page2 = await forge.server(123).site(456).deployments.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(\n options: DeploymentListOptions = {},\n ): Promise<Array<DeploymentAttributes & { id: number }>> {\n const params = new URLSearchParams({ sort: \"-created_at\" });\n if (options.cursor !== undefined) {\n params.set(\"page[cursor]\", options.cursor);\n }\n const response = await this.client.get<JsonApiListDocument<DeploymentAttributes>>(\n `${this.basePath}?${params.toString()}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<DeploymentAttributes & { id: number }> {\n return new AsyncPaginatedIterator<DeploymentAttributes & { id: number }>(async (cursor) => {\n const params = \"?sort=-created_at\" + (cursor !== null ? `&page[cursor]=${cursor}` : \"\");\n const response = await this.client.get<JsonApiListDocument<DeploymentAttributes>>(\n `${this.basePath}${params}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<DeploymentAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<DeploymentAttributes>>(\n `${this.basePath}/${deploymentId}`,\n );\n return unwrapDocument(response);\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 const response = await this.client.get<JsonApiDocument<DeploymentOutputAttributes>>(\n `${this.basePath}/${deploymentId}/output`,\n );\n return unwrapDocument(response).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 const response = await this.client.get<JsonApiDocument<DeploymentScriptAttributes>>(\n `/orgs/${this.orgSlug}/servers/${this.serverId}/sites/${this.siteId}/deployments/script`,\n );\n return unwrapDocument(response).content;\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(\n `/orgs/${this.orgSlug}/servers/${this.serverId}/sites/${this.siteId}/deployments/script`,\n { content },\n );\n }\n}\n","import type {\n CreateCertificateData,\n HttpClient,\n JsonApiDocument,\n CertificateAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument } from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\n\n/**\n * SSL certificates for a site, accessed per-domain.\n *\n * In v2, certificates are a singular sub-resource of a domain:\n * `/orgs/{org}/servers/{server}/sites/{site}/domains/{domain}/certificate`\n *\n * Access via `forge.server(id).site(id).certificates`.\n *\n * @example\n * ```ts\n * const cert = await forge.server(123).site(456).certificates.get(789);\n * ```\n */\nexport class CertificatesCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n orgSlug: string,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client, orgSlug);\n }\n\n private domainPath(domainId: number): string {\n return `/orgs/${this.orgSlug}/servers/${this.serverId}/sites/${this.siteId}/domains/${domainId}/certificate`;\n }\n\n /**\n * Get the certificate for a domain.\n *\n * @example\n * ```ts\n * const cert = await forge.server(123).site(456).certificates.get(789);\n * ```\n */\n async get(domainId: number): Promise<CertificateAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<CertificateAttributes>>(\n this.domainPath(domainId),\n );\n return unwrapDocument(response);\n }\n\n /**\n * Create a certificate for a domain.\n *\n * @example\n * ```ts\n * const cert = await forge.server(123).site(456).certificates.create(789, {\n * type: 'letsencrypt',\n * });\n * ```\n */\n async create(\n domainId: number,\n data: CreateCertificateData,\n ): Promise<CertificateAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<CertificateAttributes>>(\n this.domainPath(domainId),\n data,\n );\n return unwrapDocument(response);\n }\n\n /**\n * Delete the certificate for a domain.\n *\n * @example\n * ```ts\n * await forge.server(123).site(456).certificates.delete(789);\n * ```\n */\n async delete(domainId: number): Promise<void> {\n await this.client.delete(this.domainPath(domainId));\n }\n\n /**\n * Activate the certificate for a domain.\n *\n * @example\n * ```ts\n * await forge.server(123).site(456).certificates.activate(789);\n * ```\n */\n async activate(domainId: number): Promise<void> {\n await this.client.post(`${this.domainPath(domainId)}/actions`, { action: \"activate\" });\n }\n}\n","import type {\n CreateCommandData,\n HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n CommandAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/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 cursor page:\n * const page2 = await forge.server(123).site(456).commands.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(options: CommandListOptions = {}): Promise<Array<CommandAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<CommandAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<CommandAttributes & { id: number }> {\n return new AsyncPaginatedIterator<CommandAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<CommandAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<CommandAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<CommandAttributes>>(\n `${this.basePath}/${commandId}`,\n );\n return unwrapDocument(response);\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<CommandAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<CommandAttributes>>(\n this.basePath,\n data,\n );\n return unwrapDocument(response);\n }\n}\n","import type {\n CreateSecurityRuleData,\n HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n SecurityRuleAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/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 cursor page:\n * const page2 = await forge.server(123).site(456).securityRules.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(\n options: SecurityRuleListOptions = {},\n ): Promise<Array<SecurityRuleAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<SecurityRuleAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<SecurityRuleAttributes & { id: number }> {\n return new AsyncPaginatedIterator<SecurityRuleAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<SecurityRuleAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<SecurityRuleAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<SecurityRuleAttributes>>(\n `${this.basePath}/${ruleId}`,\n );\n return unwrapDocument(response);\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<SecurityRuleAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<SecurityRuleAttributes>>(\n this.basePath,\n data,\n );\n return unwrapDocument(response);\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 HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n RedirectRuleAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/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 cursor page:\n * const page2 = await forge.server(123).site(456).redirectRules.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(\n options: RedirectRuleListOptions = {},\n ): Promise<Array<RedirectRuleAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<RedirectRuleAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<RedirectRuleAttributes & { id: number }> {\n return new AsyncPaginatedIterator<RedirectRuleAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<RedirectRuleAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<RedirectRuleAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<RedirectRuleAttributes>>(\n `${this.basePath}/${ruleId}`,\n );\n return unwrapDocument(response);\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<RedirectRuleAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<RedirectRuleAttributes>>(\n this.basePath,\n data,\n );\n return unwrapDocument(response);\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 HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n SiteAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/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 cursor page:\n * const page2 = await forge.server(123).sites.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(options: SiteListOptions = {}): Promise<Array<SiteAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<SiteAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<SiteAttributes & { id: number }> {\n return new AsyncPaginatedIterator<SiteAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<SiteAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<SiteAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<SiteAttributes>>(\n `/orgs/${this.orgSlug}/sites/${siteId}`,\n );\n return unwrapDocument(response);\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 * type: 'php',\n * name: 'example.com',\n * directory: '/public',\n * });\n * ```\n */\n async create(data: CreateSiteData): Promise<SiteAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<SiteAttributes>>(this.basePath, data);\n return unwrapDocument(response);\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(\n siteId: number,\n data: Partial<CreateSiteData>,\n ): Promise<SiteAttributes & { id: number }> {\n const response = await this.client.put<JsonApiDocument<SiteAttributes>>(\n `${this.basePath}/${siteId}`,\n data,\n );\n return unwrapDocument(response);\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 orgSlug: string,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client, orgSlug);\n this.deployments = new DeploymentsCollection(client, orgSlug, serverId, siteId);\n this.certificates = new CertificatesCollection(client, orgSlug, serverId, siteId);\n this.env = new SiteEnvResource(client, orgSlug, serverId, siteId);\n this.nginx = new SiteNginxResource(client, orgSlug, serverId, siteId);\n this.commands = new CommandsCollection(client, orgSlug, serverId, siteId);\n this.securityRules = new SecurityRulesCollection(client, orgSlug, serverId, siteId);\n this.redirectRules = new RedirectRulesCollection(client, orgSlug, serverId, siteId);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/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<SiteAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<SiteAttributes>>(\n `/orgs/${this.orgSlug}/sites/${this.siteId}`,\n );\n return unwrapDocument(response);\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}/deployments/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 orgSlug: string,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/servers/${this.serverId}/sites/${this.siteId}/environment`;\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, { environment: 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 orgSlug: string,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/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, { config: content });\n }\n}\n","import type {\n CreateDatabaseData,\n HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n DatabaseAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/servers/${this.serverId}/database/schemas`;\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 cursor page:\n * const page2 = await forge.server(123).databases.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(\n options: DatabaseListOptions = {},\n ): Promise<Array<DatabaseAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<DatabaseAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<DatabaseAttributes & { id: number }> {\n return new AsyncPaginatedIterator<DatabaseAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<DatabaseAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<DatabaseAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<DatabaseAttributes>>(\n `${this.basePath}/${databaseId}`,\n );\n return unwrapDocument(response);\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<DatabaseAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<DatabaseAttributes>>(\n this.basePath,\n data,\n );\n return unwrapDocument(response);\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 HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n DatabaseUserAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/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 cursor page:\n * const page2 = await forge.server(123).databaseUsers.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(\n options: DatabaseUserListOptions = {},\n ): Promise<Array<DatabaseUserAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<DatabaseUserAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<DatabaseUserAttributes & { id: number }> {\n return new AsyncPaginatedIterator<DatabaseUserAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<DatabaseUserAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<DatabaseUserAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<DatabaseUserAttributes>>(\n `${this.basePath}/${userId}`,\n );\n return unwrapDocument(response);\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<DatabaseUserAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<DatabaseUserAttributes>>(\n this.basePath,\n data,\n );\n return unwrapDocument(response);\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 HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n BackgroundProcessAttributes,\n BackgroundProcessLogAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/servers/${this.serverId}/background-processes`;\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 cursor page:\n * const page2 = await forge.server(123).daemons.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(\n options: DaemonListOptions = {},\n ): Promise<Array<BackgroundProcessAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<BackgroundProcessAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<BackgroundProcessAttributes & { id: number }> {\n return new AsyncPaginatedIterator<BackgroundProcessAttributes & { id: number }>(\n async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<BackgroundProcessAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n },\n );\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<BackgroundProcessAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<BackgroundProcessAttributes>>(\n `${this.basePath}/${daemonId}`,\n );\n return unwrapDocument(response);\n }\n\n /**\n * Get the log output of a daemon.\n *\n * @example\n * ```ts\n * const log = await forge.server(123).daemons.log(789);\n * ```\n */\n async log(daemonId: number): Promise<string> {\n const response = await this.client.get<JsonApiDocument<BackgroundProcessLogAttributes>>(\n `${this.basePath}/${daemonId}/log`,\n );\n return unwrapDocument(response).content;\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<BackgroundProcessAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<BackgroundProcessAttributes>>(\n this.basePath,\n data,\n );\n return unwrapDocument(response);\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 CreateBackupConfigData,\n HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n BackupConfigAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/servers/${this.serverId}/database/backups`;\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 cursor page:\n * const page2 = await forge.server(123).backups.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(\n options: BackupConfigListOptions = {},\n ): Promise<Array<BackupConfigAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<BackupConfigAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<BackupConfigAttributes & { id: number }> {\n return new AsyncPaginatedIterator<BackupConfigAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<BackupConfigAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<BackupConfigAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<BackupConfigAttributes>>(\n `${this.basePath}/${backupId}`,\n );\n return unwrapDocument(response);\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<BackupConfigAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<BackupConfigAttributes>>(\n this.basePath,\n data,\n );\n return unwrapDocument(response);\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 HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n ScheduledJobAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/servers/${this.serverId}/scheduled-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 cursor page:\n * const page2 = await forge.server(123).scheduledJobs.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(\n options: ScheduledJobListOptions = {},\n ): Promise<Array<ScheduledJobAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<ScheduledJobAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<ScheduledJobAttributes & { id: number }> {\n return new AsyncPaginatedIterator<ScheduledJobAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<ScheduledJobAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<ScheduledJobAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<ScheduledJobAttributes>>(\n `${this.basePath}/${jobId}`,\n );\n return unwrapDocument(response);\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<ScheduledJobAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<ScheduledJobAttributes>>(\n this.basePath,\n data,\n );\n return unwrapDocument(response);\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 HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n MonitorAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/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 cursor page:\n * const page2 = await forge.server(123).monitors.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(options: MonitorListOptions = {}): Promise<Array<MonitorAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<MonitorAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<MonitorAttributes & { id: number }> {\n return new AsyncPaginatedIterator<MonitorAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<MonitorAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<MonitorAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<MonitorAttributes>>(\n `${this.basePath}/${monitorId}`,\n );\n return unwrapDocument(response);\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<MonitorAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<MonitorAttributes>>(\n this.basePath,\n data,\n );\n return unwrapDocument(response);\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 HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n FirewallRuleAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/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 cursor page:\n * const page2 = await forge.server(123).firewallRules.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(\n options: FirewallRuleListOptions = {},\n ): Promise<Array<FirewallRuleAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<FirewallRuleAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<FirewallRuleAttributes & { id: number }> {\n return new AsyncPaginatedIterator<FirewallRuleAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<FirewallRuleAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<FirewallRuleAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<FirewallRuleAttributes>>(\n `${this.basePath}/${ruleId}`,\n );\n return unwrapDocument(response);\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<FirewallRuleAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<FirewallRuleAttributes>>(\n this.basePath,\n data,\n );\n return unwrapDocument(response);\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 HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n SshKeyAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/servers/${this.serverId}/ssh-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 cursor page:\n * const page2 = await forge.server(123).sshKeys.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(options: SshKeyListOptions = {}): Promise<Array<SshKeyAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<SshKeyAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<SshKeyAttributes & { id: number }> {\n return new AsyncPaginatedIterator<SshKeyAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<SshKeyAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<SshKeyAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<SshKeyAttributes>>(\n `${this.basePath}/${keyId}`,\n );\n return unwrapDocument(response);\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<SshKeyAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<SshKeyAttributes>>(this.basePath, data);\n return unwrapDocument(response);\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 HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n NginxTemplateAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/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 cursor page:\n * const page2 = await forge.server(123).nginxTemplates.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(\n options: NginxTemplateListOptions = {},\n ): Promise<Array<NginxTemplateAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<NginxTemplateAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<NginxTemplateAttributes & { id: number }> {\n return new AsyncPaginatedIterator<NginxTemplateAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<NginxTemplateAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\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<NginxTemplateAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<NginxTemplateAttributes>>(\n `${this.basePath}/${templateId}`,\n );\n return unwrapDocument(response);\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<NginxTemplateAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<NginxTemplateAttributes>>(\n this.basePath,\n data,\n );\n return unwrapDocument(response);\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<NginxTemplateAttributes & { id: number }> {\n const response = await this.client.put<JsonApiDocument<NginxTemplateAttributes>>(\n `${this.basePath}/${templateId}`,\n data,\n );\n return unwrapDocument(response);\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 { HttpClient, JsonApiDocument, ServerAttributes } from \"@studiometa/forge-api\";\n\nimport { unwrapDocument } from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\n\n/**\n * The six restartable services exposed by the Forge v2 API.\n */\nexport const RESTARTABLE_SERVICES = [\n \"nginx\",\n \"php\",\n \"mysql\",\n \"postgres\",\n \"redis\",\n \"supervisor\",\n] as const;\n\nexport type RestartableService = (typeof RESTARTABLE_SERVICES)[number];\n\n/**\n * A single service availability row.\n *\n * `available` is a documented heuristic derived from the server object, since\n * the API has no services GET endpoint.\n */\nexport interface ServiceStatus {\n service: string;\n available: boolean;\n detail: string | null;\n}\n\n/**\n * Options for restarting a service.\n */\nexport interface RestartServiceOptions {\n /** PHP version (e.g. \"php83\") — required when restarting the php service. */\n version?: string;\n}\n\n/**\n * Services on a server — list availability and restart individual services.\n *\n * Access via `forge.server(id).services`.\n *\n * The v2 API has no GET endpoint for services, so `list()` derives availability\n * from the server object. Restarting maps to the API action `reboot`.\n *\n * @example\n * ```ts\n * // List services and their availability\n * const services = await forge.server(123).services.list();\n *\n * // Restart nginx\n * await forge.server(123).services.restart('nginx');\n *\n * // Restart php (version required)\n * await forge.server(123).services.restart('php', { version: 'php83' });\n * ```\n */\nexport class ServicesCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/servers/${this.serverId}`;\n }\n\n /**\n * List services on this server with a derived availability flag.\n *\n * @example\n * ```ts\n * const services = await forge.server(123).services.list();\n * // → [{ service: 'nginx', available: true, detail: null }, ...]\n * ```\n */\n async list(): Promise<ServiceStatus[]> {\n const response = await this.client.get<JsonApiDocument<ServerAttributes>>(this.basePath);\n const server = unwrapDocument(response);\n\n const databaseType = server.database_type ?? \"\";\n const isMysql = databaseType.startsWith(\"mysql\") || databaseType.startsWith(\"mariadb\");\n const isPostgres = databaseType.startsWith(\"postgres\");\n\n return [\n { service: \"nginx\", available: true, detail: null },\n { service: \"php\", available: server.php_version !== null, detail: server.php_version },\n { service: \"mysql\", available: isMysql, detail: isMysql ? server.database_type : null },\n {\n service: \"postgres\",\n available: isPostgres,\n detail: isPostgres ? server.database_type : null,\n },\n { service: \"redis\", available: server.redis_status !== null, detail: server.redis_status },\n { service: \"supervisor\", available: true, detail: null },\n ];\n }\n\n /**\n * Restart a service on this server.\n *\n * Maps to the API action `reboot`. The php service requires a `version`.\n *\n * @example\n * ```ts\n * await forge.server(123).services.restart('nginx');\n * await forge.server(123).services.restart('php', { version: 'php83' });\n * ```\n */\n async restart(service: string, options: RestartServiceOptions = {}): Promise<void> {\n if (!(RESTARTABLE_SERVICES as readonly string[]).includes(service)) {\n throw new Error(\n `Invalid service \"${service}\". Valid services: ${RESTARTABLE_SERVICES.join(\", \")}.`,\n );\n }\n\n if (service === \"php\" && !options.version) {\n throw new Error('The \"php\" service requires a version (e.g. \"php83\") to restart.');\n }\n\n await this.client.post(`${this.basePath}/services/${service}/actions`, {\n action: \"reboot\",\n ...(options.version ? { version: options.version } : {}),\n });\n }\n}\n","import type {\n HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n PhpConfigAttributes,\n PhpMaxExecutionTimeAttributes,\n PhpMaxUploadSizeAttributes,\n PhpOpcacheAttributes,\n PhpVersionAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\n\n/**\n * The PHP configuration files that Forge can read and write.\n */\nexport const PHP_CONFIG_TYPES = [\"cli\", \"fpm\", \"pool\"] as const;\n\n/**\n * A PHP configuration file that Forge can read and write.\n */\nexport type PhpConfigType = (typeof PHP_CONFIG_TYPES)[number];\n\n/**\n * Options for listing PHP versions.\n */\nexport interface PhpVersionListOptions {\n /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\n}\n\n/**\n * Options for reading or writing a PHP configuration file.\n */\nexport interface PhpConfigOptions {\n /** Unix user of the FPM pool (pool only). */\n user?: string;\n}\n\n/**\n * Throw when the configuration type is not one of cli, fpm or pool,\n * or when a user is given for a type other than pool.\n */\nfunction assertConfigTarget(type: string, options: PhpConfigOptions): void {\n if (!(PHP_CONFIG_TYPES as readonly string[]).includes(type)) {\n throw new Error(\n `Invalid PHP config type \"${type}\". Valid types: ${PHP_CONFIG_TYPES.join(\", \")}.`,\n );\n }\n\n if (options.user && type !== \"pool\") {\n throw new Error(`The user option applies to the pool config only, not \"${type}\".`);\n }\n}\n\n/**\n * PHP on a server — installed versions, configuration files, limits and OPcache.\n *\n * Access via `forge.server(id).php`.\n *\n * Version methods take the PHP version ID from `list()`.\n *\n * @example\n * ```ts\n * const versions = await forge.server(123).php.list();\n * const fpm = await forge.server(123).php.config(versions[0].id, 'fpm');\n * await forge.server(123).php.setMaxUploadSize(64);\n * await forge.server(123).php.enableOpcache();\n * ```\n */\nexport class PhpResource extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/servers/${this.serverId}/php`;\n }\n\n /**\n * List the PHP versions installed on this server.\n *\n * @example\n * ```ts\n * const versions = await forge.server(123).php.list();\n * // → [{ id: 12, version: '8.3', binary_name: 'php8.3', status: 'installed', ... }]\n * ```\n */\n async list(\n options: PhpVersionListOptions = {},\n ): Promise<Array<PhpVersionAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<PhpVersionAttributes>>(\n `${this.basePath}/versions${query}`,\n );\n return unwrapListDocument(response);\n }\n\n /**\n * Get one installed PHP version.\n *\n * @example\n * ```ts\n * const version = await forge.server(123).php.get(12);\n * ```\n */\n async get(versionId: number): Promise<PhpVersionAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<PhpVersionAttributes>>(\n `${this.basePath}/versions/${versionId}`,\n );\n return unwrapDocument(response);\n }\n\n /**\n * Get a PHP configuration file (cli, fpm or pool) of a version.\n *\n * @example\n * ```ts\n * const ini = await forge.server(123).php.config(12, 'fpm');\n * const pool = await forge.server(123).php.config(12, 'pool', { user: 'forge' });\n * ```\n */\n async config(\n versionId: number,\n type: PhpConfigType,\n options: PhpConfigOptions = {},\n ): Promise<string> {\n assertConfigTarget(type, options);\n const query = options.user ? `?user=${encodeURIComponent(options.user)}` : \"\";\n const response = await this.client.get<JsonApiDocument<PhpConfigAttributes>>(\n `${this.basePath}/versions/${versionId}/configs/${type}${query}`,\n );\n return unwrapDocument(response).configuration;\n }\n\n /**\n * Replace a PHP configuration file (cli, fpm or pool) of a version.\n *\n * @example\n * ```ts\n * await forge.server(123).php.updateConfig(12, 'fpm', 'memory_limit = 512M\\n...');\n * ```\n */\n async updateConfig(\n versionId: number,\n type: PhpConfigType,\n content: string,\n options: PhpConfigOptions = {},\n ): Promise<void> {\n assertConfigTarget(type, options);\n await this.client.put(`${this.basePath}/versions/${versionId}/configs/${type}`, {\n config: content,\n ...(options.user ? { user: options.user } : {}),\n });\n }\n\n /**\n * Get the PHP max upload size, in megabytes.\n *\n * @example\n * ```ts\n * const size = await forge.server(123).php.maxUploadSize(); // → \"64\"\n * ```\n */\n async maxUploadSize(): Promise<string> {\n const response = await this.client.get<JsonApiDocument<PhpMaxUploadSizeAttributes>>(\n `${this.basePath}/max-upload-size`,\n );\n return String(unwrapDocument(response).max_upload_size);\n }\n\n /**\n * Set the PHP max upload size, in megabytes.\n *\n * @example\n * ```ts\n * await forge.server(123).php.setMaxUploadSize(128);\n * ```\n */\n async setMaxUploadSize(size: number): Promise<void> {\n await this.client.put(`${this.basePath}/max-upload-size`, { max_upload_size: size });\n }\n\n /**\n * Get the PHP max execution time, in seconds.\n *\n * @example\n * ```ts\n * const seconds = await forge.server(123).php.maxExecutionTime(); // → \"60\"\n * ```\n */\n async maxExecutionTime(): Promise<string> {\n const response = await this.client.get<JsonApiDocument<PhpMaxExecutionTimeAttributes>>(\n `${this.basePath}/max-execution-time`,\n );\n return String(unwrapDocument(response).max_execution_time);\n }\n\n /**\n * Set the PHP max execution time, in seconds.\n *\n * @example\n * ```ts\n * await forge.server(123).php.setMaxExecutionTime(120);\n * ```\n */\n async setMaxExecutionTime(seconds: number): Promise<void> {\n await this.client.put(`${this.basePath}/max-execution-time`, { max_execution_time: seconds });\n }\n\n /**\n * Get whether OPcache is enabled.\n *\n * @example\n * ```ts\n * const enabled = await forge.server(123).php.opcache(); // → true\n * ```\n */\n async opcache(): Promise<boolean> {\n const response = await this.client.get<JsonApiDocument<PhpOpcacheAttributes>>(\n `${this.basePath}/opcache`,\n );\n return unwrapDocument(response).opcache_enabled;\n }\n\n /**\n * Enable OPcache.\n *\n * @example\n * ```ts\n * await forge.server(123).php.enableOpcache();\n * ```\n */\n async enableOpcache(): Promise<void> {\n await this.client.post(`${this.basePath}/opcache`);\n }\n\n /**\n * Disable OPcache.\n *\n * @example\n * ```ts\n * await forge.server(123).php.disableOpcache();\n * ```\n */\n async disableOpcache(): Promise<void> {\n await this.client.delete(`${this.basePath}/opcache`);\n }\n}\n","import type {\n CreateServerData,\n HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n ServerAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 { ServicesCollection } from \"./services.ts\";\nimport { PhpResource } from \"./php.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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/servers`;\n }\n\n /**\n * List servers.\n *\n * @example\n * ```ts\n * const servers = await forge.servers.list();\n *\n * // Fetch a specific cursor page:\n * const page2 = await forge.servers.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(options: ServerListOptions = {}): Promise<Array<ServerAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<ServerAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<ServerAttributes & { id: number }> {\n return new AsyncPaginatedIterator<ServerAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<ServerAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<ServerAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<ServerAttributes>>(\n `${this.basePath}/${serverId}`,\n );\n return unwrapDocument(response);\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<ServerAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<ServerAttributes>>(this.basePath, data);\n return unwrapDocument(response);\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(\n serverId: number,\n data: Partial<CreateServerData>,\n ): Promise<ServerAttributes & { id: number }> {\n const response = await this.client.put<JsonApiDocument<ServerAttributes>>(\n `${this.basePath}/${serverId}`,\n data,\n );\n return unwrapDocument(response);\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(`${this.basePath}/${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(`${this.basePath}/${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 /** Services (nginx, php, mysql, etc.) on this server. */\n readonly services: ServicesCollection;\n\n /** PHP versions, configuration files, limits and OPcache on this server. */\n readonly php: PhpResource;\n\n /** @internal */\n constructor(\n client: HttpClient,\n orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n this.sites = new SitesCollection(client, orgSlug, serverId);\n this.databases = new DatabasesCollection(client, orgSlug, serverId);\n this.databaseUsers = new DatabaseUsersCollection(client, orgSlug, serverId);\n this.daemons = new DaemonsCollection(client, orgSlug, serverId);\n this.backups = new BackupsCollection(client, orgSlug, serverId);\n this.scheduledJobs = new ScheduledJobsCollection(client, orgSlug, serverId);\n this.monitors = new MonitorsCollection(client, orgSlug, serverId);\n this.firewallRules = new FirewallRulesCollection(client, orgSlug, serverId);\n this.sshKeys = new SshKeysCollection(client, orgSlug, serverId);\n this.nginxTemplates = new NginxTemplatesCollection(client, orgSlug, serverId);\n this.services = new ServicesCollection(client, orgSlug, serverId);\n this.php = new PhpResource(client, orgSlug, 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.orgSlug, 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<ServerAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<ServerAttributes>>(\n `/orgs/${this.orgSlug}/servers/${this.serverId}`,\n );\n return unwrapDocument(response);\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(`/orgs/${this.orgSlug}/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(`/orgs/${this.orgSlug}/servers/${this.serverId}`);\n }\n}\n","import type {\n CreateRecipeData,\n JsonApiDocument,\n JsonApiListDocument,\n RecipeAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/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 cursor page:\n * const page2 = await forge.recipes.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(options: RecipeListOptions = {}): Promise<Array<RecipeAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<RecipeAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<RecipeAttributes & { id: number }> {\n return new AsyncPaginatedIterator<RecipeAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<RecipeAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<RecipeAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<RecipeAttributes>>(\n `${this.basePath}/${recipeId}`,\n );\n return unwrapDocument(response);\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<RecipeAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<RecipeAttributes>>(this.basePath, data);\n return unwrapDocument(response);\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, JsonApiDocument, UserAttributes } from \"@studiometa/forge-api\";\n\nimport { HttpClient, unwrapDocument } 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', 'my-org');\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 /** The organization slug used for v2 API URL prefixing. */\n readonly organizationSlug: string;\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 organizationSlug Your organization slug (used for v2 API URLs).\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', 'my-org');\n *\n * // With custom options\n * const forge = new Forge('your-api-token', 'my-org', {\n * baseUrl: 'https://forge.laravel.com/api/v2',\n * });\n *\n * // With mock fetch for testing\n * const forge = new Forge('test-token', 'test-org', { fetch: mockFetch });\n * ```\n */\n constructor(token: string, organizationSlug: string, options?: ForgeOptions) {\n this.client = new HttpClient({ token, ...options });\n this.organizationSlug = organizationSlug;\n this.servers = new ServersCollection(this.client, organizationSlug);\n this.recipes = new RecipesCollection(this.client, organizationSlug);\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, this.organizationSlug, 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<UserAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<UserAttributes>>(\"/user\");\n return unwrapDocument(response);\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/services.ts","../src/resources/php.ts","../src/resources/servers.ts","../src/resources/recipes.ts","../src/resources/storage-providers.ts","../src/forge.ts"],"sourcesContent":["/**\n * Function that fetches a page of results using cursor-based pagination.\n * Pass `null` for the first page, or a cursor string for subsequent pages.\n */\nexport type PageFetcher<T> = (\n cursor: string | null,\n) => Promise<{ items: T[]; nextCursor: string | null }>;\n\n/**\n * Async paginated iterator that auto-fetches all pages using cursor-based pagination.\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\n constructor(fetchPage: PageFetcher<T>) {\n this.fetchPage = fetchPage;\n }\n\n async *[Symbol.asyncIterator](): AsyncGenerator<T, void, undefined> {\n let cursor: string | null = null;\n let hasMore = true;\n\n while (hasMore) {\n const { items, nextCursor } = await this.fetchPage(cursor);\n\n for (const item of items) {\n yield item;\n }\n\n if (nextCursor) {\n cursor = nextCursor;\n } else {\n hasMore = false;\n }\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 shared `client` and `orgSlug` properties to avoid duplication across all collection classes.\n */\nexport abstract class BaseCollection {\n protected readonly client: HttpClient;\n protected readonly orgSlug: string;\n\n constructor(client: HttpClient, orgSlug: string) {\n this.client = client;\n this.orgSlug = orgSlug;\n }\n}\n","import type {\n HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n DeploymentAttributes,\n DeploymentOutputAttributes,\n DeploymentScriptAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/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 cursor page:\n * const page2 = await forge.server(123).site(456).deployments.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(\n options: DeploymentListOptions = {},\n ): Promise<Array<DeploymentAttributes & { id: number }>> {\n const params = new URLSearchParams({ sort: \"-created_at\" });\n if (options.cursor !== undefined) {\n params.set(\"page[cursor]\", options.cursor);\n }\n const response = await this.client.get<JsonApiListDocument<DeploymentAttributes>>(\n `${this.basePath}?${params.toString()}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<DeploymentAttributes & { id: number }> {\n return new AsyncPaginatedIterator<DeploymentAttributes & { id: number }>(async (cursor) => {\n const params = \"?sort=-created_at\" + (cursor !== null ? `&page[cursor]=${cursor}` : \"\");\n const response = await this.client.get<JsonApiListDocument<DeploymentAttributes>>(\n `${this.basePath}${params}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<DeploymentAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<DeploymentAttributes>>(\n `${this.basePath}/${deploymentId}`,\n );\n return unwrapDocument(response);\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 const response = await this.client.get<JsonApiDocument<DeploymentOutputAttributes>>(\n `${this.basePath}/${deploymentId}/output`,\n );\n return unwrapDocument(response).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 const response = await this.client.get<JsonApiDocument<DeploymentScriptAttributes>>(\n `/orgs/${this.orgSlug}/servers/${this.serverId}/sites/${this.siteId}/deployments/script`,\n );\n return unwrapDocument(response).content;\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(\n `/orgs/${this.orgSlug}/servers/${this.serverId}/sites/${this.siteId}/deployments/script`,\n { content },\n );\n }\n}\n","import type {\n CreateCertificateData,\n HttpClient,\n JsonApiDocument,\n CertificateAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument } from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\n\n/**\n * SSL certificates for a site, accessed per-domain.\n *\n * In v2, certificates are a singular sub-resource of a domain:\n * `/orgs/{org}/servers/{server}/sites/{site}/domains/{domain}/certificate`\n *\n * Access via `forge.server(id).site(id).certificates`.\n *\n * @example\n * ```ts\n * const cert = await forge.server(123).site(456).certificates.get(789);\n * ```\n */\nexport class CertificatesCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n orgSlug: string,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client, orgSlug);\n }\n\n private domainPath(domainId: number): string {\n return `/orgs/${this.orgSlug}/servers/${this.serverId}/sites/${this.siteId}/domains/${domainId}/certificate`;\n }\n\n /**\n * Get the certificate for a domain.\n *\n * @example\n * ```ts\n * const cert = await forge.server(123).site(456).certificates.get(789);\n * ```\n */\n async get(domainId: number): Promise<CertificateAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<CertificateAttributes>>(\n this.domainPath(domainId),\n );\n return unwrapDocument(response);\n }\n\n /**\n * Create a certificate for a domain.\n *\n * @example\n * ```ts\n * const cert = await forge.server(123).site(456).certificates.create(789, {\n * type: 'letsencrypt',\n * });\n * ```\n */\n async create(\n domainId: number,\n data: CreateCertificateData,\n ): Promise<CertificateAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<CertificateAttributes>>(\n this.domainPath(domainId),\n data,\n );\n return unwrapDocument(response);\n }\n\n /**\n * Delete the certificate for a domain.\n *\n * @example\n * ```ts\n * await forge.server(123).site(456).certificates.delete(789);\n * ```\n */\n async delete(domainId: number): Promise<void> {\n await this.client.delete(this.domainPath(domainId));\n }\n\n /**\n * Activate the certificate for a domain.\n *\n * @example\n * ```ts\n * await forge.server(123).site(456).certificates.activate(789);\n * ```\n */\n async activate(domainId: number): Promise<void> {\n await this.client.post(`${this.domainPath(domainId)}/actions`, { action: \"activate\" });\n }\n}\n","import type {\n CreateCommandData,\n HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n CommandAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/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 cursor page:\n * const page2 = await forge.server(123).site(456).commands.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(options: CommandListOptions = {}): Promise<Array<CommandAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<CommandAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<CommandAttributes & { id: number }> {\n return new AsyncPaginatedIterator<CommandAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<CommandAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<CommandAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<CommandAttributes>>(\n `${this.basePath}/${commandId}`,\n );\n return unwrapDocument(response);\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<CommandAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<CommandAttributes>>(\n this.basePath,\n data,\n );\n return unwrapDocument(response);\n }\n}\n","import type {\n CreateSecurityRuleData,\n HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n SecurityRuleAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/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 cursor page:\n * const page2 = await forge.server(123).site(456).securityRules.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(\n options: SecurityRuleListOptions = {},\n ): Promise<Array<SecurityRuleAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<SecurityRuleAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<SecurityRuleAttributes & { id: number }> {\n return new AsyncPaginatedIterator<SecurityRuleAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<SecurityRuleAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<SecurityRuleAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<SecurityRuleAttributes>>(\n `${this.basePath}/${ruleId}`,\n );\n return unwrapDocument(response);\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<SecurityRuleAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<SecurityRuleAttributes>>(\n this.basePath,\n data,\n );\n return unwrapDocument(response);\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 HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n RedirectRuleAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/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 cursor page:\n * const page2 = await forge.server(123).site(456).redirectRules.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(\n options: RedirectRuleListOptions = {},\n ): Promise<Array<RedirectRuleAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<RedirectRuleAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<RedirectRuleAttributes & { id: number }> {\n return new AsyncPaginatedIterator<RedirectRuleAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<RedirectRuleAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<RedirectRuleAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<RedirectRuleAttributes>>(\n `${this.basePath}/${ruleId}`,\n );\n return unwrapDocument(response);\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<RedirectRuleAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<RedirectRuleAttributes>>(\n this.basePath,\n data,\n );\n return unwrapDocument(response);\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 HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n SiteAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/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 cursor page:\n * const page2 = await forge.server(123).sites.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(options: SiteListOptions = {}): Promise<Array<SiteAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<SiteAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<SiteAttributes & { id: number }> {\n return new AsyncPaginatedIterator<SiteAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<SiteAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<SiteAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<SiteAttributes>>(\n `/orgs/${this.orgSlug}/sites/${siteId}`,\n );\n return unwrapDocument(response);\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 * type: 'php',\n * name: 'example.com',\n * directory: '/public',\n * });\n * ```\n */\n async create(data: CreateSiteData): Promise<SiteAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<SiteAttributes>>(this.basePath, data);\n return unwrapDocument(response);\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(\n siteId: number,\n data: Partial<CreateSiteData>,\n ): Promise<SiteAttributes & { id: number }> {\n const response = await this.client.put<JsonApiDocument<SiteAttributes>>(\n `${this.basePath}/${siteId}`,\n data,\n );\n return unwrapDocument(response);\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 orgSlug: string,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client, orgSlug);\n this.deployments = new DeploymentsCollection(client, orgSlug, serverId, siteId);\n this.certificates = new CertificatesCollection(client, orgSlug, serverId, siteId);\n this.env = new SiteEnvResource(client, orgSlug, serverId, siteId);\n this.nginx = new SiteNginxResource(client, orgSlug, serverId, siteId);\n this.commands = new CommandsCollection(client, orgSlug, serverId, siteId);\n this.securityRules = new SecurityRulesCollection(client, orgSlug, serverId, siteId);\n this.redirectRules = new RedirectRulesCollection(client, orgSlug, serverId, siteId);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/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<SiteAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<SiteAttributes>>(\n `/orgs/${this.orgSlug}/sites/${this.siteId}`,\n );\n return unwrapDocument(response);\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}/deployments/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 orgSlug: string,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/servers/${this.serverId}/sites/${this.siteId}/environment`;\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, { environment: 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 orgSlug: string,\n private readonly serverId: number,\n private readonly siteId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/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, { config: content });\n }\n}\n","import type {\n CreateDatabaseData,\n HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n DatabaseAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/servers/${this.serverId}/database/schemas`;\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 cursor page:\n * const page2 = await forge.server(123).databases.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(\n options: DatabaseListOptions = {},\n ): Promise<Array<DatabaseAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<DatabaseAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<DatabaseAttributes & { id: number }> {\n return new AsyncPaginatedIterator<DatabaseAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<DatabaseAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<DatabaseAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<DatabaseAttributes>>(\n `${this.basePath}/${databaseId}`,\n );\n return unwrapDocument(response);\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<DatabaseAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<DatabaseAttributes>>(\n this.basePath,\n data,\n );\n return unwrapDocument(response);\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 HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n DatabaseUserAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/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 cursor page:\n * const page2 = await forge.server(123).databaseUsers.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(\n options: DatabaseUserListOptions = {},\n ): Promise<Array<DatabaseUserAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<DatabaseUserAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<DatabaseUserAttributes & { id: number }> {\n return new AsyncPaginatedIterator<DatabaseUserAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<DatabaseUserAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<DatabaseUserAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<DatabaseUserAttributes>>(\n `${this.basePath}/${userId}`,\n );\n return unwrapDocument(response);\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<DatabaseUserAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<DatabaseUserAttributes>>(\n this.basePath,\n data,\n );\n return unwrapDocument(response);\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 HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n BackgroundProcessAttributes,\n BackgroundProcessLogAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/servers/${this.serverId}/background-processes`;\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 cursor page:\n * const page2 = await forge.server(123).daemons.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(\n options: DaemonListOptions = {},\n ): Promise<Array<BackgroundProcessAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<BackgroundProcessAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<BackgroundProcessAttributes & { id: number }> {\n return new AsyncPaginatedIterator<BackgroundProcessAttributes & { id: number }>(\n async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<BackgroundProcessAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n },\n );\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<BackgroundProcessAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<BackgroundProcessAttributes>>(\n `${this.basePath}/${daemonId}`,\n );\n return unwrapDocument(response);\n }\n\n /**\n * Get the log output of a daemon.\n *\n * @example\n * ```ts\n * const log = await forge.server(123).daemons.log(789);\n * ```\n */\n async log(daemonId: number): Promise<string> {\n const response = await this.client.get<JsonApiDocument<BackgroundProcessLogAttributes>>(\n `${this.basePath}/${daemonId}/log`,\n );\n return unwrapDocument(response).content;\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<BackgroundProcessAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<BackgroundProcessAttributes>>(\n this.basePath,\n data,\n );\n return unwrapDocument(response);\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 CreateBackupConfigData,\n HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n BackupConfigAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/servers/${this.serverId}/database/backups`;\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 cursor page:\n * const page2 = await forge.server(123).backups.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(\n options: BackupConfigListOptions = {},\n ): Promise<Array<BackupConfigAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<BackupConfigAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<BackupConfigAttributes & { id: number }> {\n return new AsyncPaginatedIterator<BackupConfigAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<BackupConfigAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<BackupConfigAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<BackupConfigAttributes>>(\n `${this.basePath}/${backupId}`,\n );\n return unwrapDocument(response);\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<BackupConfigAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<BackupConfigAttributes>>(\n this.basePath,\n data,\n );\n return unwrapDocument(response);\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 HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n ScheduledJobAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/servers/${this.serverId}/scheduled-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 cursor page:\n * const page2 = await forge.server(123).scheduledJobs.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(\n options: ScheduledJobListOptions = {},\n ): Promise<Array<ScheduledJobAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<ScheduledJobAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<ScheduledJobAttributes & { id: number }> {\n return new AsyncPaginatedIterator<ScheduledJobAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<ScheduledJobAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<ScheduledJobAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<ScheduledJobAttributes>>(\n `${this.basePath}/${jobId}`,\n );\n return unwrapDocument(response);\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<ScheduledJobAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<ScheduledJobAttributes>>(\n this.basePath,\n data,\n );\n return unwrapDocument(response);\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 HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n MonitorAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/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 cursor page:\n * const page2 = await forge.server(123).monitors.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(options: MonitorListOptions = {}): Promise<Array<MonitorAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<MonitorAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<MonitorAttributes & { id: number }> {\n return new AsyncPaginatedIterator<MonitorAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<MonitorAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<MonitorAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<MonitorAttributes>>(\n `${this.basePath}/${monitorId}`,\n );\n return unwrapDocument(response);\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<MonitorAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<MonitorAttributes>>(\n this.basePath,\n data,\n );\n return unwrapDocument(response);\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 HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n FirewallRuleAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/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 cursor page:\n * const page2 = await forge.server(123).firewallRules.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(\n options: FirewallRuleListOptions = {},\n ): Promise<Array<FirewallRuleAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<FirewallRuleAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<FirewallRuleAttributes & { id: number }> {\n return new AsyncPaginatedIterator<FirewallRuleAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<FirewallRuleAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<FirewallRuleAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<FirewallRuleAttributes>>(\n `${this.basePath}/${ruleId}`,\n );\n return unwrapDocument(response);\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<FirewallRuleAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<FirewallRuleAttributes>>(\n this.basePath,\n data,\n );\n return unwrapDocument(response);\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 HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n SshKeyAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/servers/${this.serverId}/ssh-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 cursor page:\n * const page2 = await forge.server(123).sshKeys.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(options: SshKeyListOptions = {}): Promise<Array<SshKeyAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<SshKeyAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<SshKeyAttributes & { id: number }> {\n return new AsyncPaginatedIterator<SshKeyAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<SshKeyAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<SshKeyAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<SshKeyAttributes>>(\n `${this.basePath}/${keyId}`,\n );\n return unwrapDocument(response);\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<SshKeyAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<SshKeyAttributes>>(this.basePath, data);\n return unwrapDocument(response);\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 HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n NginxTemplateAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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 orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/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 cursor page:\n * const page2 = await forge.server(123).nginxTemplates.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(\n options: NginxTemplateListOptions = {},\n ): Promise<Array<NginxTemplateAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<NginxTemplateAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<NginxTemplateAttributes & { id: number }> {\n return new AsyncPaginatedIterator<NginxTemplateAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<NginxTemplateAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\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<NginxTemplateAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<NginxTemplateAttributes>>(\n `${this.basePath}/${templateId}`,\n );\n return unwrapDocument(response);\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<NginxTemplateAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<NginxTemplateAttributes>>(\n this.basePath,\n data,\n );\n return unwrapDocument(response);\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<NginxTemplateAttributes & { id: number }> {\n const response = await this.client.put<JsonApiDocument<NginxTemplateAttributes>>(\n `${this.basePath}/${templateId}`,\n data,\n );\n return unwrapDocument(response);\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 { HttpClient, JsonApiDocument, ServerAttributes } from \"@studiometa/forge-api\";\n\nimport { unwrapDocument } from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\n\n/**\n * The six restartable services exposed by the Forge v2 API.\n */\nexport const RESTARTABLE_SERVICES = [\n \"nginx\",\n \"php\",\n \"mysql\",\n \"postgres\",\n \"redis\",\n \"supervisor\",\n] as const;\n\nexport type RestartableService = (typeof RESTARTABLE_SERVICES)[number];\n\n/**\n * A single service availability row.\n *\n * `available` is a documented heuristic derived from the server object, since\n * the API has no services GET endpoint.\n */\nexport interface ServiceStatus {\n service: string;\n available: boolean;\n detail: string | null;\n}\n\n/**\n * Options for restarting a service.\n */\nexport interface RestartServiceOptions {\n /** PHP version (e.g. \"php83\") — required when restarting the php service. */\n version?: string;\n}\n\n/**\n * Services on a server — list availability and restart individual services.\n *\n * Access via `forge.server(id).services`.\n *\n * The v2 API has no GET endpoint for services, so `list()` derives availability\n * from the server object. Restarting maps to the API action `reboot`.\n *\n * @example\n * ```ts\n * // List services and their availability\n * const services = await forge.server(123).services.list();\n *\n * // Restart nginx\n * await forge.server(123).services.restart('nginx');\n *\n * // Restart php (version required)\n * await forge.server(123).services.restart('php', { version: 'php83' });\n * ```\n */\nexport class ServicesCollection extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/servers/${this.serverId}`;\n }\n\n /**\n * List services on this server with a derived availability flag.\n *\n * @example\n * ```ts\n * const services = await forge.server(123).services.list();\n * // → [{ service: 'nginx', available: true, detail: null }, ...]\n * ```\n */\n async list(): Promise<ServiceStatus[]> {\n const response = await this.client.get<JsonApiDocument<ServerAttributes>>(this.basePath);\n const server = unwrapDocument(response);\n\n const databaseType = server.database_type ?? \"\";\n const isMysql = databaseType.startsWith(\"mysql\") || databaseType.startsWith(\"mariadb\");\n const isPostgres = databaseType.startsWith(\"postgres\");\n\n return [\n { service: \"nginx\", available: true, detail: null },\n { service: \"php\", available: server.php_version !== null, detail: server.php_version },\n { service: \"mysql\", available: isMysql, detail: isMysql ? server.database_type : null },\n {\n service: \"postgres\",\n available: isPostgres,\n detail: isPostgres ? server.database_type : null,\n },\n { service: \"redis\", available: server.redis_status !== null, detail: server.redis_status },\n { service: \"supervisor\", available: true, detail: null },\n ];\n }\n\n /**\n * Restart a service on this server.\n *\n * Maps to the API action `reboot`. The php service requires a `version`.\n *\n * @example\n * ```ts\n * await forge.server(123).services.restart('nginx');\n * await forge.server(123).services.restart('php', { version: 'php83' });\n * ```\n */\n async restart(service: string, options: RestartServiceOptions = {}): Promise<void> {\n if (!(RESTARTABLE_SERVICES as readonly string[]).includes(service)) {\n throw new Error(\n `Invalid service \"${service}\". Valid services: ${RESTARTABLE_SERVICES.join(\", \")}.`,\n );\n }\n\n if (service === \"php\" && !options.version) {\n throw new Error('The \"php\" service requires a version (e.g. \"php83\") to restart.');\n }\n\n await this.client.post(`${this.basePath}/services/${service}/actions`, {\n action: \"reboot\",\n ...(options.version ? { version: options.version } : {}),\n });\n }\n}\n","import type {\n HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n PhpConfigAttributes,\n PhpMaxExecutionTimeAttributes,\n PhpMaxUploadSizeAttributes,\n PhpOpcacheAttributes,\n PhpVersionAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\n\n/**\n * The PHP configuration files that Forge can read and write.\n */\nexport const PHP_CONFIG_TYPES = [\"cli\", \"fpm\", \"pool\"] as const;\n\n/**\n * A PHP configuration file that Forge can read and write.\n */\nexport type PhpConfigType = (typeof PHP_CONFIG_TYPES)[number];\n\n/**\n * Options for listing PHP versions.\n */\nexport interface PhpVersionListOptions {\n /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\n}\n\n/**\n * Options for reading or writing a PHP configuration file.\n */\nexport interface PhpConfigOptions {\n /** Unix user of the FPM pool (pool only). */\n user?: string;\n}\n\n/**\n * Throw when the configuration type is not one of cli, fpm or pool,\n * or when a user is given for a type other than pool.\n */\nfunction assertConfigTarget(type: string, options: PhpConfigOptions): void {\n if (!(PHP_CONFIG_TYPES as readonly string[]).includes(type)) {\n throw new Error(\n `Invalid PHP config type \"${type}\". Valid types: ${PHP_CONFIG_TYPES.join(\", \")}.`,\n );\n }\n\n if (options.user && type !== \"pool\") {\n throw new Error(`The user option applies to the pool config only, not \"${type}\".`);\n }\n}\n\n/**\n * PHP on a server — installed versions, configuration files, limits and OPcache.\n *\n * Access via `forge.server(id).php`.\n *\n * Version methods take the PHP version ID from `list()`.\n *\n * @example\n * ```ts\n * const versions = await forge.server(123).php.list();\n * const fpm = await forge.server(123).php.config(versions[0].id, 'fpm');\n * await forge.server(123).php.setMaxUploadSize(64);\n * await forge.server(123).php.enableOpcache();\n * ```\n */\nexport class PhpResource extends BaseCollection {\n /** @internal */\n constructor(\n client: HttpClient,\n orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n }\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/servers/${this.serverId}/php`;\n }\n\n /**\n * List the PHP versions installed on this server.\n *\n * @example\n * ```ts\n * const versions = await forge.server(123).php.list();\n * // → [{ id: 12, version: '8.3', binary_name: 'php8.3', status: 'installed', ... }]\n * ```\n */\n async list(\n options: PhpVersionListOptions = {},\n ): Promise<Array<PhpVersionAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<PhpVersionAttributes>>(\n `${this.basePath}/versions${query}`,\n );\n return unwrapListDocument(response);\n }\n\n /**\n * Get one installed PHP version.\n *\n * @example\n * ```ts\n * const version = await forge.server(123).php.get(12);\n * ```\n */\n async get(versionId: number): Promise<PhpVersionAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<PhpVersionAttributes>>(\n `${this.basePath}/versions/${versionId}`,\n );\n return unwrapDocument(response);\n }\n\n /**\n * Get a PHP configuration file (cli, fpm or pool) of a version.\n *\n * @example\n * ```ts\n * const ini = await forge.server(123).php.config(12, 'fpm');\n * const pool = await forge.server(123).php.config(12, 'pool', { user: 'forge' });\n * ```\n */\n async config(\n versionId: number,\n type: PhpConfigType,\n options: PhpConfigOptions = {},\n ): Promise<string> {\n assertConfigTarget(type, options);\n const query = options.user ? `?user=${encodeURIComponent(options.user)}` : \"\";\n const response = await this.client.get<JsonApiDocument<PhpConfigAttributes>>(\n `${this.basePath}/versions/${versionId}/configs/${type}${query}`,\n );\n return unwrapDocument(response).configuration;\n }\n\n /**\n * Replace a PHP configuration file (cli, fpm or pool) of a version.\n *\n * @example\n * ```ts\n * await forge.server(123).php.updateConfig(12, 'fpm', 'memory_limit = 512M\\n...');\n * ```\n */\n async updateConfig(\n versionId: number,\n type: PhpConfigType,\n content: string,\n options: PhpConfigOptions = {},\n ): Promise<void> {\n assertConfigTarget(type, options);\n await this.client.put(`${this.basePath}/versions/${versionId}/configs/${type}`, {\n config: content,\n ...(options.user ? { user: options.user } : {}),\n });\n }\n\n /**\n * Get the PHP max upload size, in megabytes.\n *\n * @example\n * ```ts\n * const size = await forge.server(123).php.maxUploadSize(); // → \"64\"\n * ```\n */\n async maxUploadSize(): Promise<string> {\n const response = await this.client.get<JsonApiDocument<PhpMaxUploadSizeAttributes>>(\n `${this.basePath}/max-upload-size`,\n );\n return String(unwrapDocument(response).max_upload_size);\n }\n\n /**\n * Set the PHP max upload size, in megabytes.\n *\n * @example\n * ```ts\n * await forge.server(123).php.setMaxUploadSize(128);\n * ```\n */\n async setMaxUploadSize(size: number): Promise<void> {\n await this.client.put(`${this.basePath}/max-upload-size`, { max_upload_size: size });\n }\n\n /**\n * Get the PHP max execution time, in seconds.\n *\n * @example\n * ```ts\n * const seconds = await forge.server(123).php.maxExecutionTime(); // → \"60\"\n * ```\n */\n async maxExecutionTime(): Promise<string> {\n const response = await this.client.get<JsonApiDocument<PhpMaxExecutionTimeAttributes>>(\n `${this.basePath}/max-execution-time`,\n );\n return String(unwrapDocument(response).max_execution_time);\n }\n\n /**\n * Set the PHP max execution time, in seconds.\n *\n * @example\n * ```ts\n * await forge.server(123).php.setMaxExecutionTime(120);\n * ```\n */\n async setMaxExecutionTime(seconds: number): Promise<void> {\n await this.client.put(`${this.basePath}/max-execution-time`, { max_execution_time: seconds });\n }\n\n /**\n * Get whether OPcache is enabled.\n *\n * @example\n * ```ts\n * const enabled = await forge.server(123).php.opcache(); // → true\n * ```\n */\n async opcache(): Promise<boolean> {\n const response = await this.client.get<JsonApiDocument<PhpOpcacheAttributes>>(\n `${this.basePath}/opcache`,\n );\n return unwrapDocument(response).opcache_enabled;\n }\n\n /**\n * Enable OPcache.\n *\n * @example\n * ```ts\n * await forge.server(123).php.enableOpcache();\n * ```\n */\n async enableOpcache(): Promise<void> {\n await this.client.post(`${this.basePath}/opcache`);\n }\n\n /**\n * Disable OPcache.\n *\n * @example\n * ```ts\n * await forge.server(123).php.disableOpcache();\n * ```\n */\n async disableOpcache(): Promise<void> {\n await this.client.delete(`${this.basePath}/opcache`);\n }\n}\n","import type {\n CreateServerData,\n HttpClient,\n JsonApiDocument,\n JsonApiListDocument,\n ServerAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 { ServicesCollection } from \"./services.ts\";\nimport { PhpResource } from \"./php.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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/servers`;\n }\n\n /**\n * List servers.\n *\n * @example\n * ```ts\n * const servers = await forge.servers.list();\n *\n * // Fetch a specific cursor page:\n * const page2 = await forge.servers.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(options: ServerListOptions = {}): Promise<Array<ServerAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<ServerAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<ServerAttributes & { id: number }> {\n return new AsyncPaginatedIterator<ServerAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<ServerAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<ServerAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<ServerAttributes>>(\n `${this.basePath}/${serverId}`,\n );\n return unwrapDocument(response);\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<ServerAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<ServerAttributes>>(this.basePath, data);\n return unwrapDocument(response);\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(\n serverId: number,\n data: Partial<CreateServerData>,\n ): Promise<ServerAttributes & { id: number }> {\n const response = await this.client.put<JsonApiDocument<ServerAttributes>>(\n `${this.basePath}/${serverId}`,\n data,\n );\n return unwrapDocument(response);\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(`${this.basePath}/${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(`${this.basePath}/${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 /** Services (nginx, php, mysql, etc.) on this server. */\n readonly services: ServicesCollection;\n\n /** PHP versions, configuration files, limits and OPcache on this server. */\n readonly php: PhpResource;\n\n /** @internal */\n constructor(\n client: HttpClient,\n orgSlug: string,\n private readonly serverId: number,\n ) {\n super(client, orgSlug);\n this.sites = new SitesCollection(client, orgSlug, serverId);\n this.databases = new DatabasesCollection(client, orgSlug, serverId);\n this.databaseUsers = new DatabaseUsersCollection(client, orgSlug, serverId);\n this.daemons = new DaemonsCollection(client, orgSlug, serverId);\n this.backups = new BackupsCollection(client, orgSlug, serverId);\n this.scheduledJobs = new ScheduledJobsCollection(client, orgSlug, serverId);\n this.monitors = new MonitorsCollection(client, orgSlug, serverId);\n this.firewallRules = new FirewallRulesCollection(client, orgSlug, serverId);\n this.sshKeys = new SshKeysCollection(client, orgSlug, serverId);\n this.nginxTemplates = new NginxTemplatesCollection(client, orgSlug, serverId);\n this.services = new ServicesCollection(client, orgSlug, serverId);\n this.php = new PhpResource(client, orgSlug, 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.orgSlug, 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<ServerAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<ServerAttributes>>(\n `/orgs/${this.orgSlug}/servers/${this.serverId}`,\n );\n return unwrapDocument(response);\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(`/orgs/${this.orgSlug}/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(`/orgs/${this.orgSlug}/servers/${this.serverId}`);\n }\n}\n","import type {\n CreateRecipeData,\n JsonApiDocument,\n JsonApiListDocument,\n RecipeAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } 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 /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\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\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/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 cursor page:\n * const page2 = await forge.recipes.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(options: RecipeListOptions = {}): Promise<Array<RecipeAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<RecipeAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\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(): AsyncPaginatedIterator<RecipeAttributes & { id: number }> {\n return new AsyncPaginatedIterator<RecipeAttributes & { id: number }>(async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<RecipeAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n });\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<RecipeAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<RecipeAttributes>>(\n `${this.basePath}/${recipeId}`,\n );\n return unwrapDocument(response);\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<RecipeAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<RecipeAttributes>>(this.basePath, data);\n return unwrapDocument(response);\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 {\n CreateStorageProviderData,\n JsonApiDocument,\n JsonApiListDocument,\n StorageProviderAttributes,\n} from \"@studiometa/forge-api\";\n\nimport { unwrapDocument, unwrapListDocument } from \"@studiometa/forge-api\";\n\nimport { BaseCollection } from \"./base.ts\";\nimport { AsyncPaginatedIterator } from \"../pagination.ts\";\n\n/**\n * Options for listing storage providers.\n */\nexport interface StorageProviderListOptions {\n /** Cursor for pagination (from previous response's next_cursor). */\n cursor?: string;\n}\n\n/**\n * Collection of storage providers: the S3-compatible buckets that database backups use.\n *\n * Access via `forge.storageProviders`.\n *\n * @example\n * ```ts\n * const providers = await forge.storageProviders.list();\n * ```\n */\nexport class StorageProvidersCollection extends BaseCollection {\n /** @internal */\n\n private get basePath(): string {\n return `/orgs/${this.orgSlug}/storage-providers`;\n }\n\n /**\n * List storage providers.\n *\n * @example\n * ```ts\n * const providers = await forge.storageProviders.list();\n *\n * // Fetch a specific cursor page:\n * const page2 = await forge.storageProviders.list({ cursor: 'next-cursor-value' });\n * ```\n */\n async list(\n options: StorageProviderListOptions = {},\n ): Promise<Array<StorageProviderAttributes & { id: number }>> {\n const query = options.cursor !== undefined ? `?page[cursor]=${options.cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<StorageProviderAttributes>>(\n `${this.basePath}${query}`,\n );\n return unwrapListDocument(response);\n }\n\n /**\n * Iterate over all storage providers across all pages.\n *\n * @example\n * ```ts\n * const providers = await forge.storageProviders.all().toArray();\n * ```\n */\n all(): AsyncPaginatedIterator<StorageProviderAttributes & { id: number }> {\n return new AsyncPaginatedIterator<StorageProviderAttributes & { id: number }>(\n async (cursor) => {\n const query = cursor !== null ? `?page[cursor]=${cursor}` : \"\";\n const response = await this.client.get<JsonApiListDocument<StorageProviderAttributes>>(\n `${this.basePath}${query}`,\n );\n return {\n items: unwrapListDocument(response),\n nextCursor: response.meta.next_cursor ?? null,\n };\n },\n );\n }\n\n /**\n * Get a specific storage provider.\n *\n * @example\n * ```ts\n * const provider = await forge.storageProviders.get(12);\n * ```\n */\n async get(providerId: number): Promise<StorageProviderAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<StorageProviderAttributes>>(\n `${this.basePath}/${providerId}`,\n );\n return unwrapDocument(response);\n }\n\n /**\n * Create a storage provider.\n *\n * @example\n * ```ts\n * const provider = await forge.storageProviders.create({\n * name: 'Backups',\n * provider: 'custom',\n * endpoint: 'https://s3.example.com',\n * region: 'eu-west-1',\n * bucket: 'my-bucket',\n * access_key: 'AKIA...',\n * secret_key: process.env.S3_SECRET_KEY,\n * });\n * ```\n */\n async create(\n data: CreateStorageProviderData,\n ): Promise<StorageProviderAttributes & { id: number }> {\n const response = await this.client.post<JsonApiDocument<StorageProviderAttributes>>(\n this.basePath,\n data,\n );\n return unwrapDocument(response);\n }\n\n /**\n * Delete a storage provider. Forge refuses when a backup configuration uses it.\n *\n * @example\n * ```ts\n * await forge.storageProviders.delete(12);\n * ```\n */\n async delete(providerId: number): Promise<void> {\n await this.client.delete(`${this.basePath}/${providerId}`);\n }\n}\n","import type { ForgeOptions, JsonApiDocument, UserAttributes } from \"@studiometa/forge-api\";\n\nimport { HttpClient, unwrapDocument } from \"@studiometa/forge-api\";\n\nimport { ServersCollection, ServerResource } from \"./resources/servers.ts\";\nimport { RecipesCollection } from \"./resources/recipes.ts\";\nimport { StorageProvidersCollection } from \"./resources/storage-providers.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', 'my-org');\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 /** The organization slug used for v2 API URL prefixing. */\n readonly organizationSlug: string;\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 /** Storage provider operations (list, get, create, delete), used by database backups. */\n readonly storageProviders: StorageProvidersCollection;\n\n /**\n * Create a new Forge SDK instance.\n *\n * @param token Your Laravel Forge API token.\n * @param organizationSlug Your organization slug (used for v2 API URLs).\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', 'my-org');\n *\n * // With custom options\n * const forge = new Forge('your-api-token', 'my-org', {\n * baseUrl: 'https://forge.laravel.com/api/v2',\n * });\n *\n * // With mock fetch for testing\n * const forge = new Forge('test-token', 'test-org', { fetch: mockFetch });\n * ```\n */\n constructor(token: string, organizationSlug: string, options?: ForgeOptions) {\n this.client = new HttpClient({ token, ...options });\n this.organizationSlug = organizationSlug;\n this.servers = new ServersCollection(this.client, organizationSlug);\n this.recipes = new RecipesCollection(this.client, organizationSlug);\n this.storageProviders = new StorageProvidersCollection(this.client, organizationSlug);\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, this.organizationSlug, 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<UserAttributes & { id: number }> {\n const response = await this.client.get<JsonApiDocument<UserAttributes>>(\"/user\");\n return unwrapDocument(response);\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { CreateStorageProviderData, StorageProviderAttributes } from "@studiometa/forge-api";
|
|
2
|
+
import { BaseCollection } from "./base.ts";
|
|
3
|
+
import { AsyncPaginatedIterator } from "../pagination.ts";
|
|
4
|
+
/**
|
|
5
|
+
* Options for listing storage providers.
|
|
6
|
+
*/
|
|
7
|
+
export interface StorageProviderListOptions {
|
|
8
|
+
/** Cursor for pagination (from previous response's next_cursor). */
|
|
9
|
+
cursor?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Collection of storage providers: the S3-compatible buckets that database backups use.
|
|
13
|
+
*
|
|
14
|
+
* Access via `forge.storageProviders`.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* const providers = await forge.storageProviders.list();
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare class StorageProvidersCollection extends BaseCollection {
|
|
22
|
+
/** @internal */
|
|
23
|
+
private get basePath();
|
|
24
|
+
/**
|
|
25
|
+
* List storage providers.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* const providers = await forge.storageProviders.list();
|
|
30
|
+
*
|
|
31
|
+
* // Fetch a specific cursor page:
|
|
32
|
+
* const page2 = await forge.storageProviders.list({ cursor: 'next-cursor-value' });
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
list(options?: StorageProviderListOptions): Promise<Array<StorageProviderAttributes & {
|
|
36
|
+
id: number;
|
|
37
|
+
}>>;
|
|
38
|
+
/**
|
|
39
|
+
* Iterate over all storage providers across all pages.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* const providers = await forge.storageProviders.all().toArray();
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
all(): AsyncPaginatedIterator<StorageProviderAttributes & {
|
|
47
|
+
id: number;
|
|
48
|
+
}>;
|
|
49
|
+
/**
|
|
50
|
+
* Get a specific storage provider.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* const provider = await forge.storageProviders.get(12);
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
get(providerId: number): Promise<StorageProviderAttributes & {
|
|
58
|
+
id: number;
|
|
59
|
+
}>;
|
|
60
|
+
/**
|
|
61
|
+
* Create a storage provider.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* const provider = await forge.storageProviders.create({
|
|
66
|
+
* name: 'Backups',
|
|
67
|
+
* provider: 'custom',
|
|
68
|
+
* endpoint: 'https://s3.example.com',
|
|
69
|
+
* region: 'eu-west-1',
|
|
70
|
+
* bucket: 'my-bucket',
|
|
71
|
+
* access_key: 'AKIA...',
|
|
72
|
+
* secret_key: process.env.S3_SECRET_KEY,
|
|
73
|
+
* });
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
create(data: CreateStorageProviderData): Promise<StorageProviderAttributes & {
|
|
77
|
+
id: number;
|
|
78
|
+
}>;
|
|
79
|
+
/**
|
|
80
|
+
* Delete a storage provider. Forge refuses when a backup configuration uses it.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* await forge.storageProviders.delete(12);
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
delete(providerId: number): Promise<void>;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=storage-providers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-providers.d.ts","sourceRoot":"","sources":["../../src/resources/storage-providers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EAGzB,yBAAyB,EAC1B,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,qBAAa,0BAA2B,SAAQ,cAAc;IAC5D,gBAAgB;IAEhB,OAAO,KAAK,QAAQ,GAEnB;IAED;;;;;;;;;;OAUG;IACG,IAAI,CACR,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC,KAAK,CAAC,yBAAyB,GAAG;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAM5D;IAED;;;;;;;OAOG;IACH,GAAG,IAAI,sBAAsB,CAAC,yBAAyB,GAAG;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAaxE;IAED;;;;;;;OAOG;IACG,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,GAAG;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAKjF;IAED;;;;;;;;;;;;;;;OAeG;IACG,MAAM,CACV,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,yBAAyB,GAAG;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAMrD;IAED;;;;;;;OAOG;IACG,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9C;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@studiometa/forge-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
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": "tsgo -p tsconfig.typecheck.json --noEmit"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@studiometa/forge-api": "0.
|
|
47
|
+
"@studiometa/forge-api": "0.5.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@typescript/native-preview": "^7.0.0-dev.20260409.1",
|