gigadrive 2.6.2 → 2.7.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/dist/index.cjs CHANGED
@@ -24,15 +24,15 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  ));
25
25
 
26
26
  // src/index.ts
27
- var import_cli15 = require("@effect/cli");
27
+ var import_cli16 = require("@effect/cli");
28
28
  var import_platform_node = require("@effect/platform-node");
29
29
  var import_network_config2 = require("@gigadrive/network-config");
30
- var import_effect29 = require("effect");
30
+ var import_effect30 = require("effect");
31
31
 
32
32
  // package.json
33
33
  var package_default = {
34
34
  name: "gigadrive",
35
- version: "2.6.2",
35
+ version: "2.7.0",
36
36
  repository: {
37
37
  type: "git",
38
38
  url: "https://github.com/Gigadrive/sdk.git",
@@ -149,7 +149,9 @@ var UserInfoFetchError = class extends import_effect.Schema.TaggedError()("UserI
149
149
  var ApiRequestError = class extends import_effect.Schema.TaggedError()("ApiRequestError", {
150
150
  message: import_effect.Schema.String,
151
151
  statusCode: import_effect.Schema.optional(import_effect.Schema.Number),
152
- code: import_effect.Schema.optional(import_effect.Schema.String)
152
+ code: import_effect.Schema.optional(import_effect.Schema.String),
153
+ /** Finer-grained reason next to `code`, for example `daily_add_limit`. */
154
+ reason: import_effect.Schema.optional(import_effect.Schema.String)
153
155
  }) {
154
156
  };
155
157
  var InvalidEnvVarFormatError = class extends import_effect.Schema.TaggedError()(
@@ -163,6 +165,30 @@ var EnvVarNotFoundError = class extends import_effect.Schema.TaggedError()("EnvV
163
165
  message: import_effect.Schema.String
164
166
  }) {
165
167
  };
168
+ var DomainNotFoundError = class extends import_effect.Schema.TaggedError()("DomainNotFoundError", {
169
+ message: import_effect.Schema.String
170
+ }) {
171
+ };
172
+ var DomainWaitError = class extends import_effect.Schema.TaggedError()("DomainWaitError", {
173
+ message: import_effect.Schema.String,
174
+ state: import_effect.Schema.String
175
+ }) {
176
+ };
177
+ var InvalidDomainOptionsError = class extends import_effect.Schema.TaggedError()(
178
+ "InvalidDomainOptionsError",
179
+ { message: import_effect.Schema.String }
180
+ ) {
181
+ };
182
+ var ConfirmationRequiredError = class extends import_effect.Schema.TaggedError()(
183
+ "ConfirmationRequiredError",
184
+ { message: import_effect.Schema.String }
185
+ ) {
186
+ };
187
+ var OrganizationRequiredError = class extends import_effect.Schema.TaggedError()(
188
+ "OrganizationRequiredError",
189
+ { message: import_effect.Schema.String }
190
+ ) {
191
+ };
166
192
  var NoApplicationsFoundError = class extends import_effect.Schema.TaggedError()(
167
193
  "NoApplicationsFoundError",
168
194
  {
@@ -964,7 +990,12 @@ var ServiceCredentials = import_effect6.Config.all({
964
990
  });
965
991
  var toApiRequestError = (error) => {
966
992
  if (error instanceof import_sdk.ApiError) {
967
- return new ApiRequestError({ message: error.message, statusCode: error.status, code: error.code });
993
+ return new ApiRequestError({
994
+ message: error.message,
995
+ statusCode: error.status,
996
+ code: error.code,
997
+ reason: error.reason
998
+ });
968
999
  }
969
1000
  return new ApiRequestError({ message: error instanceof Error ? error.message : String(error) });
970
1001
  };
@@ -1607,7 +1638,8 @@ var wrapParseErrors = (effect) => effect.pipe(
1607
1638
  ConfigModuleLoadError: (e) => import_effect12.Effect.fail(new ConfigParseError({ message: e.message, cause: e.cause ?? e.filePath })),
1608
1639
  ConfigVersionError: (e) => import_effect12.Effect.fail(new ConfigParseError({ message: e.message, cause: e.filePath })),
1609
1640
  ConfigSchemaValidationError: (e) => import_effect12.Effect.fail(new ConfigParseError({ message: e.message, cause: e.validationErrors.join(", ") })),
1610
- FunctionConfigError: (e) => import_effect12.Effect.fail(new ConfigParseError({ message: e.message, cause: e.functionPath }))
1641
+ FunctionConfigError: (e) => import_effect12.Effect.fail(new ConfigParseError({ message: e.message, cause: e.functionPath })),
1642
+ ContainerConfigError: (e) => import_effect12.Effect.fail(new ConfigParseError({ message: e.message, cause: e.filePath ?? e.containerName }))
1611
1643
  })
1612
1644
  );
1613
1645
  var ProjectConfigService = class extends import_effect12.Effect.Service()("ProjectConfigService", {
@@ -1654,12 +1686,18 @@ var ProjectConfigService = class extends import_effect12.Effect.Service()("Proje
1654
1686
  config = yield* wrapParseErrors((0, import_network_config.postProcessConfig)(detection.config, cwd));
1655
1687
  framework = { name: detection.framework.name, slug: detection.framework.slug };
1656
1688
  } else {
1657
- return yield* import_effect12.Effect.fail(
1658
- new ConfigNotFoundError({
1659
- message: "No config file found and no framework detected.",
1660
- directory: cwd
1661
- })
1689
+ const containerProject = yield* wrapParseErrors(
1690
+ (0, import_network_config.detectContainerProject)(cwd).pipe(import_effect12.Effect.map((result) => result?.config ?? null))
1662
1691
  );
1692
+ if (containerProject === null) {
1693
+ return yield* import_effect12.Effect.fail(
1694
+ new ConfigNotFoundError({
1695
+ message: "No config file, framework, Compose file or Dockerfile found.",
1696
+ directory: cwd
1697
+ })
1698
+ );
1699
+ }
1700
+ config = yield* wrapParseErrors((0, import_network_config.postProcessConfig)(containerProject, cwd));
1663
1701
  }
1664
1702
  for (const warning of config.warnings) {
1665
1703
  yield* import_effect12.Effect.logWarning(warning);
@@ -1799,13 +1837,553 @@ var deploymentsCommand = deploymentsBase.pipe(
1799
1837
  import_cli6.Command.withSubcommands([deploymentsListCommand, deploymentsInspectCommand])
1800
1838
  );
1801
1839
 
1802
- // src/commands/env/index.ts
1840
+ // src/commands/domains/index.ts
1803
1841
  var import_cli7 = require("@effect/cli");
1804
- var import_effect19 = require("effect");
1842
+ var import_effect16 = require("effect");
1843
+
1844
+ // src/lib/domain-output.ts
1845
+ var DOMAIN_STATE_LABELS = {
1846
+ pending_ownership: "verifying ownership",
1847
+ pending_dns: "waiting for DNS",
1848
+ issuing_certificate: "issuing certificate",
1849
+ active: "active",
1850
+ degraded: "needs attention",
1851
+ failed: "failed",
1852
+ suspended: "suspended",
1853
+ removing: "removing"
1854
+ };
1855
+ var RECORD_STATUS_LABELS = {
1856
+ ok: "found",
1857
+ pending: "waiting",
1858
+ mismatch: "different value"
1859
+ };
1860
+ var IN_PROGRESS_STATES = /* @__PURE__ */ new Set([
1861
+ "pending_ownership",
1862
+ "pending_dns",
1863
+ "issuing_certificate"
1864
+ ]);
1865
+ var formatDnsRecords = (records) => {
1866
+ if (records.length === 0) return [];
1867
+ const rows = [
1868
+ ["Type", "Name", "Value", "Status"],
1869
+ ...records.map((record) => [record.type, record.host, record.value, RECORD_STATUS_LABELS[record.status]])
1870
+ ];
1871
+ const widths = [0, 1, 2].map((column) => Math.max(...rows.map((row) => row[column].length)));
1872
+ return rows.map(
1873
+ (row) => row.map((cell, column) => column < widths.length ? cell.padEnd(widths[column]) : cell).join(" ").trimEnd()
1874
+ );
1875
+ };
1876
+ var describeDomain = (domain) => {
1877
+ const lines = [
1878
+ `${domain.unicodeHostname} ${DOMAIN_STATE_LABELS[domain.state]}${domain.primary ? " (primary)" : ""}`
1879
+ ];
1880
+ if (domain.target.type === "redirect" && domain.target.redirectTo !== null) {
1881
+ lines.push(`Redirects to ${domain.target.redirectTo} (${domain.target.redirectStatusCode ?? 308})`);
1882
+ } else if (domain.target.type === "branch") {
1883
+ lines.push(`Serves branch ${domain.target.branchId ?? "unknown"}`);
1884
+ }
1885
+ if (domain.error !== null) lines.push(`Problem (${domain.error.code}): ${domain.error.message}`);
1886
+ if (domain.certificate.expiresAt !== null) lines.push(`Certificate expires ${domain.certificate.expiresAt}`);
1887
+ return lines;
1888
+ };
1889
+
1890
+ // src/commands/domains/index.ts
1891
+ var REDIRECT_STATUS_CODES = ["301", "302", "307", "308"];
1892
+ var CONSOLE_URL = "https://console.gigadrive.de";
1893
+ var POLL_INTERVAL = import_effect16.Duration.seconds(5);
1894
+ var appOption3 = import_cli7.Options.text("app").pipe(
1895
+ import_cli7.Options.withAlias("a"),
1896
+ import_cli7.Options.withDescription("Operate on this application (overrides the linked application)"),
1897
+ import_cli7.Options.optional
1898
+ );
1899
+ var orgOption3 = import_cli7.Options.text("org").pipe(
1900
+ import_cli7.Options.withAlias("o"),
1901
+ import_cli7.Options.withDescription("Operate on this organization (defaults to the linked project\u2019s organization)"),
1902
+ import_cli7.Options.optional
1903
+ );
1904
+ var jsonOption = import_cli7.Options.boolean("json").pipe(
1905
+ import_cli7.Options.withDescription("Print only the result as JSON on stdout; progress goes to stderr")
1906
+ );
1907
+ var waitOption = import_cli7.Options.boolean("wait").pipe(
1908
+ import_cli7.Options.withAlias("w"),
1909
+ import_cli7.Options.withDescription("Wait until the domain serves traffic, printing each state change")
1910
+ );
1911
+ var timeoutOption = import_cli7.Options.integer("timeout").pipe(
1912
+ import_cli7.Options.withDescription("Minutes to wait with --wait, at least 1 (default: 10)"),
1913
+ import_cli7.Options.withDefault(10)
1914
+ );
1915
+ var branchOption = import_cli7.Options.text("branch").pipe(
1916
+ import_cli7.Options.withDescription("Serve the latest deployment of this branch ID instead of production"),
1917
+ import_cli7.Options.optional
1918
+ );
1919
+ var productionOption = import_cli7.Options.boolean("production").pipe(
1920
+ import_cli7.Options.withDescription("Serve the production deployment (the default for new domains)")
1921
+ );
1922
+ var redirectToOption = import_cli7.Options.text("redirect-to").pipe(
1923
+ import_cli7.Options.withDescription("Redirect every request to this hostname instead of serving the application"),
1924
+ import_cli7.Options.optional
1925
+ );
1926
+ var statusOption2 = import_cli7.Options.choice("status", REDIRECT_STATUS_CODES).pipe(
1927
+ import_cli7.Options.withDescription("Redirect status code with --redirect-to (default: 308)"),
1928
+ import_cli7.Options.optional
1929
+ );
1930
+ var dropPathOption = import_cli7.Options.boolean("drop-path").pipe(
1931
+ import_cli7.Options.withDescription("With --redirect-to, redirect to the root instead of keeping the path and query")
1932
+ );
1933
+ var primaryOption = import_cli7.Options.boolean("primary").pipe(
1934
+ import_cli7.Options.withDescription("Make this domain the application\u2019s primary URL")
1935
+ );
1936
+ var yesOption = import_cli7.Options.boolean("yes").pipe(
1937
+ import_cli7.Options.withAlias("y"),
1938
+ import_cli7.Options.withDescription("Skip the confirmation prompt (required when not running in a terminal)")
1939
+ );
1940
+ var hostnameArg = import_cli7.Args.text({ name: "hostname" }).pipe(
1941
+ import_cli7.Args.withDescription("Hostname to attach, e.g. shop.example.com or example.com")
1942
+ );
1943
+ var domainArg = import_cli7.Args.text({ name: "hostname-or-id" }).pipe(import_cli7.Args.withDescription("Domain hostname or ID"));
1944
+ var targetFromFlags = (flags) => import_effect16.Effect.gen(function* () {
1945
+ const chosen = [flags.production, import_effect16.Option.isSome(flags.branch), import_effect16.Option.isSome(flags.redirectTo)].filter(Boolean);
1946
+ if (chosen.length > 1) {
1947
+ return yield* new InvalidDomainOptionsError({
1948
+ message: "Choose one target: --production, --branch or --redirect-to."
1949
+ });
1950
+ }
1951
+ if (import_effect16.Option.isNone(flags.redirectTo) && (import_effect16.Option.isSome(flags.status) || flags.dropPath)) {
1952
+ return yield* new InvalidDomainOptionsError({
1953
+ message: "--status and --drop-path only apply together with --redirect-to."
1954
+ });
1955
+ }
1956
+ if (import_effect16.Option.isSome(flags.redirectTo)) {
1957
+ const target = {
1958
+ type: "redirect",
1959
+ to: flags.redirectTo.value,
1960
+ statusCode: import_effect16.Option.match(flags.status, {
1961
+ onNone: () => void 0,
1962
+ onSome: (code) => code === "301" ? 301 : code === "302" ? 302 : code === "307" ? 307 : 308
1963
+ }),
1964
+ preservePath: !flags.dropPath
1965
+ };
1966
+ return target;
1967
+ }
1968
+ if (import_effect16.Option.isSome(flags.branch)) {
1969
+ const target = { type: "branch", branchId: flags.branch.value };
1970
+ return target;
1971
+ }
1972
+ if (flags.production) {
1973
+ const target = { type: "production" };
1974
+ return target;
1975
+ }
1976
+ return void 0;
1977
+ });
1978
+ var requirePositiveTimeout = (minutes) => minutes >= 1 ? import_effect16.Effect.succeed(minutes) : new InvalidDomainOptionsError({ message: "--timeout must be at least 1 minute." });
1979
+ var confirm = (message, yes) => import_effect16.Effect.gen(function* () {
1980
+ if (yes) return true;
1981
+ if (process.stdin.isTTY !== true) {
1982
+ return yield* new ConfirmationRequiredError({
1983
+ message: "Not running in a terminal, so there is no way to confirm. Pass --yes to proceed."
1984
+ });
1985
+ }
1986
+ return yield* import_cli7.Prompt.run(import_cli7.Prompt.confirm({ message, initial: false }));
1987
+ });
1988
+ var resolveApplication = (app) => import_effect16.Option.match(app, {
1989
+ onSome: (value) => import_effect16.Effect.succeed(value),
1990
+ onNone: () => import_effect16.Effect.gen(function* () {
1991
+ const projectLink = yield* ProjectLinkService;
1992
+ const link = yield* projectLink.resolve(process.cwd());
1993
+ return link.applicationId;
1994
+ })
1995
+ });
1996
+ var resolveOrganization = (org) => import_effect16.Option.match(org, {
1997
+ onSome: (value) => import_effect16.Effect.succeed(value),
1998
+ onNone: () => import_effect16.Effect.gen(function* () {
1999
+ const projectLink = yield* ProjectLinkService;
2000
+ const link = yield* projectLink.load(process.cwd());
2001
+ const organizationId = import_effect16.Option.flatMap(link, (value) => import_effect16.Option.fromNullable(value.organizationId));
2002
+ if (import_effect16.Option.isNone(organizationId)) {
2003
+ return yield* new OrganizationRequiredError({
2004
+ message: "Pass --org, or run the command in a linked project."
2005
+ });
2006
+ }
2007
+ return organizationId.value;
2008
+ })
2009
+ });
2010
+ var normalizeHostname = (value) => value.trim().toLowerCase().replace(/\.$/, "");
2011
+ var findDomain = (applicationId, hostnameOrId) => import_effect16.Effect.gen(function* () {
2012
+ const apiClient = yield* ApiClientService;
2013
+ const { items } = yield* apiClient.request((client) => client.applications.domains.list(applicationId));
2014
+ const wanted = normalizeHostname(hostnameOrId);
2015
+ const domain = items.find(
2016
+ (item) => item.id === hostnameOrId || item.hostname === wanted || item.unicodeHostname === wanted
2017
+ );
2018
+ if (!domain) {
2019
+ return yield* new DomainNotFoundError({ message: `No custom domain ${hostnameOrId} on this application.` });
2020
+ }
2021
+ return domain;
2022
+ });
2023
+ var printDomain = (domain) => import_effect16.Effect.gen(function* () {
2024
+ for (const line of describeDomain(domain)) yield* import_effect16.Console.log(line);
2025
+ const pending = domain.requiredRecords.filter((record) => record.status !== "ok");
2026
+ const records = formatDnsRecords(pending);
2027
+ if (records.length > 0 && domain.state !== "removing") {
2028
+ yield* import_effect16.Console.log("\nAdd these records at your DNS provider:");
2029
+ for (const line of records) yield* import_effect16.Console.log(` ${line}`);
2030
+ if (pending.some((record) => record.type === "ALIAS")) {
2031
+ yield* import_effect16.Console.log(
2032
+ "\nApex domains need an ALIAS, ANAME or flattened CNAME record. Without one, attach www instead and redirect the apex to it."
2033
+ );
2034
+ }
2035
+ }
2036
+ });
2037
+ var isTransient = (error) => error._tag === "ApiRequestError" && (error.statusCode === void 0 || error.statusCode === 429 || error.statusCode >= 500);
2038
+ var waitUntilServing = (applicationId, initial, timeoutMinutes, json) => import_effect16.Effect.gen(function* () {
2039
+ const apiClient = yield* ApiClientService;
2040
+ const progress = (line) => json ? import_effect16.Console.error(line) : import_effect16.Console.log(line);
2041
+ const fail = (domain2, message) => import_effect16.Effect.gen(function* () {
2042
+ if (json) yield* import_effect16.Console.log(JSON.stringify(domain2, null, 2));
2043
+ return yield* new DomainWaitError({ message, state: domain2.state });
2044
+ });
2045
+ const deadline = (yield* import_effect16.Clock.currentTimeMillis) + import_effect16.Duration.toMillis(import_effect16.Duration.minutes(timeoutMinutes));
2046
+ let domain = initial;
2047
+ yield* progress(`Waiting for ${domain.unicodeHostname} (${DOMAIN_STATE_LABELS[domain.state]})...`);
2048
+ while (IN_PROGRESS_STATES.has(domain.state)) {
2049
+ const remaining = deadline - (yield* import_effect16.Clock.currentTimeMillis);
2050
+ if (remaining <= 0) {
2051
+ return yield* fail(
2052
+ domain,
2053
+ `${domain.unicodeHostname} is not serving yet (${DOMAIN_STATE_LABELS[domain.state]}). Check again later with "gigadrive domains inspect ${domain.hostname}".`
2054
+ );
2055
+ }
2056
+ yield* import_effect16.Effect.sleep(import_effect16.Duration.min(POLL_INTERVAL, import_effect16.Duration.millis(remaining)));
2057
+ const polled = yield* import_effect16.Effect.either(
2058
+ apiClient.request((client) => client.applications.domains.get(applicationId, domain.id))
2059
+ );
2060
+ if (import_effect16.Either.isLeft(polled)) {
2061
+ if (isTransient(polled.left)) continue;
2062
+ return yield* polled.left;
2063
+ }
2064
+ if (polled.right.state !== domain.state) {
2065
+ yield* progress(` ${DOMAIN_STATE_LABELS[polled.right.state]}`);
2066
+ }
2067
+ domain = polled.right;
2068
+ }
2069
+ if (domain.state !== "active" && domain.state !== "degraded") {
2070
+ return yield* fail(
2071
+ domain,
2072
+ `${domain.unicodeHostname} is ${DOMAIN_STATE_LABELS[domain.state]}${domain.error ? `: ${domain.error.message}` : ""}`
2073
+ );
2074
+ }
2075
+ yield* progress(`
2076
+ ${domain.unicodeHostname} is live: https://${domain.hostname}`);
2077
+ if (json) yield* import_effect16.Console.log(JSON.stringify(domain, null, 2));
2078
+ return domain;
2079
+ });
2080
+ var errorMessage = (action, error) => {
2081
+ switch (error._tag) {
2082
+ case "NotAuthenticatedError":
2083
+ return 'You are not logged in. Run "gigadrive login" to authenticate.';
2084
+ case "ApiRequestError":
2085
+ if (error.code === "quota_exceeded" && error.reason === "daily_add_limit") {
2086
+ return `${error.message}
2087
+ The daily limit resets within 24 hours; upgrading your plan raises it.`;
2088
+ }
2089
+ if (error.code === "quota_exceeded") {
2090
+ return `${error.message}
2091
+ See your plan's limits and upgrade at ${CONSOLE_URL} (organization settings > Limits).`;
2092
+ }
2093
+ if (error.code === "invalid_target" && error.reason === "redirects_not_available") {
2094
+ return `${error.message}
2095
+ Redirect domains are available on paid plans. Upgrade at ${CONSOLE_URL}.`;
2096
+ }
2097
+ if (error.code === "domain_in_use" && error.reason === "other_organization") {
2098
+ return `${error.message}
2099
+ If you control the domain, verify it with "gigadrive domains owners add <domain>", then move it with "gigadrive domains claim <hostname>".`;
2100
+ }
2101
+ if (error.reason === "ownership_not_live") {
2102
+ return `${error.message}
2103
+ Publish the TXT record shown by "gigadrive domains owners list" again, wait for DNS to update, then retry the claim.`;
2104
+ }
2105
+ return `Failed to ${action}: ${error.message}`;
2106
+ default:
2107
+ return error.message;
2108
+ }
2109
+ };
2110
+ var reportErrors = (action) => (self) => import_effect16.Effect.tapError(self, (error) => import_effect16.Console.error(errorMessage(action, error)));
2111
+ var listCommand = import_cli7.Command.make(
2112
+ "list",
2113
+ { app: appOption3, json: jsonOption },
2114
+ ({ app, json }) => import_effect16.Effect.gen(function* () {
2115
+ const apiClient = yield* ApiClientService;
2116
+ const applicationId = yield* resolveApplication(app);
2117
+ const { items } = yield* apiClient.request((client) => client.applications.domains.list(applicationId));
2118
+ if (json) return yield* import_effect16.Console.log(JSON.stringify(items, null, 2));
2119
+ if (items.length === 0) {
2120
+ return yield* import_effect16.Console.log('No custom domains. Add one with "gigadrive domains add <hostname>".');
2121
+ }
2122
+ const width = Math.max(...items.map((item) => item.unicodeHostname.length));
2123
+ for (const item of items) {
2124
+ const problem = item.error ? ` ${item.error.code}` : "";
2125
+ yield* import_effect16.Console.log(
2126
+ `${item.unicodeHostname.padEnd(width)} ${DOMAIN_STATE_LABELS[item.state]}${item.primary ? " (primary)" : ""}${problem}`
2127
+ );
2128
+ }
2129
+ }).pipe(reportErrors("list custom domains"))
2130
+ );
2131
+ var addDomain = (input) => import_effect16.Effect.gen(function* () {
2132
+ const apiClient = yield* ApiClientService;
2133
+ const target = yield* targetFromFlags(input);
2134
+ const timeout = yield* requirePositiveTimeout(input.timeout);
2135
+ const domain = yield* apiClient.request(
2136
+ (client) => client.applications.domains.add(input.applicationId, { hostname: input.hostname, target })
2137
+ );
2138
+ if (input.wait) return yield* waitUntilServing(input.applicationId, domain, timeout, input.json);
2139
+ if (input.json) {
2140
+ yield* import_effect16.Console.log(JSON.stringify(domain, null, 2));
2141
+ return domain;
2142
+ }
2143
+ yield* printDomain(domain);
2144
+ if (IN_PROGRESS_STATES.has(domain.state)) {
2145
+ yield* import_effect16.Console.log(
2146
+ `
2147
+ Gigadrive checks the records automatically. Follow progress with "gigadrive domains inspect ${domain.hostname}".`
2148
+ );
2149
+ }
2150
+ return domain;
2151
+ });
2152
+ var addCommand = import_cli7.Command.make(
2153
+ "add",
2154
+ {
2155
+ hostname: hostnameArg,
2156
+ app: appOption3,
2157
+ production: productionOption,
2158
+ branch: branchOption,
2159
+ redirectTo: redirectToOption,
2160
+ status: statusOption2,
2161
+ dropPath: dropPathOption,
2162
+ wait: waitOption,
2163
+ timeout: timeoutOption,
2164
+ json: jsonOption
2165
+ },
2166
+ ({ app, ...options }) => import_effect16.Effect.gen(function* () {
2167
+ const applicationId = yield* resolveApplication(app);
2168
+ yield* addDomain({ ...options, applicationId });
2169
+ }).pipe(reportErrors("add the domain"))
2170
+ );
2171
+ var updateCommand = import_cli7.Command.make(
2172
+ "update",
2173
+ {
2174
+ domain: domainArg,
2175
+ app: appOption3,
2176
+ production: productionOption,
2177
+ branch: branchOption,
2178
+ redirectTo: redirectToOption,
2179
+ status: statusOption2,
2180
+ dropPath: dropPathOption,
2181
+ primary: primaryOption,
2182
+ json: jsonOption
2183
+ },
2184
+ ({ domain: hostnameOrId, app, primary, json, ...flags }) => import_effect16.Effect.gen(function* () {
2185
+ const apiClient = yield* ApiClientService;
2186
+ const target = yield* targetFromFlags(flags);
2187
+ if (target === void 0 && !primary) {
2188
+ return yield* new InvalidDomainOptionsError({
2189
+ message: "Nothing to change. Pass --production, --branch, --redirect-to or --primary."
2190
+ });
2191
+ }
2192
+ const applicationId = yield* resolveApplication(app);
2193
+ const found = yield* findDomain(applicationId, hostnameOrId);
2194
+ const domain = yield* apiClient.request(
2195
+ (client) => client.applications.domains.update(applicationId, found.id, {
2196
+ ...target === void 0 ? {} : { target },
2197
+ ...primary ? { primary: true } : {}
2198
+ })
2199
+ );
2200
+ if (json) return yield* import_effect16.Console.log(JSON.stringify(domain, null, 2));
2201
+ yield* printDomain(domain);
2202
+ }).pipe(reportErrors("update the domain"))
2203
+ );
2204
+ var claimCommand = import_cli7.Command.make(
2205
+ "claim",
2206
+ {
2207
+ hostname: hostnameArg.pipe(import_cli7.Args.withDescription("Hostname another organization attached")),
2208
+ app: appOption3,
2209
+ json: jsonOption
2210
+ },
2211
+ ({ hostname: hostname2, app, json }) => import_effect16.Effect.gen(function* () {
2212
+ const apiClient = yield* ApiClientService;
2213
+ const applicationId = yield* resolveApplication(app);
2214
+ const domain = yield* apiClient.request((client) => client.applications.domains.claim(applicationId, hostname2));
2215
+ if (json) return yield* import_effect16.Console.log(JSON.stringify(domain, null, 2));
2216
+ yield* import_effect16.Console.log(`Moved ${domain.unicodeHostname} to this application.`);
2217
+ yield* printDomain(domain);
2218
+ }).pipe(reportErrors("claim the domain"))
2219
+ );
2220
+ var inspectCommand = import_cli7.Command.make(
2221
+ "inspect",
2222
+ { domain: domainArg, app: appOption3, json: jsonOption },
2223
+ ({ domain: hostnameOrId, app, json }) => import_effect16.Effect.gen(function* () {
2224
+ const applicationId = yield* resolveApplication(app);
2225
+ const domain = yield* findDomain(applicationId, hostnameOrId);
2226
+ if (json) return yield* import_effect16.Console.log(JSON.stringify(domain, null, 2));
2227
+ yield* printDomain(domain);
2228
+ if (domain.nextCheckAt !== null) yield* import_effect16.Console.log(`
2229
+ Next automatic check: ${domain.nextCheckAt}`);
2230
+ }).pipe(reportErrors("inspect the domain"))
2231
+ );
2232
+ var checkCommand = import_cli7.Command.make(
2233
+ "check",
2234
+ { domain: domainArg, app: appOption3, wait: waitOption, timeout: timeoutOption, json: jsonOption },
2235
+ ({ domain: hostnameOrId, app, wait, timeout, json }) => import_effect16.Effect.gen(function* () {
2236
+ const apiClient = yield* ApiClientService;
2237
+ const minutes = yield* requirePositiveTimeout(timeout);
2238
+ const applicationId = yield* resolveApplication(app);
2239
+ const found = yield* findDomain(applicationId, hostnameOrId);
2240
+ const domain = yield* apiClient.request((client) => client.applications.domains.refresh(applicationId, found.id));
2241
+ if (wait) return yield* waitUntilServing(applicationId, domain, minutes, json);
2242
+ if (json) return yield* import_effect16.Console.log(JSON.stringify(domain, null, 2));
2243
+ yield* import_effect16.Console.log(`Checking ${domain.unicodeHostname}.`);
2244
+ yield* printDomain(domain);
2245
+ }).pipe(reportErrors("check the domain"))
2246
+ );
2247
+ var removeDomain = (applicationId, hostnameOrId, yes) => import_effect16.Effect.gen(function* () {
2248
+ const apiClient = yield* ApiClientService;
2249
+ const domain = yield* findDomain(applicationId, hostnameOrId);
2250
+ const confirmed = yield* confirm(
2251
+ `Remove ${domain.unicodeHostname}? It stops serving this application immediately.`,
2252
+ yes
2253
+ );
2254
+ if (!confirmed) return yield* import_effect16.Console.log("Cancelled.");
2255
+ yield* apiClient.request((client) => client.applications.domains.remove(applicationId, domain.id));
2256
+ yield* import_effect16.Console.log(`Removed ${domain.unicodeHostname}.`);
2257
+ });
2258
+ var removeCommand = import_cli7.Command.make(
2259
+ "rm",
2260
+ { domain: domainArg, app: appOption3, yes: yesOption },
2261
+ ({ domain: hostnameOrId, app, yes }) => import_effect16.Effect.gen(function* () {
2262
+ const applicationId = yield* resolveApplication(app);
2263
+ yield* removeDomain(applicationId, hostnameOrId, yes);
2264
+ }).pipe(
2265
+ // Ctrl+C at the confirmation is a deliberate cancel, not a failure.
2266
+ import_effect16.Effect.catchTag("QuitException", () => import_effect16.Console.log("Cancelled.")),
2267
+ reportErrors("remove the domain")
2268
+ )
2269
+ );
2270
+ var findOwnership = (organizationId, name) => import_effect16.Effect.gen(function* () {
2271
+ const apiClient = yield* ApiClientService;
2272
+ const { items } = yield* apiClient.request((client) => client.organizations.domains.list(organizationId));
2273
+ const wanted = normalizeHostname(name);
2274
+ const claim = items.find((item) => item.id === name || item.name === wanted || item.unicodeName === wanted);
2275
+ if (!claim) {
2276
+ return yield* new DomainNotFoundError({
2277
+ message: `${name} is not claimed. Add it with "gigadrive domains owners add".`
2278
+ });
2279
+ }
2280
+ return claim;
2281
+ });
2282
+ var ownersListCommand = import_cli7.Command.make(
2283
+ "list",
2284
+ { org: orgOption3, json: jsonOption },
2285
+ ({ org, json }) => import_effect16.Effect.gen(function* () {
2286
+ const apiClient = yield* ApiClientService;
2287
+ const organizationId = yield* resolveOrganization(org);
2288
+ const { items } = yield* apiClient.request((client) => client.organizations.domains.list(organizationId));
2289
+ if (json) return yield* import_effect16.Console.log(JSON.stringify(items, null, 2));
2290
+ if (items.length === 0) return yield* import_effect16.Console.log("No verified domains.");
2291
+ const width = Math.max(...items.map((item) => item.unicodeName.length));
2292
+ for (const item of items) {
2293
+ yield* import_effect16.Console.log(`${item.unicodeName.padEnd(width)} ${item.status}`);
2294
+ }
2295
+ }).pipe(reportErrors("list verified domains"))
2296
+ );
2297
+ var ownersAddCommand = import_cli7.Command.make(
2298
+ "add",
2299
+ {
2300
+ name: import_cli7.Args.text({ name: "domain" }).pipe(import_cli7.Args.withDescription("Domain to verify, e.g. example.com")),
2301
+ org: orgOption3,
2302
+ json: jsonOption
2303
+ },
2304
+ ({ name, org, json }) => import_effect16.Effect.gen(function* () {
2305
+ const apiClient = yield* ApiClientService;
2306
+ const organizationId = yield* resolveOrganization(org);
2307
+ const claim = yield* apiClient.request((client) => client.organizations.domains.add(organizationId, name));
2308
+ if (json) return yield* import_effect16.Console.log(JSON.stringify(claim, null, 2));
2309
+ if (claim.status === "verified") {
2310
+ return yield* import_effect16.Console.log(`${claim.unicodeName} is verified.`);
2311
+ }
2312
+ yield* import_effect16.Console.log(`Publish this TXT record for ${claim.unicodeName}:`);
2313
+ yield* import_effect16.Console.log(` Name: ${claim.record.host}`);
2314
+ yield* import_effect16.Console.log(` Value: ${claim.record.value}`);
2315
+ yield* import_effect16.Console.log(`
2316
+ Then run "gigadrive domains owners verify ${claim.name}".`);
2317
+ }).pipe(reportErrors("add the domain"))
2318
+ );
2319
+ var ownersVerifyCommand = import_cli7.Command.make(
2320
+ "verify",
2321
+ { name: import_cli7.Args.text({ name: "domain" }).pipe(import_cli7.Args.withDescription("Domain to verify")), org: orgOption3 },
2322
+ ({ name, org }) => import_effect16.Effect.gen(function* () {
2323
+ const apiClient = yield* ApiClientService;
2324
+ const organizationId = yield* resolveOrganization(org);
2325
+ const claim = yield* findOwnership(organizationId, name);
2326
+ const checked = yield* apiClient.request(
2327
+ (client) => client.organizations.domains.verify(organizationId, claim.id)
2328
+ );
2329
+ if (checked.status === "verified") {
2330
+ return yield* import_effect16.Console.log(`${checked.unicodeName} is verified.`);
2331
+ }
2332
+ yield* import_effect16.Console.log(
2333
+ `${checked.unicodeName} is not verified yet${checked.error ? `: ${checked.error.message}` : "."} Gigadrive keeps checking automatically.`
2334
+ );
2335
+ }).pipe(reportErrors("verify the domain"))
2336
+ );
2337
+ var ownersRemoveCommand = import_cli7.Command.make(
2338
+ "rm",
2339
+ {
2340
+ name: import_cli7.Args.text({ name: "domain" }).pipe(import_cli7.Args.withDescription("Domain to remove")),
2341
+ org: orgOption3,
2342
+ yes: yesOption
2343
+ },
2344
+ ({ name, org, yes }) => import_effect16.Effect.gen(function* () {
2345
+ const apiClient = yield* ApiClientService;
2346
+ const organizationId = yield* resolveOrganization(org);
2347
+ const claim = yield* findOwnership(organizationId, name);
2348
+ const confirmed = yield* confirm(
2349
+ `Remove ${claim.unicodeName} from your organization's domains? Custom domains that rely on it must be removed first.`,
2350
+ yes
2351
+ );
2352
+ if (!confirmed) return yield* import_effect16.Console.log("Cancelled.");
2353
+ yield* apiClient.request((client) => client.organizations.domains.remove(organizationId, claim.id));
2354
+ yield* import_effect16.Console.log(`Removed ${claim.unicodeName}.`);
2355
+ }).pipe(
2356
+ import_effect16.Effect.catchTag("QuitException", () => import_effect16.Console.log("Cancelled.")),
2357
+ reportErrors("remove the domain")
2358
+ )
2359
+ );
2360
+ var ownersCommand = import_cli7.Command.make("owners", {}, () => import_effect16.Effect.void).pipe(
2361
+ import_cli7.Command.withDescription("Domains your organization verified with a TXT record"),
2362
+ import_cli7.Command.withSubcommands([ownersListCommand, ownersAddCommand, ownersVerifyCommand, ownersRemoveCommand])
2363
+ );
2364
+ var domainsBase = import_cli7.Command.make("domains", {}, () => import_effect16.Effect.void).pipe(
2365
+ import_cli7.Command.withDescription("Custom domains of the linked application")
2366
+ );
2367
+ var domainsCommand = domainsBase.pipe(
2368
+ import_cli7.Command.withSubcommands([
2369
+ listCommand,
2370
+ addCommand,
2371
+ updateCommand,
2372
+ claimCommand,
2373
+ inspectCommand,
2374
+ checkCommand,
2375
+ removeCommand,
2376
+ ownersCommand
2377
+ ])
2378
+ );
2379
+
2380
+ // src/commands/env/index.ts
2381
+ var import_cli8 = require("@effect/cli");
2382
+ var import_effect20 = require("effect");
1805
2383
 
1806
2384
  // src/services/env-file.ts
1807
2385
  var import_platform6 = require("@effect/platform");
1808
- var import_effect16 = require("effect");
2386
+ var import_effect17 = require("effect");
1809
2387
 
1810
2388
  // src/lib/dotenv.ts
1811
2389
  var DEFAULT_ENV_HEADER = "# Generated by `gigadrive env pull` \u2014 do not edit by hand.";
@@ -1863,42 +2441,42 @@ var parseEnv = (content) => {
1863
2441
  };
1864
2442
 
1865
2443
  // src/services/env-file.ts
1866
- var EnvFileService = class extends import_effect16.Effect.Service()("EnvFileService", {
2444
+ var EnvFileService = class extends import_effect17.Effect.Service()("EnvFileService", {
1867
2445
  accessors: true,
1868
- effect: import_effect16.Effect.gen(function* () {
2446
+ effect: import_effect17.Effect.gen(function* () {
1869
2447
  const fs = yield* import_platform6.FileSystem.FileSystem;
1870
2448
  const pathService = yield* import_platform6.Path.Path;
1871
- const exists = import_effect16.Effect.fn("EnvFileService.exists")(function* (filePath) {
1872
- return yield* fs.exists(filePath).pipe(import_effect16.Effect.mapError(() => new EnvFileReadError({ message: `Failed to check whether ${filePath} exists` })));
2449
+ const exists = import_effect17.Effect.fn("EnvFileService.exists")(function* (filePath) {
2450
+ return yield* fs.exists(filePath).pipe(import_effect17.Effect.mapError(() => new EnvFileReadError({ message: `Failed to check whether ${filePath} exists` })));
1873
2451
  });
1874
- const read = import_effect16.Effect.fn("EnvFileService.read")(function* (filePath) {
2452
+ const read = import_effect17.Effect.fn("EnvFileService.read")(function* (filePath) {
1875
2453
  const present = yield* exists(filePath);
1876
- if (!present) return import_effect16.Option.none();
1877
- const contents = yield* fs.readFileString(filePath, "utf8").pipe(import_effect16.Effect.mapError(() => new EnvFileReadError({ message: `Failed to read ${filePath}` })));
1878
- return import_effect16.Option.some(contents);
2454
+ if (!present) return import_effect17.Option.none();
2455
+ const contents = yield* fs.readFileString(filePath, "utf8").pipe(import_effect17.Effect.mapError(() => new EnvFileReadError({ message: `Failed to read ${filePath}` })));
2456
+ return import_effect17.Option.some(contents);
1879
2457
  });
1880
- const write = import_effect16.Effect.fn("EnvFileService.write")(function* (filePath, entries, opts) {
2458
+ const write = import_effect17.Effect.fn("EnvFileService.write")(function* (filePath, entries, opts) {
1881
2459
  const dir = pathService.dirname(filePath);
1882
2460
  yield* fs.makeDirectory(dir, { recursive: true }).pipe(
1883
- import_effect16.Effect.mapError(
2461
+ import_effect17.Effect.mapError(
1884
2462
  (error) => new EnvFileWriteError({ message: `Failed to create directory for ${filePath}`, cause: String(error) })
1885
2463
  )
1886
2464
  );
1887
2465
  yield* fs.writeFileString(filePath, serializeEnv(entries, opts), { mode: 384 }).pipe(
1888
- import_effect16.Effect.mapError(
2466
+ import_effect17.Effect.mapError(
1889
2467
  (error) => new EnvFileWriteError({ message: `Failed to write ${filePath}`, cause: String(error) })
1890
2468
  )
1891
2469
  );
1892
2470
  yield* fs.chmod(filePath, 384).pipe(
1893
- import_effect16.Effect.mapError(
2471
+ import_effect17.Effect.mapError(
1894
2472
  (error) => new EnvFileWriteError({ message: `Failed to secure ${filePath}`, cause: String(error) })
1895
2473
  )
1896
2474
  );
1897
2475
  });
1898
- const ensureGitignored = import_effect16.Effect.fn("EnvFileService.ensureGitignored")(function* (dir, entry) {
2476
+ const ensureGitignored = import_effect17.Effect.fn("EnvFileService.ensureGitignored")(function* (dir, entry) {
1899
2477
  const gitignorePath = pathService.join(dir, ".gitignore");
1900
2478
  const existing = yield* read(gitignorePath);
1901
- const current = import_effect16.Option.getOrElse(existing, () => "");
2479
+ const current = import_effect17.Option.getOrElse(existing, () => "");
1902
2480
  const alreadyIgnored = current.split("\n").some((line) => line.trim() === entry);
1903
2481
  if (alreadyIgnored) {
1904
2482
  return false;
@@ -1906,7 +2484,7 @@ var EnvFileService = class extends import_effect16.Effect.Service()("EnvFileServ
1906
2484
  const separator = current.length > 0 && !current.endsWith("\n") ? "\n" : "";
1907
2485
  yield* fs.writeFileString(gitignorePath, `${current}${separator}${entry}
1908
2486
  `).pipe(
1909
- import_effect16.Effect.mapError(
2487
+ import_effect17.Effect.mapError(
1910
2488
  (error) => new EnvFileWriteError({ message: "Failed to update .gitignore", cause: String(error) })
1911
2489
  )
1912
2490
  );
@@ -1918,29 +2496,29 @@ var EnvFileService = class extends import_effect16.Effect.Service()("EnvFileServ
1918
2496
  };
1919
2497
 
1920
2498
  // src/services/local-credentials.ts
1921
- var import_effect18 = require("effect");
2499
+ var import_effect19 = require("effect");
1922
2500
  var os3 = __toESM(require("os"), 1);
1923
2501
 
1924
2502
  // src/services/dev-credentials-store.ts
1925
2503
  var import_platform7 = require("@effect/platform");
1926
- var import_effect17 = require("effect");
2504
+ var import_effect18 = require("effect");
1927
2505
  var os2 = __toESM(require("os"), 1);
1928
- var DevCredentialsStore = class extends import_effect17.Effect.Service()("DevCredentialsStore", {
2506
+ var DevCredentialsStore = class extends import_effect18.Effect.Service()("DevCredentialsStore", {
1929
2507
  accessors: true,
1930
- effect: import_effect17.Effect.gen(function* () {
2508
+ effect: import_effect18.Effect.gen(function* () {
1931
2509
  const fs = yield* import_platform7.FileSystem.FileSystem;
1932
2510
  const pathService = yield* import_platform7.Path.Path;
1933
2511
  const homeDir = os2.homedir();
1934
2512
  const storeDir = pathService.join(homeDir, ".gigadrive");
1935
2513
  const storeFile = pathService.join(storeDir, "dev-keys.json");
1936
- const ensureDirectory = import_effect17.Effect.gen(function* () {
2514
+ const ensureDirectory = import_effect18.Effect.gen(function* () {
1937
2515
  yield* fs.makeDirectory(storeDir, { recursive: true }).pipe(
1938
- import_effect17.Effect.mapError(
2516
+ import_effect18.Effect.mapError(
1939
2517
  (error) => new DevCredentialsStoreWriteError({ message: "Failed to create ~/.gigadrive", cause: String(error) })
1940
2518
  )
1941
2519
  );
1942
2520
  yield* fs.chmod(storeDir, 448).pipe(
1943
- import_effect17.Effect.mapError(
2521
+ import_effect18.Effect.mapError(
1944
2522
  (error) => new DevCredentialsStoreWriteError({
1945
2523
  message: "Failed to set ~/.gigadrive permissions",
1946
2524
  cause: String(error)
@@ -1948,30 +2526,30 @@ var DevCredentialsStore = class extends import_effect17.Effect.Service()("DevCre
1948
2526
  )
1949
2527
  );
1950
2528
  });
1951
- const load = import_effect17.Effect.gen(function* () {
1952
- const present = yield* fs.exists(storeFile).pipe(import_effect17.Effect.mapError(() => new DevCredentialsStoreReadError({ message: "Failed to check dev-keys.json" })));
2529
+ const load = import_effect18.Effect.gen(function* () {
2530
+ const present = yield* fs.exists(storeFile).pipe(import_effect18.Effect.mapError(() => new DevCredentialsStoreReadError({ message: "Failed to check dev-keys.json" })));
1953
2531
  if (!present) return {};
1954
- const data = yield* fs.readFileString(storeFile, "utf8").pipe(import_effect17.Effect.mapError(() => new DevCredentialsStoreReadError({ message: "Failed to read dev-keys.json" })));
1955
- const json = yield* import_effect17.Effect.try({
2532
+ const data = yield* fs.readFileString(storeFile, "utf8").pipe(import_effect18.Effect.mapError(() => new DevCredentialsStoreReadError({ message: "Failed to read dev-keys.json" })));
2533
+ const json = yield* import_effect18.Effect.try({
1956
2534
  try: () => JSON.parse(data),
1957
2535
  catch: () => new DevCredentialsStoreReadError({ message: "dev-keys.json contains invalid JSON" })
1958
2536
  });
1959
- return yield* import_effect17.Schema.decodeUnknown(DevKeyStore)(json).pipe(
1960
- import_effect17.Effect.mapError(() => new DevCredentialsStoreReadError({ message: "dev-keys.json has an invalid schema" }))
2537
+ return yield* import_effect18.Schema.decodeUnknown(DevKeyStore)(json).pipe(
2538
+ import_effect18.Effect.mapError(() => new DevCredentialsStoreReadError({ message: "dev-keys.json has an invalid schema" }))
1961
2539
  );
1962
2540
  });
1963
- const get = import_effect17.Effect.fn("DevCredentialsStore.get")(function* (applicationId) {
2541
+ const get = import_effect18.Effect.fn("DevCredentialsStore.get")(function* (applicationId) {
1964
2542
  const store = yield* load;
1965
2543
  const entry = store[applicationId];
1966
- return entry ? import_effect17.Option.some(entry) : import_effect17.Option.none();
2544
+ return entry ? import_effect18.Option.some(entry) : import_effect18.Option.none();
1967
2545
  });
1968
- const set = import_effect17.Effect.fn("DevCredentialsStore.set")(function* (applicationId, entry) {
2546
+ const set = import_effect18.Effect.fn("DevCredentialsStore.set")(function* (applicationId, entry) {
1969
2547
  const store = yield* load;
1970
2548
  const next = { ...store, [applicationId]: entry };
1971
2549
  yield* ensureDirectory;
1972
2550
  yield* fs.writeFileString(storeFile, `${JSON.stringify(next, null, 2)}
1973
2551
  `, { mode: 384 }).pipe(
1974
- import_effect17.Effect.mapError(
2552
+ import_effect18.Effect.mapError(
1975
2553
  (error) => new DevCredentialsStoreWriteError({ message: "Failed to write dev-keys.json", cause: String(error) })
1976
2554
  )
1977
2555
  );
@@ -1983,31 +2561,31 @@ var DevCredentialsStore = class extends import_effect17.Effect.Service()("DevCre
1983
2561
 
1984
2562
  // src/services/local-credentials.ts
1985
2563
  var DEV_KEY_SCOPES = ["network:env_vars:read"];
1986
- var ApiBaseUrl2 = import_effect18.Config.string("GIGADRIVE_API_BASE_URL").pipe(import_effect18.Config.withDefault("https://api.gigadrive.network"));
2564
+ var ApiBaseUrl2 = import_effect19.Config.string("GIGADRIVE_API_BASE_URL").pipe(import_effect19.Config.withDefault("https://api.gigadrive.network"));
1987
2565
  var credentialEntries = (clientId, clientSecret, baseUrl) => [
1988
2566
  { key: "GIGADRIVE_CLIENT_ID", value: clientId },
1989
2567
  { key: "GIGADRIVE_CLIENT_SECRET", value: clientSecret },
1990
2568
  { key: "GIGADRIVE_API_BASE_URL", value: baseUrl }
1991
2569
  ];
1992
- var LocalCredentialsService = class extends import_effect18.Effect.Service()("LocalCredentialsService", {
2570
+ var LocalCredentialsService = class extends import_effect19.Effect.Service()("LocalCredentialsService", {
1993
2571
  accessors: true,
1994
2572
  dependencies: [ApiClientService.Default, DevCredentialsStore.Default],
1995
- effect: import_effect18.Effect.gen(function* () {
2573
+ effect: import_effect19.Effect.gen(function* () {
1996
2574
  const apiClient = yield* ApiClientService;
1997
2575
  const store = yield* DevCredentialsStore;
1998
2576
  const baseUrl = yield* ApiBaseUrl2;
1999
2577
  const keyName = (applicationId) => `cli-dev:${os3.hostname()}:${applicationId}`;
2000
- const provision = import_effect18.Effect.fn("LocalCredentialsService.provision")(function* (input) {
2578
+ const provision = import_effect19.Effect.fn("LocalCredentialsService.provision")(function* (input) {
2001
2579
  const stored = yield* store.get(input.applicationId);
2002
2580
  const existing = input.existingContent ? parseEnv(input.existingContent) : {};
2003
2581
  const existingClientId = existing["GIGADRIVE_CLIENT_ID"];
2004
2582
  const existingClientSecret = existing["GIGADRIVE_CLIENT_SECRET"];
2005
- const canReuse = !input.rotate && existingClientId !== void 0 && existingClientSecret !== void 0 && import_effect18.Option.isSome(stored) && stored.value.apiKeyId === existingClientId;
2583
+ const canReuse = !input.rotate && existingClientId !== void 0 && existingClientSecret !== void 0 && import_effect19.Option.isSome(stored) && stored.value.apiKeyId === existingClientId;
2006
2584
  if (canReuse) {
2007
2585
  return credentialEntries(existingClientId, existingClientSecret, baseUrl);
2008
2586
  }
2009
- if (import_effect18.Option.isSome(stored)) {
2010
- yield* apiClient.request((client) => client.apiKeys.delete(stored.value.apiKeyId)).pipe(import_effect18.Effect.catchTag("ApiRequestError", () => import_effect18.Effect.void));
2587
+ if (import_effect19.Option.isSome(stored)) {
2588
+ yield* apiClient.request((client) => client.apiKeys.delete(stored.value.apiKeyId)).pipe(import_effect19.Effect.catchTag("ApiRequestError", () => import_effect19.Effect.void));
2011
2589
  }
2012
2590
  const created = yield* apiClient.request(
2013
2591
  (client) => client.apiKeys.create({
@@ -2025,92 +2603,92 @@ var LocalCredentialsService = class extends import_effect18.Effect.Service()("Lo
2025
2603
  };
2026
2604
 
2027
2605
  // src/commands/env/index.ts
2028
- var appOption3 = import_cli7.Options.text("app").pipe(
2029
- import_cli7.Options.withAlias("a"),
2030
- import_cli7.Options.withDescription("Operate on this application (overrides the linked application)"),
2031
- import_cli7.Options.optional
2606
+ var appOption4 = import_cli8.Options.text("app").pipe(
2607
+ import_cli8.Options.withAlias("a"),
2608
+ import_cli8.Options.withDescription("Operate on this application (overrides the linked application)"),
2609
+ import_cli8.Options.optional
2032
2610
  );
2033
- var orgOption3 = import_cli7.Options.text("org").pipe(
2034
- import_cli7.Options.withAlias("o"),
2035
- import_cli7.Options.withDescription("Operate on this organization instead of an application"),
2036
- import_cli7.Options.optional
2611
+ var orgOption4 = import_cli8.Options.text("org").pipe(
2612
+ import_cli8.Options.withAlias("o"),
2613
+ import_cli8.Options.withDescription("Operate on this organization instead of an application"),
2614
+ import_cli8.Options.optional
2037
2615
  );
2038
- var sensitiveOption = import_cli7.Options.boolean("sensitive").pipe(
2039
- import_cli7.Options.withDescription("Store the value as sensitive (hidden in API responses)")
2616
+ var sensitiveOption = import_cli8.Options.boolean("sensitive").pipe(
2617
+ import_cli8.Options.withDescription("Store the value as sensitive (hidden in API responses)")
2040
2618
  );
2041
- var envIdOption = import_cli7.Options.text("env").pipe(
2042
- import_cli7.Options.withAlias("e"),
2043
- import_cli7.Options.withDescription("Environment ID for an environment-scoped variable (application scope only)"),
2044
- import_cli7.Options.optional
2619
+ var envIdOption = import_cli8.Options.text("env").pipe(
2620
+ import_cli8.Options.withAlias("e"),
2621
+ import_cli8.Options.withDescription("Environment ID for an environment-scoped variable (application scope only)"),
2622
+ import_cli8.Options.optional
2045
2623
  );
2046
- var keyValueArg = import_cli7.Args.text({ name: "key=value" }).pipe(
2047
- import_cli7.Args.withDescription("Variable assignment, e.g. DATABASE_URL=postgres://user:pass@host/db")
2624
+ var keyValueArg = import_cli8.Args.text({ name: "key=value" }).pipe(
2625
+ import_cli8.Args.withDescription("Variable assignment, e.g. DATABASE_URL=postgres://user:pass@host/db")
2048
2626
  );
2049
- var keyOrIdArg = import_cli7.Args.text({ name: "key-or-id" }).pipe(import_cli7.Args.withDescription("Variable key or ID to remove"));
2050
- var fileArg = import_cli7.Args.text({ name: "file" }).pipe(
2051
- import_cli7.Args.withDescription("Output file to write (default: .env.local)"),
2052
- import_cli7.Args.optional
2627
+ var keyOrIdArg = import_cli8.Args.text({ name: "key-or-id" }).pipe(import_cli8.Args.withDescription("Variable key or ID to remove"));
2628
+ var fileArg = import_cli8.Args.text({ name: "file" }).pipe(
2629
+ import_cli8.Args.withDescription("Output file to write (default: .env.local)"),
2630
+ import_cli8.Args.optional
2053
2631
  );
2054
- var environmentOption = import_cli7.Options.text("environment").pipe(
2055
- import_cli7.Options.withAlias("e"),
2056
- import_cli7.Options.withDescription("Environment slug to resolve overrides for (e.g. preview). Omit for the local baseline"),
2057
- import_cli7.Options.optional
2632
+ var environmentOption = import_cli8.Options.text("environment").pipe(
2633
+ import_cli8.Options.withAlias("e"),
2634
+ import_cli8.Options.withDescription("Environment slug to resolve overrides for (e.g. preview). Omit for the local baseline"),
2635
+ import_cli8.Options.optional
2058
2636
  );
2059
- var yesOption = import_cli7.Options.boolean("yes").pipe(
2060
- import_cli7.Options.withAlias("y"),
2061
- import_cli7.Options.withDescription("Overwrite an existing file without confirmation")
2637
+ var yesOption2 = import_cli8.Options.boolean("yes").pipe(
2638
+ import_cli8.Options.withAlias("y"),
2639
+ import_cli8.Options.withDescription("Overwrite an existing file without confirmation")
2062
2640
  );
2063
- var withCredentialsOption = import_cli7.Options.boolean("with-credentials").pipe(
2064
- import_cli7.Options.withDescription("Also provision API-key credentials so the local app can call the API as this application")
2641
+ var withCredentialsOption = import_cli8.Options.boolean("with-credentials").pipe(
2642
+ import_cli8.Options.withDescription("Also provision API-key credentials so the local app can call the API as this application")
2065
2643
  );
2066
- var rotateOption = import_cli7.Options.boolean("rotate").pipe(
2067
- import_cli7.Options.withDescription("Force a fresh API key when provisioning credentials, revoking the previous one")
2644
+ var rotateOption = import_cli8.Options.boolean("rotate").pipe(
2645
+ import_cli8.Options.withDescription("Force a fresh API key when provisioning credentials, revoking the previous one")
2068
2646
  );
2069
- var resolveScope = (app, org) => import_effect19.Effect.gen(function* () {
2070
- if (import_effect19.Option.isSome(org)) {
2647
+ var resolveScope = (app, org) => import_effect20.Effect.gen(function* () {
2648
+ if (import_effect20.Option.isSome(org)) {
2071
2649
  return { kind: "organization", id: org.value };
2072
2650
  }
2073
2651
  const projectLink = yield* ProjectLinkService;
2074
- const id = yield* import_effect19.Option.match(app, {
2075
- onSome: (value) => import_effect19.Effect.succeed(value),
2076
- onNone: () => projectLink.resolve(process.cwd()).pipe(import_effect19.Effect.map((link) => link.applicationId))
2652
+ const id = yield* import_effect20.Option.match(app, {
2653
+ onSome: (value) => import_effect20.Effect.succeed(value),
2654
+ onNone: () => projectLink.resolve(process.cwd()).pipe(import_effect20.Effect.map((link) => link.applicationId))
2077
2655
  });
2078
2656
  return { kind: "application", id };
2079
2657
  });
2080
- var envListCommand = import_cli7.Command.make(
2658
+ var envListCommand = import_cli8.Command.make(
2081
2659
  "list",
2082
- { app: appOption3, org: orgOption3 },
2083
- ({ app, org }) => import_effect19.Effect.gen(function* () {
2660
+ { app: appOption4, org: orgOption4 },
2661
+ ({ app, org }) => import_effect20.Effect.gen(function* () {
2084
2662
  const apiClient = yield* ApiClientService;
2085
2663
  const scope = yield* resolveScope(app, org);
2086
2664
  const { items } = yield* apiClient.request(
2087
2665
  (client) => scope.kind === "organization" ? client.organizations.envVars.list(scope.id) : client.applications.envVars.list(scope.id)
2088
2666
  );
2089
2667
  if (items.length === 0) {
2090
- yield* import_effect19.Console.log("No environment variables set.");
2668
+ yield* import_effect20.Console.log("No environment variables set.");
2091
2669
  return;
2092
2670
  }
2093
2671
  for (const v of items) {
2094
- yield* import_effect19.Console.log(`${v.key}=${v.sensitive ? "***" : v.value ?? ""}`);
2672
+ yield* import_effect20.Console.log(`${v.key}=${v.sensitive ? "***" : v.value ?? ""}`);
2095
2673
  }
2096
2674
  }).pipe(
2097
- import_effect19.Effect.catchTags({
2098
- NotAuthenticatedError: (err) => import_effect19.Console.error('You are not logged in. Run "gigadrive login" to authenticate.').pipe(
2099
- import_effect19.Effect.andThen(import_effect19.Effect.fail(err))
2675
+ import_effect20.Effect.catchTags({
2676
+ NotAuthenticatedError: (err) => import_effect20.Console.error('You are not logged in. Run "gigadrive login" to authenticate.').pipe(
2677
+ import_effect20.Effect.andThen(import_effect20.Effect.fail(err))
2100
2678
  ),
2101
- ApiRequestError: (err) => import_effect19.Console.error(`Failed to list environment variables: ${err.message}`).pipe(import_effect19.Effect.andThen(import_effect19.Effect.fail(err))),
2102
- ProjectNotLinkedError: (err) => import_effect19.Console.error(err.message).pipe(import_effect19.Effect.andThen(import_effect19.Effect.fail(err))),
2103
- ProjectLinkReadError: (err) => import_effect19.Console.error(err.message).pipe(import_effect19.Effect.andThen(import_effect19.Effect.fail(err)))
2679
+ ApiRequestError: (err) => import_effect20.Console.error(`Failed to list environment variables: ${err.message}`).pipe(import_effect20.Effect.andThen(import_effect20.Effect.fail(err))),
2680
+ ProjectNotLinkedError: (err) => import_effect20.Console.error(err.message).pipe(import_effect20.Effect.andThen(import_effect20.Effect.fail(err))),
2681
+ ProjectLinkReadError: (err) => import_effect20.Console.error(err.message).pipe(import_effect20.Effect.andThen(import_effect20.Effect.fail(err)))
2104
2682
  })
2105
2683
  )
2106
2684
  );
2107
- var envSetCommand = import_cli7.Command.make(
2685
+ var envSetCommand = import_cli8.Command.make(
2108
2686
  "set",
2109
- { keyValue: keyValueArg, app: appOption3, org: orgOption3, sensitive: sensitiveOption, env: envIdOption },
2110
- ({ keyValue, app, org, sensitive, env }) => import_effect19.Effect.gen(function* () {
2687
+ { keyValue: keyValueArg, app: appOption4, org: orgOption4, sensitive: sensitiveOption, env: envIdOption },
2688
+ ({ keyValue, app, org, sensitive, env }) => import_effect20.Effect.gen(function* () {
2111
2689
  const separator = keyValue.indexOf("=");
2112
2690
  if (separator <= 0) {
2113
- return yield* import_effect19.Effect.fail(
2691
+ return yield* import_effect20.Effect.fail(
2114
2692
  new InvalidEnvVarFormatError({
2115
2693
  message: 'Invalid format. Use KEY=VALUE, e.g. "gigadrive env set DATABASE_URL=postgres://...".'
2116
2694
  })
@@ -2120,27 +2698,27 @@ var envSetCommand = import_cli7.Command.make(
2120
2698
  const value = keyValue.slice(separator + 1);
2121
2699
  const apiClient = yield* ApiClientService;
2122
2700
  const scope = yield* resolveScope(app, org);
2123
- const environmentId = import_effect19.Option.getOrUndefined(env);
2701
+ const environmentId = import_effect20.Option.getOrUndefined(env);
2124
2702
  const created = yield* apiClient.request(
2125
2703
  (client) => scope.kind === "organization" ? client.organizations.envVars.create(scope.id, { key, value, sensitive }) : client.applications.envVars.create(scope.id, { key, value, sensitive, environmentId })
2126
2704
  );
2127
- yield* import_effect19.Console.log(`Set ${created.key}.`);
2705
+ yield* import_effect20.Console.log(`Set ${created.key}.`);
2128
2706
  }).pipe(
2129
- import_effect19.Effect.catchTags({
2130
- InvalidEnvVarFormatError: (err) => import_effect19.Console.error(err.message).pipe(import_effect19.Effect.andThen(import_effect19.Effect.fail(err))),
2131
- NotAuthenticatedError: (err) => import_effect19.Console.error('You are not logged in. Run "gigadrive login" to authenticate.').pipe(
2132
- import_effect19.Effect.andThen(import_effect19.Effect.fail(err))
2707
+ import_effect20.Effect.catchTags({
2708
+ InvalidEnvVarFormatError: (err) => import_effect20.Console.error(err.message).pipe(import_effect20.Effect.andThen(import_effect20.Effect.fail(err))),
2709
+ NotAuthenticatedError: (err) => import_effect20.Console.error('You are not logged in. Run "gigadrive login" to authenticate.').pipe(
2710
+ import_effect20.Effect.andThen(import_effect20.Effect.fail(err))
2133
2711
  ),
2134
- ApiRequestError: (err) => import_effect19.Console.error(`Failed to set environment variable: ${err.message}`).pipe(import_effect19.Effect.andThen(import_effect19.Effect.fail(err))),
2135
- ProjectNotLinkedError: (err) => import_effect19.Console.error(err.message).pipe(import_effect19.Effect.andThen(import_effect19.Effect.fail(err))),
2136
- ProjectLinkReadError: (err) => import_effect19.Console.error(err.message).pipe(import_effect19.Effect.andThen(import_effect19.Effect.fail(err)))
2712
+ ApiRequestError: (err) => import_effect20.Console.error(`Failed to set environment variable: ${err.message}`).pipe(import_effect20.Effect.andThen(import_effect20.Effect.fail(err))),
2713
+ ProjectNotLinkedError: (err) => import_effect20.Console.error(err.message).pipe(import_effect20.Effect.andThen(import_effect20.Effect.fail(err))),
2714
+ ProjectLinkReadError: (err) => import_effect20.Console.error(err.message).pipe(import_effect20.Effect.andThen(import_effect20.Effect.fail(err)))
2137
2715
  })
2138
2716
  )
2139
2717
  );
2140
- var envRmCommand = import_cli7.Command.make(
2718
+ var envRmCommand = import_cli8.Command.make(
2141
2719
  "rm",
2142
- { keyOrId: keyOrIdArg, app: appOption3, org: orgOption3 },
2143
- ({ keyOrId, app, org }) => import_effect19.Effect.gen(function* () {
2720
+ { keyOrId: keyOrIdArg, app: appOption4, org: orgOption4 },
2721
+ ({ keyOrId, app, org }) => import_effect20.Effect.gen(function* () {
2144
2722
  const apiClient = yield* ApiClientService;
2145
2723
  const scope = yield* resolveScope(app, org);
2146
2724
  const { items } = yield* apiClient.request(
@@ -2148,56 +2726,56 @@ var envRmCommand = import_cli7.Command.make(
2148
2726
  );
2149
2727
  const target = items.find((v) => v.id === keyOrId || v.key === keyOrId);
2150
2728
  if (target === void 0) {
2151
- return yield* import_effect19.Effect.fail(
2729
+ return yield* import_effect20.Effect.fail(
2152
2730
  new EnvVarNotFoundError({ message: `No environment variable matching "${keyOrId}".` })
2153
2731
  );
2154
2732
  }
2155
2733
  yield* apiClient.request(
2156
2734
  (client) => scope.kind === "organization" ? client.organizations.envVars.delete(scope.id, target.id) : client.applications.envVars.delete(scope.id, target.id)
2157
2735
  );
2158
- yield* import_effect19.Console.log(`Removed ${target.key}.`);
2736
+ yield* import_effect20.Console.log(`Removed ${target.key}.`);
2159
2737
  }).pipe(
2160
- import_effect19.Effect.catchTags({
2161
- EnvVarNotFoundError: (err) => import_effect19.Console.error(err.message).pipe(import_effect19.Effect.andThen(import_effect19.Effect.fail(err))),
2162
- NotAuthenticatedError: (err) => import_effect19.Console.error('You are not logged in. Run "gigadrive login" to authenticate.').pipe(
2163
- import_effect19.Effect.andThen(import_effect19.Effect.fail(err))
2738
+ import_effect20.Effect.catchTags({
2739
+ EnvVarNotFoundError: (err) => import_effect20.Console.error(err.message).pipe(import_effect20.Effect.andThen(import_effect20.Effect.fail(err))),
2740
+ NotAuthenticatedError: (err) => import_effect20.Console.error('You are not logged in. Run "gigadrive login" to authenticate.').pipe(
2741
+ import_effect20.Effect.andThen(import_effect20.Effect.fail(err))
2164
2742
  ),
2165
- ApiRequestError: (err) => import_effect19.Console.error(`Failed to remove environment variable: ${err.message}`).pipe(import_effect19.Effect.andThen(import_effect19.Effect.fail(err))),
2166
- ProjectNotLinkedError: (err) => import_effect19.Console.error(err.message).pipe(import_effect19.Effect.andThen(import_effect19.Effect.fail(err))),
2167
- ProjectLinkReadError: (err) => import_effect19.Console.error(err.message).pipe(import_effect19.Effect.andThen(import_effect19.Effect.fail(err)))
2743
+ ApiRequestError: (err) => import_effect20.Console.error(`Failed to remove environment variable: ${err.message}`).pipe(import_effect20.Effect.andThen(import_effect20.Effect.fail(err))),
2744
+ ProjectNotLinkedError: (err) => import_effect20.Console.error(err.message).pipe(import_effect20.Effect.andThen(import_effect20.Effect.fail(err))),
2745
+ ProjectLinkReadError: (err) => import_effect20.Console.error(err.message).pipe(import_effect20.Effect.andThen(import_effect20.Effect.fail(err)))
2168
2746
  })
2169
2747
  )
2170
2748
  );
2171
- var envPullCommand = import_cli7.Command.make(
2749
+ var envPullCommand = import_cli8.Command.make(
2172
2750
  "pull",
2173
2751
  {
2174
2752
  file: fileArg,
2175
- app: appOption3,
2753
+ app: appOption4,
2176
2754
  environment: environmentOption,
2177
- yes: yesOption,
2755
+ yes: yesOption2,
2178
2756
  withCredentials: withCredentialsOption,
2179
2757
  rotate: rotateOption
2180
2758
  },
2181
- ({ file, app, environment, yes, withCredentials, rotate }) => import_effect19.Effect.gen(function* () {
2759
+ ({ file, app, environment, yes, withCredentials, rotate }) => import_effect20.Effect.gen(function* () {
2182
2760
  const apiClient = yield* ApiClientService;
2183
2761
  const projectLink = yield* ProjectLinkService;
2184
2762
  const envFile = yield* EnvFileService;
2185
- const applicationId = yield* import_effect19.Option.match(app, {
2186
- onSome: (value) => import_effect19.Effect.succeed(value),
2187
- onNone: () => projectLink.resolve(process.cwd()).pipe(import_effect19.Effect.map((link) => link.applicationId))
2763
+ const applicationId = yield* import_effect20.Option.match(app, {
2764
+ onSome: (value) => import_effect20.Effect.succeed(value),
2765
+ onNone: () => projectLink.resolve(process.cwd()).pipe(import_effect20.Effect.map((link) => link.applicationId))
2188
2766
  });
2189
- const target = import_effect19.Option.getOrElse(file, () => ".env.local");
2190
- const environmentSlug = import_effect19.Option.getOrUndefined(environment);
2767
+ const target = import_effect20.Option.getOrElse(file, () => ".env.local");
2768
+ const environmentSlug = import_effect20.Option.getOrUndefined(environment);
2191
2769
  const { items, omittedSensitive } = yield* apiClient.request(
2192
2770
  (client) => client.applications.envVars.pull(applicationId, environmentSlug ? { environment: environmentSlug } : void 0)
2193
2771
  );
2194
2772
  const existing = yield* envFile.read(target);
2195
- if (import_effect19.Option.isSome(existing) && !yes) {
2196
- const overwrite = yield* import_cli7.Prompt.run(
2197
- import_cli7.Prompt.confirm({ message: `${target} already exists. Overwrite?`, initial: false })
2773
+ if (import_effect20.Option.isSome(existing) && !yes) {
2774
+ const overwrite = yield* import_cli8.Prompt.run(
2775
+ import_cli8.Prompt.confirm({ message: `${target} already exists. Overwrite?`, initial: false })
2198
2776
  );
2199
2777
  if (!overwrite) {
2200
- return yield* import_effect19.Console.log("Cancelled.");
2778
+ return yield* import_effect20.Console.log("Cancelled.");
2201
2779
  }
2202
2780
  }
2203
2781
  let credentialEntries2 = [];
@@ -2206,81 +2784,81 @@ var envPullCommand = import_cli7.Command.make(
2206
2784
  credentialEntries2 = yield* localCredentials.provision({
2207
2785
  applicationId,
2208
2786
  rotate,
2209
- existingContent: import_effect19.Option.getOrUndefined(existing)
2787
+ existingContent: import_effect20.Option.getOrUndefined(existing)
2210
2788
  });
2211
2789
  }
2212
2790
  const entries = [...items.map((v) => ({ key: v.key, value: v.value })), ...credentialEntries2];
2213
2791
  yield* envFile.write(target, entries);
2214
2792
  const gitignored = yield* envFile.ensureGitignored(process.cwd(), target);
2215
- yield* import_effect19.Console.log(
2793
+ yield* import_effect20.Console.log(
2216
2794
  `Pulled ${items.length} environment variable(s)${withCredentials ? " and API credentials" : ""} to ${target}.`
2217
2795
  );
2218
2796
  if (omittedSensitive > 0) {
2219
- yield* import_effect19.Console.log(
2797
+ yield* import_effect20.Console.log(
2220
2798
  `Skipped ${omittedSensitive} sensitive variable(s); secrets live only in production/preview environments.`
2221
2799
  );
2222
2800
  }
2223
2801
  if (gitignored) {
2224
- yield* import_effect19.Console.log(`Added ${target} to .gitignore.`);
2802
+ yield* import_effect20.Console.log(`Added ${target} to .gitignore.`);
2225
2803
  }
2226
2804
  }).pipe(
2227
- import_effect19.Effect.catchTags({
2805
+ import_effect20.Effect.catchTags({
2228
2806
  // Ctrl+C during the overwrite prompt is a deliberate cancel — exit 0.
2229
- QuitException: () => import_effect19.Console.log("Cancelled."),
2230
- NotAuthenticatedError: (err) => import_effect19.Console.error('You are not logged in. Run "gigadrive login" to authenticate.').pipe(
2231
- import_effect19.Effect.andThen(import_effect19.Effect.fail(err))
2807
+ QuitException: () => import_effect20.Console.log("Cancelled."),
2808
+ NotAuthenticatedError: (err) => import_effect20.Console.error('You are not logged in. Run "gigadrive login" to authenticate.').pipe(
2809
+ import_effect20.Effect.andThen(import_effect20.Effect.fail(err))
2232
2810
  ),
2233
- ApiRequestError: (err) => import_effect19.Console.error(`Failed to pull environment variables: ${err.message}`).pipe(import_effect19.Effect.andThen(import_effect19.Effect.fail(err))),
2234
- ProjectNotLinkedError: (err) => import_effect19.Console.error(err.message).pipe(import_effect19.Effect.andThen(import_effect19.Effect.fail(err))),
2235
- ProjectLinkReadError: (err) => import_effect19.Console.error(err.message).pipe(import_effect19.Effect.andThen(import_effect19.Effect.fail(err))),
2236
- EnvFileReadError: (err) => import_effect19.Console.error(err.message).pipe(import_effect19.Effect.andThen(import_effect19.Effect.fail(err))),
2237
- EnvFileWriteError: (err) => import_effect19.Console.error(err.message).pipe(import_effect19.Effect.andThen(import_effect19.Effect.fail(err))),
2238
- DevCredentialsStoreReadError: (err) => import_effect19.Console.error(err.message).pipe(import_effect19.Effect.andThen(import_effect19.Effect.fail(err))),
2239
- DevCredentialsStoreWriteError: (err) => import_effect19.Console.error(err.message).pipe(import_effect19.Effect.andThen(import_effect19.Effect.fail(err)))
2811
+ ApiRequestError: (err) => import_effect20.Console.error(`Failed to pull environment variables: ${err.message}`).pipe(import_effect20.Effect.andThen(import_effect20.Effect.fail(err))),
2812
+ ProjectNotLinkedError: (err) => import_effect20.Console.error(err.message).pipe(import_effect20.Effect.andThen(import_effect20.Effect.fail(err))),
2813
+ ProjectLinkReadError: (err) => import_effect20.Console.error(err.message).pipe(import_effect20.Effect.andThen(import_effect20.Effect.fail(err))),
2814
+ EnvFileReadError: (err) => import_effect20.Console.error(err.message).pipe(import_effect20.Effect.andThen(import_effect20.Effect.fail(err))),
2815
+ EnvFileWriteError: (err) => import_effect20.Console.error(err.message).pipe(import_effect20.Effect.andThen(import_effect20.Effect.fail(err))),
2816
+ DevCredentialsStoreReadError: (err) => import_effect20.Console.error(err.message).pipe(import_effect20.Effect.andThen(import_effect20.Effect.fail(err))),
2817
+ DevCredentialsStoreWriteError: (err) => import_effect20.Console.error(err.message).pipe(import_effect20.Effect.andThen(import_effect20.Effect.fail(err)))
2240
2818
  })
2241
2819
  )
2242
2820
  );
2243
- var envBase = import_cli7.Command.make("env", {}, () => import_effect19.Effect.void);
2821
+ var envBase = import_cli8.Command.make("env", {}, () => import_effect20.Effect.void);
2244
2822
  var envCommand = envBase.pipe(
2245
- import_cli7.Command.withSubcommands([envListCommand, envSetCommand, envRmCommand, envPullCommand])
2823
+ import_cli8.Command.withSubcommands([envListCommand, envSetCommand, envRmCommand, envPullCommand])
2246
2824
  );
2247
2825
 
2248
2826
  // src/commands/link/index.ts
2249
- var import_cli8 = require("@effect/cli");
2250
- var import_effect20 = require("effect");
2251
- var appOption4 = import_cli8.Options.text("app").pipe(
2252
- import_cli8.Options.withAlias("a"),
2253
- import_cli8.Options.withDescription("Application ID to link (skips the interactive picker)"),
2254
- import_cli8.Options.optional
2827
+ var import_cli9 = require("@effect/cli");
2828
+ var import_effect21 = require("effect");
2829
+ var appOption5 = import_cli9.Options.text("app").pipe(
2830
+ import_cli9.Options.withAlias("a"),
2831
+ import_cli9.Options.withDescription("Application ID to link (skips the interactive picker)"),
2832
+ import_cli9.Options.optional
2255
2833
  );
2256
- var orgOption4 = import_cli8.Options.text("org").pipe(
2257
- import_cli8.Options.withAlias("o"),
2258
- import_cli8.Options.withDescription("Only list applications belonging to this organization ID"),
2259
- import_cli8.Options.optional
2834
+ var orgOption5 = import_cli9.Options.text("org").pipe(
2835
+ import_cli9.Options.withAlias("o"),
2836
+ import_cli9.Options.withDescription("Only list applications belonging to this organization ID"),
2837
+ import_cli9.Options.optional
2260
2838
  );
2261
- var linkCommand = import_cli8.Command.make(
2839
+ var linkCommand = import_cli9.Command.make(
2262
2840
  "link",
2263
- { app: appOption4, org: orgOption4 },
2264
- ({ app, org }) => import_effect20.Effect.gen(function* () {
2841
+ { app: appOption5, org: orgOption5 },
2842
+ ({ app, org }) => import_effect21.Effect.gen(function* () {
2265
2843
  const apiClient = yield* ApiClientService;
2266
2844
  const projectLink = yield* ProjectLinkService;
2267
2845
  const cwd = process.cwd();
2268
- const organizationId = import_effect20.Option.getOrUndefined(org);
2846
+ const organizationId = import_effect21.Option.getOrUndefined(org);
2269
2847
  const { items: apps } = yield* apiClient.request((client) => client.applications.list({ organizationId }));
2270
2848
  if (apps.length === 0) {
2271
- return yield* import_effect20.Effect.fail(
2849
+ return yield* import_effect21.Effect.fail(
2272
2850
  new NoApplicationsFoundError({
2273
2851
  message: 'No applications found. Create one in the Gigadrive console, then run "gigadrive link" again.'
2274
2852
  })
2275
2853
  );
2276
2854
  }
2277
- const explicitAppId = import_effect20.Option.getOrUndefined(app);
2855
+ const explicitAppId = import_effect21.Option.getOrUndefined(app);
2278
2856
  let applicationId;
2279
2857
  let linkedOrganizationId;
2280
2858
  if (explicitAppId !== void 0) {
2281
2859
  const match = apps.find((a) => a.id === explicitAppId);
2282
2860
  if (match === void 0) {
2283
- return yield* import_effect20.Effect.fail(
2861
+ return yield* import_effect21.Effect.fail(
2284
2862
  new ApplicationNotFoundError({
2285
2863
  message: `Application "${explicitAppId}" was not found among your applications.`
2286
2864
  })
@@ -2292,8 +2870,8 @@ var linkCommand = import_cli8.Command.make(
2292
2870
  applicationId = apps[0].id;
2293
2871
  linkedOrganizationId = apps[0].organization.id;
2294
2872
  } else {
2295
- const chosen = yield* import_cli8.Prompt.run(
2296
- import_cli8.Prompt.select({
2873
+ const chosen = yield* import_cli9.Prompt.run(
2874
+ import_cli9.Prompt.select({
2297
2875
  message: "Select an application to link",
2298
2876
  choices: apps.map((a) => ({ title: `${a.name} (${a.organization.name})`, value: a }))
2299
2877
  })
@@ -2302,88 +2880,88 @@ var linkCommand = import_cli8.Command.make(
2302
2880
  linkedOrganizationId = chosen.organization.id;
2303
2881
  }
2304
2882
  yield* projectLink.save(cwd, { applicationId, organizationId: linkedOrganizationId });
2305
- yield* import_effect20.Console.log(`Linked this directory to application ${applicationId}.`);
2306
- yield* import_effect20.Console.log('Tip: add ".gigadrive/" to your .gitignore.');
2883
+ yield* import_effect21.Console.log(`Linked this directory to application ${applicationId}.`);
2884
+ yield* import_effect21.Console.log('Tip: add ".gigadrive/" to your .gitignore.');
2307
2885
  }).pipe(
2308
- import_effect20.Effect.catchTags({
2886
+ import_effect21.Effect.catchTags({
2309
2887
  // Ctrl+C during the picker is a deliberate cancel — exit 0.
2310
- QuitException: () => import_effect20.Console.log("Cancelled."),
2311
- NotAuthenticatedError: (err) => import_effect20.Console.error('You are not logged in. Run "gigadrive login" to authenticate.').pipe(
2312
- import_effect20.Effect.andThen(import_effect20.Effect.fail(err))
2888
+ QuitException: () => import_effect21.Console.log("Cancelled."),
2889
+ NotAuthenticatedError: (err) => import_effect21.Console.error('You are not logged in. Run "gigadrive login" to authenticate.').pipe(
2890
+ import_effect21.Effect.andThen(import_effect21.Effect.fail(err))
2313
2891
  ),
2314
- ApiRequestError: (err) => import_effect20.Console.error(`Failed to list applications: ${err.message}`).pipe(import_effect20.Effect.andThen(import_effect20.Effect.fail(err))),
2315
- NoApplicationsFoundError: (err) => import_effect20.Console.error(err.message).pipe(import_effect20.Effect.andThen(import_effect20.Effect.fail(err))),
2316
- ApplicationNotFoundError: (err) => import_effect20.Console.error(err.message).pipe(import_effect20.Effect.andThen(import_effect20.Effect.fail(err))),
2317
- ProjectLinkWriteError: (err) => import_effect20.Console.error(err.message).pipe(import_effect20.Effect.andThen(import_effect20.Effect.fail(err)))
2892
+ ApiRequestError: (err) => import_effect21.Console.error(`Failed to list applications: ${err.message}`).pipe(import_effect21.Effect.andThen(import_effect21.Effect.fail(err))),
2893
+ NoApplicationsFoundError: (err) => import_effect21.Console.error(err.message).pipe(import_effect21.Effect.andThen(import_effect21.Effect.fail(err))),
2894
+ ApplicationNotFoundError: (err) => import_effect21.Console.error(err.message).pipe(import_effect21.Effect.andThen(import_effect21.Effect.fail(err))),
2895
+ ProjectLinkWriteError: (err) => import_effect21.Console.error(err.message).pipe(import_effect21.Effect.andThen(import_effect21.Effect.fail(err)))
2318
2896
  })
2319
2897
  )
2320
2898
  );
2321
- var unlinkCommand = import_cli8.Command.make(
2899
+ var unlinkCommand = import_cli9.Command.make(
2322
2900
  "unlink",
2323
2901
  {},
2324
- () => import_effect20.Effect.gen(function* () {
2902
+ () => import_effect21.Effect.gen(function* () {
2325
2903
  const projectLink = yield* ProjectLinkService;
2326
2904
  yield* projectLink.remove(process.cwd());
2327
- yield* import_effect20.Console.log("Unlinked this directory.");
2905
+ yield* import_effect21.Console.log("Unlinked this directory.");
2328
2906
  }).pipe(
2329
- import_effect20.Effect.catchTags({
2330
- ProjectLinkWriteError: (err) => import_effect20.Console.error(err.message).pipe(import_effect20.Effect.andThen(import_effect20.Effect.fail(err)))
2907
+ import_effect21.Effect.catchTags({
2908
+ ProjectLinkWriteError: (err) => import_effect21.Console.error(err.message).pipe(import_effect21.Effect.andThen(import_effect21.Effect.fail(err)))
2331
2909
  })
2332
2910
  )
2333
2911
  );
2334
2912
 
2335
2913
  // src/commands/login/index.ts
2336
- var import_cli9 = require("@effect/cli");
2337
- var import_effect21 = require("effect");
2338
- var loginCommand = import_cli9.Command.make(
2914
+ var import_cli10 = require("@effect/cli");
2915
+ var import_effect22 = require("effect");
2916
+ var loginCommand = import_cli10.Command.make(
2339
2917
  "login",
2340
2918
  {},
2341
- () => import_effect21.Effect.gen(function* () {
2342
- yield* import_effect21.Console.log("Initiating login...");
2919
+ () => import_effect22.Effect.gen(function* () {
2920
+ yield* import_effect22.Console.log("Initiating login...");
2343
2921
  const auth = yield* AuthService;
2344
2922
  yield* auth.login;
2345
- const info = yield* auth.getUserInfo.pipe(import_effect21.Effect.catchAll(() => import_effect21.Effect.succeed({})));
2923
+ const info = yield* auth.getUserInfo.pipe(import_effect22.Effect.catchAll(() => import_effect22.Effect.succeed({})));
2346
2924
  const name = auth.inferUserName(info);
2347
- yield* import_effect21.Console.log(`You are now logged in as ${name}.`);
2925
+ yield* import_effect22.Console.log(`You are now logged in as ${name}.`);
2348
2926
  }).pipe(
2349
- import_effect21.Effect.catchTags({
2350
- LoginFlowError: (err) => import_effect21.Console.error(err.message),
2351
- DeviceAuthorizationError: (err) => import_effect21.Console.error(`Login failed: ${err.message}`),
2352
- AuthorizationDeniedError: (err) => import_effect21.Console.error(err.message),
2353
- DeviceCodeExpiredError: (err) => import_effect21.Console.error(err.message),
2354
- TokenExchangeError: (err) => import_effect21.Console.error(`Login failed: ${err.message}`),
2355
- OAuthDiscoveryError: (err) => import_effect21.Console.error(`Login failed: ${err.message}`),
2356
- AuthStorageWriteError: (err) => import_effect21.Console.error(`Failed to save credentials: ${err.message}`)
2927
+ import_effect22.Effect.catchTags({
2928
+ LoginFlowError: (err) => import_effect22.Console.error(err.message),
2929
+ DeviceAuthorizationError: (err) => import_effect22.Console.error(`Login failed: ${err.message}`),
2930
+ AuthorizationDeniedError: (err) => import_effect22.Console.error(err.message),
2931
+ DeviceCodeExpiredError: (err) => import_effect22.Console.error(err.message),
2932
+ TokenExchangeError: (err) => import_effect22.Console.error(`Login failed: ${err.message}`),
2933
+ OAuthDiscoveryError: (err) => import_effect22.Console.error(`Login failed: ${err.message}`),
2934
+ AuthStorageWriteError: (err) => import_effect22.Console.error(`Failed to save credentials: ${err.message}`)
2357
2935
  })
2358
2936
  )
2359
2937
  );
2360
2938
 
2361
2939
  // src/commands/logout/index.ts
2362
- var import_cli10 = require("@effect/cli");
2363
- var import_effect22 = require("effect");
2364
- var logoutCommand = import_cli10.Command.make(
2940
+ var import_cli11 = require("@effect/cli");
2941
+ var import_effect23 = require("effect");
2942
+ var logoutCommand = import_cli11.Command.make(
2365
2943
  "logout",
2366
2944
  {},
2367
- () => import_effect22.Effect.gen(function* () {
2945
+ () => import_effect23.Effect.gen(function* () {
2368
2946
  const auth = yield* AuthService;
2369
2947
  yield* auth.logout;
2370
- yield* import_effect22.Console.log("Logged out.");
2948
+ yield* import_effect23.Console.log("Logged out.");
2371
2949
  }).pipe(
2372
- import_effect22.Effect.catchTags({
2373
- AuthStorageWriteError: (err) => import_effect22.Console.error(`Failed to log out: ${err.message}`).pipe(import_effect22.Effect.andThen(import_effect22.Effect.fail(err)))
2950
+ import_effect23.Effect.catchTags({
2951
+ AuthStorageWriteError: (err) => import_effect23.Console.error(`Failed to log out: ${err.message}`).pipe(import_effect23.Effect.andThen(import_effect23.Effect.fail(err)))
2374
2952
  })
2375
2953
  )
2376
2954
  );
2377
2955
 
2378
2956
  // src/commands/platform/index.ts
2379
- var import_cli12 = require("@effect/cli");
2380
- var import_effect26 = require("effect");
2957
+ var import_cli13 = require("@effect/cli");
2958
+ var import_effect27 = require("effect");
2381
2959
 
2382
2960
  // src/commands/platform/deploy/index.ts
2383
- var import_cli11 = require("@effect/cli");
2961
+ var import_cli12 = require("@effect/cli");
2384
2962
  var import_platform9 = require("@effect/platform");
2385
2963
  var import_commons = require("@gigadrive/commons");
2386
- var import_effect25 = require("effect");
2964
+ var import_effect26 = require("effect");
2387
2965
  var os4 = __toESM(require("os"), 1);
2388
2966
  var path = __toESM(require("path"), 1);
2389
2967
 
@@ -2391,7 +2969,7 @@ var path = __toESM(require("path"), 1);
2391
2969
  var import_platform8 = require("@effect/platform");
2392
2970
  var import_build_utils3 = require("@gigadrive/build-utils");
2393
2971
  var import_archiver = __toESM(require("archiver"), 1);
2394
- var import_effect23 = require("effect");
2972
+ var import_effect24 = require("effect");
2395
2973
  var import_ignore = __toESM(require("ignore"), 1);
2396
2974
  var nodeFs = __toESM(require("fs"), 1);
2397
2975
  var nodeFsPromises = __toESM(require("fs/promises"), 1);
@@ -2404,22 +2982,33 @@ var MANAGED_IGNORE_PATTERNS = [
2404
2982
  "**/.DS_Store",
2405
2983
  "**/Thumbs.db"
2406
2984
  ];
2985
+ var CONTAINER_BUILD_FILE_PATTERNS = [
2986
+ "!Dockerfile",
2987
+ "!**/Dockerfile",
2988
+ "!**/*.Dockerfile",
2989
+ "!**/Dockerfile.*",
2990
+ "!compose.yaml",
2991
+ "!compose.yml",
2992
+ "!docker-compose.yaml",
2993
+ "!docker-compose.yml"
2994
+ ];
2995
+ var DOCKER_BUILD_IGNORE_FILE = ".dockerignore";
2407
2996
  var readIgnoreFile = (fs, ignorePath) => fs.readFileString(ignorePath, "utf8").pipe(
2408
- import_effect23.Effect.map((content) => content.split("\n").filter((line) => line.trim() !== "")),
2409
- import_effect23.Effect.catchAll(() => import_effect23.Effect.succeed([]))
2997
+ import_effect24.Effect.map((content) => content.split("\n").filter((line) => line.trim() !== "")),
2998
+ import_effect24.Effect.catchAll(() => import_effect24.Effect.succeed([]))
2410
2999
  );
2411
- var collectIgnorePatterns = (fs, pathService, dir, baseDir, ignoreRules) => import_effect23.Effect.gen(function* () {
2412
- const items = yield* fs.readDirectory(dir).pipe(import_effect23.Effect.mapError(() => new ArchiveCreateError({ message: `Failed to read directory: ${dir}` })));
3000
+ var collectIgnorePatterns = (fs, pathService, dir, baseDir, ignoreRules, ignoreFileNames) => import_effect24.Effect.gen(function* () {
3001
+ const items = yield* fs.readDirectory(dir).pipe(import_effect24.Effect.mapError(() => new ArchiveCreateError({ message: `Failed to read directory: ${dir}` })));
2413
3002
  for (const item of items) {
2414
3003
  const fullPath = pathService.join(dir, item);
2415
3004
  const relativePath = pathService.relative(baseDir, fullPath);
2416
- const stat = yield* import_effect23.Effect.tryPromise({
3005
+ const stat = yield* import_effect24.Effect.tryPromise({
2417
3006
  try: () => nodeFsPromises.lstat(fullPath),
2418
3007
  catch: () => new ArchiveCreateError({ message: `Failed to stat: ${fullPath}` })
2419
3008
  });
2420
3009
  if (stat.isDirectory()) {
2421
3010
  if (ignoreRules.ignores(`${relativePath}/`)) continue;
2422
- for (const ignoreFileName of IGNORE_FILE_NAMES) {
3011
+ for (const ignoreFileName of ignoreFileNames) {
2423
3012
  const ignoreFilePath = pathService.join(fullPath, ignoreFileName);
2424
3013
  const patterns = yield* readIgnoreFile(fs, ignoreFilePath);
2425
3014
  if (patterns.length > 0) {
@@ -2430,17 +3019,18 @@ var collectIgnorePatterns = (fs, pathService, dir, baseDir, ignoreRules) => impo
2430
3019
  );
2431
3020
  }
2432
3021
  }
2433
- yield* collectIgnorePatterns(fs, pathService, fullPath, baseDir, ignoreRules);
3022
+ yield* collectIgnorePatterns(fs, pathService, fullPath, baseDir, ignoreRules, ignoreFileNames);
2434
3023
  }
2435
3024
  }
2436
- }).pipe(import_effect23.Effect.catchAll(() => import_effect23.Effect.void));
2437
- var initializeIgnoreRules = (fs, pathService, baseDir, useIgnoreFiles, useManagedIgnore) => import_effect23.Effect.gen(function* () {
3025
+ }).pipe(import_effect24.Effect.catchAll(() => import_effect24.Effect.void));
3026
+ var initializeIgnoreRules = (fs, pathService, baseDir, useIgnoreFiles, useManagedIgnore, buildsContainerImages) => import_effect24.Effect.gen(function* () {
2438
3027
  const ignoreRules = (0, import_ignore.default)();
3028
+ const ignoreFileNames = buildsContainerImages ? IGNORE_FILE_NAMES.filter((name) => name !== DOCKER_BUILD_IGNORE_FILE) : IGNORE_FILE_NAMES;
2439
3029
  if (useManagedIgnore) {
2440
3030
  ignoreRules.add(MANAGED_IGNORE_PATTERNS);
2441
3031
  }
2442
3032
  if (useIgnoreFiles) {
2443
- for (const ignoreFileName of IGNORE_FILE_NAMES) {
3033
+ for (const ignoreFileName of ignoreFileNames) {
2444
3034
  const ignoreFilePath = pathService.join(baseDir, ignoreFileName);
2445
3035
  const patterns = yield* readIgnoreFile(fs, ignoreFilePath);
2446
3036
  if (patterns.length > 0) {
@@ -2449,18 +3039,19 @@ var initializeIgnoreRules = (fs, pathService, baseDir, useIgnoreFiles, useManage
2449
3039
  );
2450
3040
  }
2451
3041
  }
2452
- yield* collectIgnorePatterns(fs, pathService, baseDir, baseDir, ignoreRules);
3042
+ yield* collectIgnorePatterns(fs, pathService, baseDir, baseDir, ignoreRules, ignoreFileNames);
3043
+ ignoreRules.add(CONTAINER_BUILD_FILE_PATTERNS);
2453
3044
  }
2454
3045
  return ignoreRules;
2455
3046
  });
2456
- var getFilesToInclude = (fs, pathService, dir, ignoreRules) => import_effect23.Effect.gen(function* () {
3047
+ var getFilesToInclude = (fs, pathService, dir, ignoreRules) => import_effect24.Effect.gen(function* () {
2457
3048
  const filesToInclude = [];
2458
- const walkDir = (currentDir) => import_effect23.Effect.gen(function* () {
2459
- const items = yield* fs.readDirectory(currentDir).pipe(import_effect23.Effect.mapError(() => new ArchiveCreateError({ message: `Failed to read directory: ${currentDir}` })));
3049
+ const walkDir = (currentDir) => import_effect24.Effect.gen(function* () {
3050
+ const items = yield* fs.readDirectory(currentDir).pipe(import_effect24.Effect.mapError(() => new ArchiveCreateError({ message: `Failed to read directory: ${currentDir}` })));
2460
3051
  for (const item of items) {
2461
3052
  const fullPath = pathService.join(currentDir, item);
2462
3053
  const relativePath = pathService.relative(dir, fullPath);
2463
- const stat = yield* import_effect23.Effect.tryPromise({
3054
+ const stat = yield* import_effect24.Effect.tryPromise({
2464
3055
  try: () => nodeFsPromises.lstat(fullPath),
2465
3056
  catch: () => new ArchiveCreateError({ message: `Failed to stat: ${fullPath}` })
2466
3057
  });
@@ -2474,27 +3065,28 @@ var getFilesToInclude = (fs, pathService, dir, ignoreRules) => import_effect23.E
2474
3065
  }
2475
3066
  }
2476
3067
  }
2477
- }).pipe(import_effect23.Effect.catchAll(() => import_effect23.Effect.void));
3068
+ }).pipe(import_effect24.Effect.catchAll(() => import_effect24.Effect.void));
2478
3069
  yield* walkDir(dir);
2479
3070
  return filesToInclude;
2480
3071
  });
2481
- var ArchiveService = class extends import_effect23.Effect.Service()("ArchiveService", {
3072
+ var ArchiveService = class extends import_effect24.Effect.Service()("ArchiveService", {
2482
3073
  accessors: true,
2483
- effect: import_effect23.Effect.gen(function* () {
3074
+ effect: import_effect24.Effect.gen(function* () {
2484
3075
  const fs = yield* import_platform8.FileSystem.FileSystem;
2485
3076
  const pathService = yield* import_platform8.Path.Path;
2486
- const createZipArchive = import_effect23.Effect.fn("ArchiveService.createZipArchive")(function* (inputDir, outputFile, options = {}) {
2487
- yield* import_effect23.Effect.annotateCurrentSpan("inputDir", inputDir);
2488
- yield* import_effect23.Effect.annotateCurrentSpan("outputFile", outputFile);
2489
- yield* import_effect23.Effect.log("Creating zip archive", { inputDir, outputFile });
3077
+ const createZipArchive = import_effect24.Effect.fn("ArchiveService.createZipArchive")(function* (inputDir, outputFile, options = {}) {
3078
+ yield* import_effect24.Effect.annotateCurrentSpan("inputDir", inputDir);
3079
+ yield* import_effect24.Effect.annotateCurrentSpan("outputFile", outputFile);
3080
+ yield* import_effect24.Effect.log("Creating zip archive", { inputDir, outputFile });
2490
3081
  const ignoreRules = yield* initializeIgnoreRules(
2491
3082
  fs,
2492
3083
  pathService,
2493
3084
  inputDir,
2494
3085
  options.useIgnoreFiles !== false,
2495
- options.useManagedIgnore !== false
3086
+ options.useManagedIgnore !== false,
3087
+ options.buildsContainerImages === true
2496
3088
  );
2497
- const filesToInclude = options.whitelist ? yield* import_effect23.Effect.tryPromise({
3089
+ const filesToInclude = options.whitelist ? yield* import_effect24.Effect.tryPromise({
2498
3090
  try: () => Promise.all(
2499
3091
  options.whitelist.map((file) => (0, import_build_utils3.getFilesForPattern)(file, inputDir, options.excludeFiles ?? []))
2500
3092
  ),
@@ -2502,25 +3094,25 @@ var ArchiveService = class extends import_effect23.Effect.Service()("ArchiveServ
2502
3094
  message: "Failed to resolve whitelist patterns",
2503
3095
  cause: error instanceof Error ? error.message : String(error)
2504
3096
  })
2505
- }) : yield* import_effect23.Effect.gen(function* () {
3097
+ }) : yield* import_effect24.Effect.gen(function* () {
2506
3098
  if (options.excludeFiles && options.excludeFiles.length > 0) {
2507
3099
  ignoreRules.add(options.excludeFiles);
2508
3100
  }
2509
3101
  return yield* getFilesToInclude(fs, pathService, inputDir, ignoreRules).pipe(
2510
- import_effect23.Effect.map((files) => [files])
3102
+ import_effect24.Effect.map((files) => [files])
2511
3103
  );
2512
3104
  });
2513
- const archiveExists = yield* fs.exists(outputFile).pipe(import_effect23.Effect.catchAll(() => import_effect23.Effect.succeed(false)));
3105
+ const archiveExists = yield* fs.exists(outputFile).pipe(import_effect24.Effect.catchAll(() => import_effect24.Effect.succeed(false)));
2514
3106
  if (archiveExists) {
2515
3107
  yield* fs.remove(outputFile).pipe(
2516
- import_effect23.Effect.mapError(
3108
+ import_effect24.Effect.mapError(
2517
3109
  (error) => new ArchiveCreateError({
2518
3110
  message: `Failed to remove existing archive: ${String(error)}`
2519
3111
  })
2520
3112
  )
2521
3113
  );
2522
3114
  }
2523
- yield* import_effect23.Effect.tryPromise({
3115
+ yield* import_effect24.Effect.tryPromise({
2524
3116
  try: () => new Promise((resolve, reject) => {
2525
3117
  const output = nodeFs.createWriteStream(outputFile);
2526
3118
  const archive = (0, import_archiver.default)("zip", { zlib: { level: 9 } });
@@ -2539,14 +3131,14 @@ var ArchiveService = class extends import_effect23.Effect.Service()("ArchiveServ
2539
3131
  })
2540
3132
  });
2541
3133
  const fileInfo = yield* fs.stat(outputFile).pipe(
2542
- import_effect23.Effect.mapError(
3134
+ import_effect24.Effect.mapError(
2543
3135
  (error) => new ArchiveCreateError({
2544
3136
  message: `Failed to stat archive: ${String(error)}`
2545
3137
  })
2546
3138
  )
2547
3139
  );
2548
3140
  const size = Number(fileInfo.size);
2549
- yield* import_effect23.Effect.log("Archive created", { size });
3141
+ yield* import_effect24.Effect.log("Archive created", { size });
2550
3142
  return { path: outputFile, size };
2551
3143
  });
2552
3144
  return { createZipArchive };
@@ -2555,32 +3147,32 @@ var ArchiveService = class extends import_effect23.Effect.Service()("ArchiveServ
2555
3147
  };
2556
3148
 
2557
3149
  // src/services/deployment-api.ts
2558
- var import_effect24 = require("effect");
2559
- var DeploymentApiService = class extends import_effect24.Effect.Service()("DeploymentApiService", {
3150
+ var import_effect25 = require("effect");
3151
+ var DeploymentApiService = class extends import_effect25.Effect.Service()("DeploymentApiService", {
2560
3152
  accessors: true,
2561
3153
  dependencies: [ApiClientService.Default],
2562
- effect: import_effect24.Effect.gen(function* () {
3154
+ effect: import_effect25.Effect.gen(function* () {
2563
3155
  const apiClient = yield* ApiClientService;
2564
3156
  const getClient = apiClient.getClient.pipe(
2565
- import_effect24.Effect.mapError((err) => new DeploymentAuthError({ message: `Authentication failed: ${err.message}` }))
3157
+ import_effect25.Effect.mapError((err) => new DeploymentAuthError({ message: `Authentication failed: ${err.message}` }))
2566
3158
  );
2567
- const createDeployment = import_effect24.Effect.fn("DeploymentApiService.createDeployment")(function* (applicationId) {
2568
- yield* import_effect24.Effect.annotateCurrentSpan("applicationId", applicationId);
2569
- yield* import_effect24.Effect.log("Creating deployment", { applicationId });
3159
+ const createDeployment = import_effect25.Effect.fn("DeploymentApiService.createDeployment")(function* (applicationId) {
3160
+ yield* import_effect25.Effect.annotateCurrentSpan("applicationId", applicationId);
3161
+ yield* import_effect25.Effect.log("Creating deployment", { applicationId });
2570
3162
  const client = yield* getClient;
2571
- const deployment = yield* import_effect24.Effect.tryPromise({
3163
+ const deployment = yield* import_effect25.Effect.tryPromise({
2572
3164
  try: () => client.deployments.create({ applicationId }),
2573
3165
  catch: (error) => new DeploymentCreateError({
2574
3166
  message: `Failed to create deployment: ${error instanceof Error ? error.message : String(error)}`
2575
3167
  })
2576
3168
  });
2577
- yield* import_effect24.Effect.log("Deployment created", { deploymentId: deployment.id });
3169
+ yield* import_effect25.Effect.log("Deployment created", { deploymentId: deployment.id });
2578
3170
  return deployment.id;
2579
3171
  });
2580
- const startMultipartUpload = import_effect24.Effect.fn("DeploymentApiService.startMultipartUpload")(function* (deploymentId) {
2581
- yield* import_effect24.Effect.annotateCurrentSpan("deploymentId", deploymentId);
3172
+ const startMultipartUpload = import_effect25.Effect.fn("DeploymentApiService.startMultipartUpload")(function* (deploymentId) {
3173
+ yield* import_effect25.Effect.annotateCurrentSpan("deploymentId", deploymentId);
2582
3174
  const client = yield* getClient;
2583
- const result = yield* import_effect24.Effect.tryPromise({
3175
+ const result = yield* import_effect25.Effect.tryPromise({
2584
3176
  try: () => client.deployments.startUpload(deploymentId),
2585
3177
  catch: (error) => new UploadStartError({
2586
3178
  message: `Failed to start multipart upload: ${error instanceof Error ? error.message : String(error)}`
@@ -2588,9 +3180,9 @@ var DeploymentApiService = class extends import_effect24.Effect.Service()("Deplo
2588
3180
  });
2589
3181
  return result.uploadId;
2590
3182
  });
2591
- const getPresignedUrl = import_effect24.Effect.fn("DeploymentApiService.getPresignedUrl")(function* (deploymentId, uploadId, partNumber) {
3183
+ const getPresignedUrl = import_effect25.Effect.fn("DeploymentApiService.getPresignedUrl")(function* (deploymentId, uploadId, partNumber) {
2592
3184
  const client = yield* getClient;
2593
- const result = yield* import_effect24.Effect.tryPromise({
3185
+ const result = yield* import_effect25.Effect.tryPromise({
2594
3186
  try: () => client.deployments.getPresignedUrl(deploymentId, uploadId, partNumber),
2595
3187
  catch: (error) => new PresignedUrlError({
2596
3188
  message: `Failed to get presigned URL: ${error instanceof Error ? error.message : String(error)}`,
@@ -2599,11 +3191,11 @@ var DeploymentApiService = class extends import_effect24.Effect.Service()("Deplo
2599
3191
  });
2600
3192
  return result.url;
2601
3193
  });
2602
- const uploadPart = import_effect24.Effect.fn("DeploymentApiService.uploadPart")(function* (presignedUrl, data, partNumber) {
2603
- yield* import_effect24.Effect.annotateCurrentSpan("partNumber", partNumber);
2604
- yield* import_effect24.Effect.annotateCurrentSpan("size", data.length);
3194
+ const uploadPart = import_effect25.Effect.fn("DeploymentApiService.uploadPart")(function* (presignedUrl, data, partNumber) {
3195
+ yield* import_effect25.Effect.annotateCurrentSpan("partNumber", partNumber);
3196
+ yield* import_effect25.Effect.annotateCurrentSpan("size", data.length);
2605
3197
  const client = yield* getClient;
2606
- const result = yield* import_effect24.Effect.tryPromise({
3198
+ const result = yield* import_effect25.Effect.tryPromise({
2607
3199
  try: () => client.deployments.uploadPart(presignedUrl, data, partNumber),
2608
3200
  catch: (error) => new UploadPartError({
2609
3201
  message: `Failed to upload part ${partNumber}: ${error instanceof Error ? error.message : String(error)}`,
@@ -2612,21 +3204,21 @@ var DeploymentApiService = class extends import_effect24.Effect.Service()("Deplo
2612
3204
  });
2613
3205
  return result;
2614
3206
  });
2615
- const completeUpload = import_effect24.Effect.fn("DeploymentApiService.completeUpload")(function* (deploymentId, uploadId, parts) {
2616
- yield* import_effect24.Effect.annotateCurrentSpan("deploymentId", deploymentId);
2617
- yield* import_effect24.Effect.annotateCurrentSpan("partsCount", parts.length);
3207
+ const completeUpload = import_effect25.Effect.fn("DeploymentApiService.completeUpload")(function* (deploymentId, uploadId, parts) {
3208
+ yield* import_effect25.Effect.annotateCurrentSpan("deploymentId", deploymentId);
3209
+ yield* import_effect25.Effect.annotateCurrentSpan("partsCount", parts.length);
2618
3210
  const client = yield* getClient;
2619
- yield* import_effect24.Effect.tryPromise({
3211
+ yield* import_effect25.Effect.tryPromise({
2620
3212
  try: () => client.deployments.completeUpload(deploymentId, uploadId, parts),
2621
3213
  catch: (error) => new UploadCompleteError({
2622
3214
  message: `Failed to complete upload: ${error instanceof Error ? error.message : String(error)}`
2623
3215
  })
2624
3216
  });
2625
- yield* import_effect24.Effect.log("Upload completed successfully");
3217
+ yield* import_effect25.Effect.log("Upload completed successfully");
2626
3218
  });
2627
- const getDeploymentStatus = import_effect24.Effect.fn("DeploymentApiService.getDeploymentStatus")(function* (deploymentId) {
3219
+ const getDeploymentStatus = import_effect25.Effect.fn("DeploymentApiService.getDeploymentStatus")(function* (deploymentId) {
2628
3220
  const client = yield* getClient;
2629
- const deployment = yield* import_effect24.Effect.tryPromise({
3221
+ const deployment = yield* import_effect25.Effect.tryPromise({
2630
3222
  try: () => client.deployments.get(deploymentId),
2631
3223
  catch: (error) => new DeploymentStatusError({
2632
3224
  message: `Failed to get deployment status: ${error instanceof Error ? error.message : String(error)}`
@@ -2634,9 +3226,9 @@ var DeploymentApiService = class extends import_effect24.Effect.Service()("Deplo
2634
3226
  });
2635
3227
  return deployment.status;
2636
3228
  });
2637
- const getLogs = import_effect24.Effect.fn("DeploymentApiService.getLogs")(function* (deploymentId, options) {
3229
+ const getLogs = import_effect25.Effect.fn("DeploymentApiService.getLogs")(function* (deploymentId, options) {
2638
3230
  const client = yield* getClient;
2639
- const result = yield* import_effect24.Effect.tryPromise({
3231
+ const result = yield* import_effect25.Effect.tryPromise({
2640
3232
  try: () => client.deployments.getLogs(deploymentId, options),
2641
3233
  catch: (error) => new DeploymentLogsFetchError({
2642
3234
  message: `Failed to get logs: ${error instanceof Error ? error.message : String(error)}`
@@ -2644,9 +3236,9 @@ var DeploymentApiService = class extends import_effect24.Effect.Service()("Deplo
2644
3236
  });
2645
3237
  return result;
2646
3238
  });
2647
- const getHostnames = import_effect24.Effect.fn("DeploymentApiService.getHostnames")(function* (deploymentId) {
3239
+ const getHostnames = import_effect25.Effect.fn("DeploymentApiService.getHostnames")(function* (deploymentId) {
2648
3240
  const client = yield* getClient;
2649
- const result = yield* import_effect24.Effect.tryPromise({
3241
+ const result = yield* import_effect25.Effect.tryPromise({
2650
3242
  try: () => client.deployments.getHostnames(deploymentId),
2651
3243
  catch: (error) => new DeploymentHostnamesFetchError({
2652
3244
  message: `Failed to get hostnames: ${error instanceof Error ? error.message : String(error)}`
@@ -2669,39 +3261,39 @@ var DeploymentApiService = class extends import_effect24.Effect.Service()("Deplo
2669
3261
  };
2670
3262
 
2671
3263
  // src/commands/platform/deploy/index.ts
2672
- var appOption5 = import_cli11.Options.text("app").pipe(
2673
- import_cli11.Options.withAlias("a"),
2674
- import_cli11.Options.withDescription("Application ID to deploy to (overrides the linked application)"),
2675
- import_cli11.Options.optional
2676
- );
2677
- var orgOption5 = import_cli11.Options.text("org").pipe(
2678
- import_cli11.Options.withAlias("o"),
2679
- import_cli11.Options.withDescription("Organization ID to use when automatically creating an application"),
2680
- import_cli11.Options.optional
2681
- );
2682
- var nameOption2 = import_cli11.Options.text("name").pipe(
2683
- import_cli11.Options.withAlias("n"),
2684
- import_cli11.Options.withDescription("Application name to use when automatically creating an application"),
2685
- import_cli11.Options.optional
2686
- );
2687
- var createAndLinkDeploymentApplication = (input) => import_effect25.Effect.gen(function* () {
3264
+ var appOption6 = import_cli12.Options.text("app").pipe(
3265
+ import_cli12.Options.withAlias("a"),
3266
+ import_cli12.Options.withDescription("Application ID to deploy to (overrides the linked application)"),
3267
+ import_cli12.Options.optional
3268
+ );
3269
+ var orgOption6 = import_cli12.Options.text("org").pipe(
3270
+ import_cli12.Options.withAlias("o"),
3271
+ import_cli12.Options.withDescription("Organization ID to use when automatically creating an application"),
3272
+ import_cli12.Options.optional
3273
+ );
3274
+ var nameOption2 = import_cli12.Options.text("name").pipe(
3275
+ import_cli12.Options.withAlias("n"),
3276
+ import_cli12.Options.withDescription("Application name to use when automatically creating an application"),
3277
+ import_cli12.Options.optional
3278
+ );
3279
+ var createAndLinkDeploymentApplication = (input) => import_effect26.Effect.gen(function* () {
2688
3280
  const projectLink = yield* ProjectLinkService;
2689
3281
  const apiClient = yield* ApiClientService;
2690
3282
  const { items: organizations } = yield* apiClient.request((client) => client.organizations.list());
2691
- const availableOrganizations = import_effect25.Option.match(input.org, {
3283
+ const availableOrganizations = import_effect26.Option.match(input.org, {
2692
3284
  onNone: () => organizations,
2693
3285
  onSome: (organizationId) => organizations.filter((organization2) => organization2.id === organizationId)
2694
3286
  });
2695
3287
  if (availableOrganizations.length === 0) {
2696
3288
  return yield* new NoOrganizationsFoundError({
2697
- message: import_effect25.Option.match(input.org, {
3289
+ message: import_effect26.Option.match(input.org, {
2698
3290
  onNone: () => 'No organization is available for this deployment. Create an organization, then run "gigadrive deploy" again.',
2699
3291
  onSome: (organizationId) => `Organization "${organizationId}" was not found among your organizations.`
2700
3292
  })
2701
3293
  });
2702
3294
  }
2703
- const organization = availableOrganizations.length === 1 ? availableOrganizations[0] : yield* import_cli11.Prompt.run(
2704
- import_cli11.Prompt.select({
3295
+ const organization = availableOrganizations.length === 1 ? availableOrganizations[0] : yield* import_cli12.Prompt.run(
3296
+ import_cli12.Prompt.select({
2705
3297
  message: "Select an organization for this application",
2706
3298
  choices: availableOrganizations.map((candidate) => ({
2707
3299
  title: candidate.name,
@@ -2710,7 +3302,7 @@ var createAndLinkDeploymentApplication = (input) => import_effect25.Effect.gen(f
2710
3302
  })
2711
3303
  );
2712
3304
  const inferredName = path.basename(input.cwd) || "Application";
2713
- const applicationName = import_effect25.Option.match(input.name, {
3305
+ const applicationName = import_effect26.Option.match(input.name, {
2714
3306
  onNone: () => inferredName,
2715
3307
  onSome: (name) => name
2716
3308
  }).trim();
@@ -2724,104 +3316,108 @@ var createAndLinkDeploymentApplication = (input) => import_effect25.Effect.gen(f
2724
3316
  applicationId: application.id,
2725
3317
  organizationId: organization.id
2726
3318
  });
2727
- yield* import_effect25.Console.log(`Created and linked application ${application.name} (${application.id}).`);
3319
+ yield* import_effect26.Console.log(`Created and linked application ${application.name} (${application.id}).`);
2728
3320
  return application.id;
2729
3321
  });
2730
- var resolveLinkedDeploymentApplication = (input) => import_effect25.Effect.gen(function* () {
3322
+ var resolveLinkedDeploymentApplication = (input) => import_effect26.Effect.gen(function* () {
2731
3323
  const projectLink = yield* ProjectLinkService;
2732
3324
  const existingLink = yield* projectLink.load(input.cwd);
2733
- return yield* import_effect25.Option.match(existingLink, {
3325
+ return yield* import_effect26.Option.match(existingLink, {
2734
3326
  onNone: () => createAndLinkDeploymentApplication(input),
2735
- onSome: (link) => import_effect25.Effect.succeed(link.applicationId)
3327
+ onSome: (link) => import_effect26.Effect.succeed(link.applicationId)
2736
3328
  });
2737
3329
  });
2738
- var resolveDeploymentApplication = (input) => import_effect25.Option.match(input.app, {
3330
+ var resolveDeploymentApplication = (input) => import_effect26.Option.match(input.app, {
2739
3331
  onNone: () => resolveLinkedDeploymentApplication(input),
2740
- onSome: import_effect25.Effect.succeed
3332
+ onSome: import_effect26.Effect.succeed
2741
3333
  });
2742
- var deployCommand = import_cli11.Command.make(
3334
+ var deployCommand = import_cli12.Command.make(
2743
3335
  "deploy",
2744
- { app: appOption5, org: orgOption5, name: nameOption2 },
2745
- ({ app, org, name }) => import_effect25.Effect.gen(function* () {
3336
+ { app: appOption6, org: orgOption6, name: nameOption2 },
3337
+ ({ app, org, name }) => import_effect26.Effect.gen(function* () {
2746
3338
  const projectConfig = yield* ProjectConfigService;
2747
3339
  const deploymentApi = yield* DeploymentApiService;
2748
3340
  const archiveService = yield* ArchiveService;
2749
3341
  const pathService = yield* import_platform9.Path.Path;
2750
3342
  const cwd = process.cwd();
2751
- yield* import_effect25.Effect.log("Starting deploy command");
3343
+ yield* import_effect26.Effect.log("Starting deploy command");
2752
3344
  const { config } = yield* projectConfig.resolve(cwd);
2753
3345
  const applicationId = yield* resolveDeploymentApplication({ app, org, name, cwd });
2754
- yield* import_effect25.Console.log("Creating deployment...");
3346
+ yield* import_effect26.Console.log("Creating deployment...");
2755
3347
  const deploymentId = yield* deploymentApi.createDeployment(applicationId);
2756
- yield* import_effect25.Console.log(`Deployment ID: ${deploymentId}`);
2757
- yield* import_effect25.Console.log("Creating archive...");
3348
+ yield* import_effect26.Console.log(`Deployment ID: ${deploymentId}`);
3349
+ yield* import_effect26.Console.log("Creating archive...");
2758
3350
  const archivePath = pathService.join(os4.tmpdir(), `project-${Date.now()}.zip`);
2759
3351
  const archive = yield* archiveService.createZipArchive(config.userArchive?.rootOverwrite || cwd, archivePath, {
2760
3352
  whitelist: config.userArchive?.fileWhitelist,
2761
- excludeFiles: config.excludeFiles
3353
+ excludeFiles: config.excludeFiles,
3354
+ buildsContainerImages: [
3355
+ ...config.entrypoints.flatMap((entrypoint) => entrypoint.container ? [entrypoint.container] : []),
3356
+ ...config.sidecars ?? []
3357
+ ].some((container) => container.source.type === "dockerfile")
2762
3358
  });
2763
- yield* import_effect25.Console.log(`Archive created (${(0, import_commons.formatFileSize)(archive.size)})`);
2764
- yield* import_effect25.Console.log("Uploading archive...");
3359
+ yield* import_effect26.Console.log(`Archive created (${(0, import_commons.formatFileSize)(archive.size)})`);
3360
+ yield* import_effect26.Console.log("Uploading archive...");
2765
3361
  yield* uploadArchive(deploymentId, archivePath, archive.size);
2766
- yield* import_effect25.Console.log("Upload complete.");
2767
- yield* import_effect25.Console.log("The deployment pipeline is now being provisioned. This may take a few seconds.");
3362
+ yield* import_effect26.Console.log("Upload complete.");
3363
+ yield* import_effect26.Console.log("The deployment pipeline is now being provisioned. This may take a few seconds.");
2768
3364
  yield* pollDeployment(deploymentId);
2769
3365
  }).pipe(
2770
- import_effect25.Effect.catchTags({
2771
- QuitException: () => import_effect25.Console.log("Cancelled."),
2772
- NotAuthenticatedError: (err) => import_effect25.Console.error('You are not logged in. Run "gigadrive login" to authenticate.').pipe(
2773
- import_effect25.Effect.andThen(import_effect25.Effect.fail(err))
3366
+ import_effect26.Effect.catchTags({
3367
+ QuitException: () => import_effect26.Console.log("Cancelled."),
3368
+ NotAuthenticatedError: (err) => import_effect26.Console.error('You are not logged in. Run "gigadrive login" to authenticate.').pipe(
3369
+ import_effect26.Effect.andThen(import_effect26.Effect.fail(err))
2774
3370
  ),
2775
- ApiRequestError: (err) => import_effect25.Console.error(`Application setup failed: ${err.message}`).pipe(import_effect25.Effect.andThen(import_effect25.Effect.fail(err))),
2776
- NoOrganizationsFoundError: (err) => import_effect25.Console.error(err.message).pipe(import_effect25.Effect.andThen(import_effect25.Effect.fail(err))),
2777
- ProjectLinkReadError: (err) => import_effect25.Console.error(err.message).pipe(import_effect25.Effect.andThen(import_effect25.Effect.fail(err))),
2778
- ProjectLinkWriteError: (err) => import_effect25.Console.error(err.message).pipe(import_effect25.Effect.andThen(import_effect25.Effect.fail(err))),
2779
- ConfigNotFoundError: (err) => import_effect25.Console.error(err.message).pipe(import_effect25.Effect.andThen(import_effect25.Effect.fail(err))),
2780
- ConfigParseError: (err) => import_effect25.Console.error(`Config parse error: ${err.message}`).pipe(import_effect25.Effect.andThen(import_effect25.Effect.fail(err))),
2781
- ConfigValidationError: (err) => import_effect25.Effect.gen(function* () {
3371
+ ApiRequestError: (err) => import_effect26.Console.error(`Application setup failed: ${err.message}`).pipe(import_effect26.Effect.andThen(import_effect26.Effect.fail(err))),
3372
+ NoOrganizationsFoundError: (err) => import_effect26.Console.error(err.message).pipe(import_effect26.Effect.andThen(import_effect26.Effect.fail(err))),
3373
+ ProjectLinkReadError: (err) => import_effect26.Console.error(err.message).pipe(import_effect26.Effect.andThen(import_effect26.Effect.fail(err))),
3374
+ ProjectLinkWriteError: (err) => import_effect26.Console.error(err.message).pipe(import_effect26.Effect.andThen(import_effect26.Effect.fail(err))),
3375
+ ConfigNotFoundError: (err) => import_effect26.Console.error(err.message).pipe(import_effect26.Effect.andThen(import_effect26.Effect.fail(err))),
3376
+ ConfigParseError: (err) => import_effect26.Console.error(`Config parse error: ${err.message}`).pipe(import_effect26.Effect.andThen(import_effect26.Effect.fail(err))),
3377
+ ConfigValidationError: (err) => import_effect26.Effect.gen(function* () {
2782
3378
  for (const e of err.errors) {
2783
- yield* import_effect25.Console.error(e);
3379
+ yield* import_effect26.Console.error(e);
2784
3380
  }
2785
- yield* import_effect25.Console.error(err.message);
2786
- }).pipe(import_effect25.Effect.andThen(import_effect25.Effect.fail(err))),
2787
- DeploymentCreateError: (err) => import_effect25.Console.error(`Deployment creation failed: ${err.message}`).pipe(import_effect25.Effect.andThen(import_effect25.Effect.fail(err))),
2788
- ArchiveCreateError: (err) => import_effect25.Console.error(`Archive creation failed: ${err.message}`).pipe(import_effect25.Effect.andThen(import_effect25.Effect.fail(err))),
2789
- UploadStartError: (err) => import_effect25.Console.error(`Upload failed: ${err.message}`).pipe(import_effect25.Effect.andThen(import_effect25.Effect.fail(err))),
2790
- UploadPartError: (err) => import_effect25.Console.error(`Upload failed: ${err.message}`).pipe(import_effect25.Effect.andThen(import_effect25.Effect.fail(err))),
2791
- UploadCompleteError: (err) => import_effect25.Console.error(`Upload failed: ${err.message}`).pipe(import_effect25.Effect.andThen(import_effect25.Effect.fail(err))),
2792
- PresignedUrlError: (err) => import_effect25.Console.error(`Upload failed: ${err.message}`).pipe(import_effect25.Effect.andThen(import_effect25.Effect.fail(err))),
2793
- DeploymentAuthError: (err) => import_effect25.Console.error(`Authentication failed: ${err.message}`).pipe(import_effect25.Effect.andThen(import_effect25.Effect.fail(err))),
2794
- DeploymentFailedError: (err) => import_effect25.Console.error(err.message).pipe(import_effect25.Effect.andThen(import_effect25.Effect.fail(err)))
3381
+ yield* import_effect26.Console.error(err.message);
3382
+ }).pipe(import_effect26.Effect.andThen(import_effect26.Effect.fail(err))),
3383
+ DeploymentCreateError: (err) => import_effect26.Console.error(`Deployment creation failed: ${err.message}`).pipe(import_effect26.Effect.andThen(import_effect26.Effect.fail(err))),
3384
+ ArchiveCreateError: (err) => import_effect26.Console.error(`Archive creation failed: ${err.message}`).pipe(import_effect26.Effect.andThen(import_effect26.Effect.fail(err))),
3385
+ UploadStartError: (err) => import_effect26.Console.error(`Upload failed: ${err.message}`).pipe(import_effect26.Effect.andThen(import_effect26.Effect.fail(err))),
3386
+ UploadPartError: (err) => import_effect26.Console.error(`Upload failed: ${err.message}`).pipe(import_effect26.Effect.andThen(import_effect26.Effect.fail(err))),
3387
+ UploadCompleteError: (err) => import_effect26.Console.error(`Upload failed: ${err.message}`).pipe(import_effect26.Effect.andThen(import_effect26.Effect.fail(err))),
3388
+ PresignedUrlError: (err) => import_effect26.Console.error(`Upload failed: ${err.message}`).pipe(import_effect26.Effect.andThen(import_effect26.Effect.fail(err))),
3389
+ DeploymentAuthError: (err) => import_effect26.Console.error(`Authentication failed: ${err.message}`).pipe(import_effect26.Effect.andThen(import_effect26.Effect.fail(err))),
3390
+ DeploymentFailedError: (err) => import_effect26.Console.error(err.message).pipe(import_effect26.Effect.andThen(import_effect26.Effect.fail(err)))
2795
3391
  })
2796
3392
  )
2797
3393
  );
2798
- var uploadArchive = (deploymentId, archivePath, fileSize) => import_effect25.Effect.gen(function* () {
3394
+ var uploadArchive = (deploymentId, archivePath, fileSize) => import_effect26.Effect.gen(function* () {
2799
3395
  const deploymentApi = yield* DeploymentApiService;
2800
3396
  const fs = yield* import_platform9.FileSystem.FileSystem;
2801
3397
  const uploadId = yield* deploymentApi.startMultipartUpload(deploymentId);
2802
3398
  const FILE_CHUNK_SIZE = 10 * 1024 * 1024;
2803
3399
  const numChunks = Math.ceil(fileSize / FILE_CHUNK_SIZE);
2804
- yield* import_effect25.Effect.log("Starting multipart upload", { uploadId, numChunks, fileSize });
2805
- const parts = yield* import_effect25.Effect.all(
3400
+ yield* import_effect26.Effect.log("Starting multipart upload", { uploadId, numChunks, fileSize });
3401
+ const parts = yield* import_effect26.Effect.all(
2806
3402
  Array.from({ length: numChunks }, (_, i) => {
2807
3403
  const partNumber = i + 1;
2808
3404
  const start = i * FILE_CHUNK_SIZE;
2809
3405
  const bytesToRead = partNumber < numChunks ? FILE_CHUNK_SIZE : fileSize - start;
2810
- return import_effect25.Effect.gen(function* () {
3406
+ return import_effect26.Effect.gen(function* () {
2811
3407
  const presignedUrl = yield* deploymentApi.getPresignedUrl(deploymentId, uploadId, partNumber);
2812
- const chunkData = yield* import_effect25.Stream.runCollect(fs.stream(archivePath, { offset: start, bytesToRead })).pipe(
2813
- import_effect25.Effect.map((chunks) => {
3408
+ const chunkData = yield* import_effect26.Stream.runCollect(fs.stream(archivePath, { offset: start, bytesToRead })).pipe(
3409
+ import_effect26.Effect.map((chunks) => {
2814
3410
  const arrays = Array.from(chunks);
2815
3411
  return Buffer.concat(arrays);
2816
3412
  }),
2817
- import_effect25.Effect.mapError(
3413
+ import_effect26.Effect.mapError(
2818
3414
  (error) => new UploadPartError({
2819
3415
  message: `Failed to read chunk ${partNumber}: ${String(error)}`,
2820
3416
  partNumber
2821
3417
  })
2822
3418
  )
2823
3419
  );
2824
- yield* import_effect25.Effect.log(`Uploading part ${partNumber}/${numChunks}`, { size: chunkData.length });
3420
+ yield* import_effect26.Effect.log(`Uploading part ${partNumber}/${numChunks}`, { size: chunkData.length });
2825
3421
  return yield* deploymentApi.uploadPart(presignedUrl, chunkData, partNumber);
2826
3422
  });
2827
3423
  }),
@@ -2829,20 +3425,20 @@ var uploadArchive = (deploymentId, archivePath, fileSize) => import_effect25.Eff
2829
3425
  );
2830
3426
  yield* deploymentApi.completeUpload(deploymentId, uploadId, parts);
2831
3427
  });
2832
- var pollDeployment = (deploymentId) => import_effect25.Effect.gen(function* () {
3428
+ var pollDeployment = (deploymentId) => import_effect26.Effect.gen(function* () {
2833
3429
  const deploymentApi = yield* DeploymentApiService;
2834
3430
  let lastStatus = "PENDING";
2835
3431
  let logOffset = 0;
2836
- yield* import_effect25.Console.log("Status: Pending");
2837
- yield* import_effect25.Effect.repeat(
2838
- import_effect25.Effect.gen(function* () {
2839
- const newStatus = yield* deploymentApi.getDeploymentStatus(deploymentId).pipe(import_effect25.Effect.catchTag("DeploymentStatusError", () => import_effect25.Effect.succeed(lastStatus)));
3432
+ yield* import_effect26.Console.log("Status: Pending");
3433
+ yield* import_effect26.Effect.repeat(
3434
+ import_effect26.Effect.gen(function* () {
3435
+ const newStatus = yield* deploymentApi.getDeploymentStatus(deploymentId).pipe(import_effect26.Effect.catchTag("DeploymentStatusError", () => import_effect26.Effect.succeed(lastStatus)));
2840
3436
  if (newStatus !== lastStatus) {
2841
3437
  lastStatus = newStatus;
2842
3438
  const label = newStatus.charAt(0) + newStatus.slice(1).toLowerCase();
2843
- yield* import_effect25.Console.log(`Status: ${label}`);
3439
+ yield* import_effect26.Console.log(`Status: ${label}`);
2844
3440
  }
2845
- const logsPage = yield* deploymentApi.getLogs(deploymentId, { offset: logOffset, limit: 100 }).pipe(import_effect25.Effect.catchTag("DeploymentLogsFetchError", () => import_effect25.Effect.succeed(null)));
3441
+ const logsPage = yield* deploymentApi.getLogs(deploymentId, { offset: logOffset, limit: 100 }).pipe(import_effect26.Effect.catchTag("DeploymentLogsFetchError", () => import_effect26.Effect.succeed(null)));
2846
3442
  if (logsPage) {
2847
3443
  for (const logEntry of logsPage.items) {
2848
3444
  logOffset++;
@@ -2850,86 +3446,86 @@ var pollDeployment = (deploymentId) => import_effect25.Effect.gen(function* () {
2850
3446
  }
2851
3447
  }
2852
3448
  if (newStatus === "ACTIVE") {
2853
- const hostnames = yield* deploymentApi.getHostnames(deploymentId).pipe(import_effect25.Effect.catchTag("DeploymentHostnamesFetchError", () => import_effect25.Effect.succeed([])));
3449
+ const hostnames = yield* deploymentApi.getHostnames(deploymentId).pipe(import_effect26.Effect.catchTag("DeploymentHostnamesFetchError", () => import_effect26.Effect.succeed([])));
2854
3450
  const active = hostnames.find((h) => h.active) ?? hostnames.at(0);
2855
3451
  if (active) {
2856
- yield* import_effect25.Console.log(`Deployed to https://${active.hostname}`);
3452
+ yield* import_effect26.Console.log(`Deployed to https://${active.hostname}`);
2857
3453
  } else {
2858
- yield* import_effect25.Console.log("Deployment is live.");
3454
+ yield* import_effect26.Console.log("Deployment is live.");
2859
3455
  }
2860
- return yield* import_effect25.Effect.fail("done");
3456
+ return yield* import_effect26.Effect.fail("done");
2861
3457
  }
2862
3458
  if (newStatus === "FAILED") {
2863
- return yield* import_effect25.Effect.fail(
3459
+ return yield* import_effect26.Effect.fail(
2864
3460
  new DeploymentFailedError({
2865
3461
  message: "The deployment failed. Please check the logs for more information."
2866
3462
  })
2867
3463
  );
2868
3464
  }
2869
3465
  }),
2870
- import_effect25.Schedule.addDelay(import_effect25.Schedule.forever, () => import_effect25.Duration.seconds(1))
3466
+ import_effect26.Schedule.addDelay(import_effect26.Schedule.forever, () => import_effect26.Duration.seconds(1))
2871
3467
  ).pipe(
2872
- import_effect25.Effect.catchAll((err) => {
2873
- if (err === "done") return import_effect25.Effect.void;
2874
- return import_effect25.Effect.fail(err);
3468
+ import_effect26.Effect.catchAll((err) => {
3469
+ if (err === "done") return import_effect26.Effect.void;
3470
+ return import_effect26.Effect.fail(err);
2875
3471
  })
2876
3472
  );
2877
3473
  });
2878
3474
  var printLog = (logEntry) => {
2879
3475
  switch (logEntry.type) {
2880
3476
  case "ERROR":
2881
- return import_effect25.Console.error(logEntry.message);
3477
+ return import_effect26.Console.error(logEntry.message);
2882
3478
  case "WARN":
2883
- return import_effect25.Console.warn(logEntry.message);
3479
+ return import_effect26.Console.warn(logEntry.message);
2884
3480
  default:
2885
- return import_effect25.Console.log(logEntry.message);
3481
+ return import_effect26.Console.log(logEntry.message);
2886
3482
  }
2887
3483
  };
2888
3484
 
2889
3485
  // src/commands/platform/index.ts
2890
- var platformBase = import_cli12.Command.make("platform", {}, () => import_effect26.Effect.void);
2891
- var platformCommand = platformBase.pipe(import_cli12.Command.withSubcommands([deployCommand]));
3486
+ var platformBase = import_cli13.Command.make("platform", {}, () => import_effect27.Effect.void);
3487
+ var platformCommand = platformBase.pipe(import_cli13.Command.withSubcommands([deployCommand]));
2892
3488
 
2893
3489
  // src/commands/setup/index.ts
2894
- var import_cli13 = require("@effect/cli");
2895
- var import_effect27 = require("effect");
2896
- var fileArg2 = import_cli13.Args.text({ name: "file" }).pipe(
2897
- import_cli13.Args.withDescription("Output file to write (default: .env.local)"),
2898
- import_cli13.Args.optional
3490
+ var import_cli14 = require("@effect/cli");
3491
+ var import_effect28 = require("effect");
3492
+ var fileArg2 = import_cli14.Args.text({ name: "file" }).pipe(
3493
+ import_cli14.Args.withDescription("Output file to write (default: .env.local)"),
3494
+ import_cli14.Args.optional
2899
3495
  );
2900
- var appOption6 = import_cli13.Options.text("app").pipe(
2901
- import_cli13.Options.withAlias("a"),
2902
- import_cli13.Options.withDescription("Application ID to set up (skips the interactive picker)"),
2903
- import_cli13.Options.optional
3496
+ var appOption7 = import_cli14.Options.text("app").pipe(
3497
+ import_cli14.Options.withAlias("a"),
3498
+ import_cli14.Options.withDescription("Application ID to set up (skips the interactive picker)"),
3499
+ import_cli14.Options.optional
2904
3500
  );
2905
- var orgOption6 = import_cli13.Options.text("org").pipe(
2906
- import_cli13.Options.withAlias("o"),
2907
- import_cli13.Options.withDescription("Only list applications belonging to this organization ID when picking"),
2908
- import_cli13.Options.optional
3501
+ var orgOption7 = import_cli14.Options.text("org").pipe(
3502
+ import_cli14.Options.withAlias("o"),
3503
+ import_cli14.Options.withDescription("Only list applications belonging to this organization ID when picking"),
3504
+ import_cli14.Options.optional
2909
3505
  );
2910
- var environmentOption2 = import_cli13.Options.text("environment").pipe(
2911
- import_cli13.Options.withAlias("e"),
2912
- import_cli13.Options.withDescription("Environment slug to resolve overrides for (e.g. preview)"),
2913
- import_cli13.Options.optional
3506
+ var environmentOption2 = import_cli14.Options.text("environment").pipe(
3507
+ import_cli14.Options.withAlias("e"),
3508
+ import_cli14.Options.withDescription("Environment slug to resolve overrides for (e.g. preview)"),
3509
+ import_cli14.Options.optional
2914
3510
  );
2915
- var yesOption2 = import_cli13.Options.boolean("yes").pipe(
2916
- import_cli13.Options.withAlias("y"),
2917
- import_cli13.Options.withDescription("Overwrite an existing file without confirmation")
3511
+ var yesOption3 = import_cli14.Options.boolean("yes").pipe(
3512
+ import_cli14.Options.withAlias("y"),
3513
+ import_cli14.Options.withDescription("Overwrite an existing file without confirmation")
2918
3514
  );
2919
- var rotateOption2 = import_cli13.Options.boolean("rotate").pipe(
2920
- import_cli13.Options.withDescription("Force a fresh API key, revoking the previous one")
3515
+ var rotateOption2 = import_cli14.Options.boolean("rotate").pipe(
3516
+ import_cli14.Options.withDescription("Force a fresh API key, revoking the previous one")
2921
3517
  );
2922
- var setupCommand = import_cli13.Command.make(
3518
+ var setupCommand = import_cli14.Command.make(
2923
3519
  "setup",
2924
3520
  {
2925
3521
  file: fileArg2,
2926
- app: appOption6,
2927
- org: orgOption6,
3522
+ app: appOption7,
3523
+ org: orgOption7,
2928
3524
  environment: environmentOption2,
2929
- yes: yesOption2,
3525
+ yes: yesOption3,
2930
3526
  rotate: rotateOption2
2931
3527
  },
2932
- ({ file, app, org, environment, yes, rotate }) => import_effect27.Effect.gen(function* () {
3528
+ ({ file, app, org, environment, yes, rotate }) => import_effect28.Effect.gen(function* () {
2933
3529
  const apiClient = yield* ApiClientService;
2934
3530
  const projectLink = yield* ProjectLinkService;
2935
3531
  const envFile = yield* EnvFileService;
@@ -2937,29 +3533,29 @@ var setupCommand = import_cli13.Command.make(
2937
3533
  const cwd = process.cwd();
2938
3534
  const existingLink = yield* projectLink.load(cwd);
2939
3535
  let applicationId;
2940
- if (import_effect27.Option.isSome(existingLink)) {
3536
+ if (import_effect28.Option.isSome(existingLink)) {
2941
3537
  applicationId = existingLink.value.applicationId;
2942
- if (import_effect27.Option.isSome(app) || import_effect27.Option.isSome(org)) {
2943
- yield* import_effect27.Console.log(
3538
+ if (import_effect28.Option.isSome(app) || import_effect28.Option.isSome(org)) {
3539
+ yield* import_effect28.Console.log(
2944
3540
  `Note: this directory is already linked to ${applicationId}; ignoring --app/--org. Run "gigadrive unlink" first to target a different application.`
2945
3541
  );
2946
3542
  }
2947
3543
  } else {
2948
- const organizationId = import_effect27.Option.getOrUndefined(org);
3544
+ const organizationId = import_effect28.Option.getOrUndefined(org);
2949
3545
  const { items: apps } = yield* apiClient.request((client) => client.applications.list({ organizationId }));
2950
3546
  if (apps.length === 0) {
2951
- return yield* import_effect27.Effect.fail(
3547
+ return yield* import_effect28.Effect.fail(
2952
3548
  new NoApplicationsFoundError({
2953
3549
  message: 'No applications found. Create one in the Gigadrive console, then run "gigadrive setup" again.'
2954
3550
  })
2955
3551
  );
2956
3552
  }
2957
- const explicitAppId = import_effect27.Option.getOrUndefined(app);
3553
+ const explicitAppId = import_effect28.Option.getOrUndefined(app);
2958
3554
  let chosen;
2959
3555
  if (explicitAppId !== void 0) {
2960
3556
  const match = apps.find((a) => a.id === explicitAppId);
2961
3557
  if (match === void 0) {
2962
- return yield* import_effect27.Effect.fail(
3558
+ return yield* import_effect28.Effect.fail(
2963
3559
  new ApplicationNotFoundError({
2964
3560
  message: `Application "${explicitAppId}" was not found among your applications.`
2965
3561
  })
@@ -2969,8 +3565,8 @@ var setupCommand = import_cli13.Command.make(
2969
3565
  } else if (apps.length === 1) {
2970
3566
  chosen = apps[0];
2971
3567
  } else {
2972
- chosen = yield* import_cli13.Prompt.run(
2973
- import_cli13.Prompt.select({
3568
+ chosen = yield* import_cli14.Prompt.run(
3569
+ import_cli14.Prompt.select({
2974
3570
  message: "Select an application to set up",
2975
3571
  choices: apps.map((a) => ({ title: `${a.name} (${a.organization.name})`, value: a }))
2976
3572
  })
@@ -2978,83 +3574,83 @@ var setupCommand = import_cli13.Command.make(
2978
3574
  }
2979
3575
  applicationId = chosen.id;
2980
3576
  yield* projectLink.save(cwd, { applicationId, organizationId: chosen.organization.id });
2981
- yield* import_effect27.Console.log(`Linked this directory to application ${applicationId}.`);
3577
+ yield* import_effect28.Console.log(`Linked this directory to application ${applicationId}.`);
2982
3578
  }
2983
- const target = import_effect27.Option.getOrElse(file, () => ".env.local");
2984
- const environmentSlug = import_effect27.Option.getOrUndefined(environment);
3579
+ const target = import_effect28.Option.getOrElse(file, () => ".env.local");
3580
+ const environmentSlug = import_effect28.Option.getOrUndefined(environment);
2985
3581
  const { items, omittedSensitive } = yield* apiClient.request(
2986
3582
  (client) => client.applications.envVars.pull(applicationId, environmentSlug ? { environment: environmentSlug } : void 0)
2987
3583
  );
2988
3584
  const existing = yield* envFile.read(target);
2989
- if (import_effect27.Option.isSome(existing) && !yes) {
2990
- const overwrite = yield* import_cli13.Prompt.run(
2991
- import_cli13.Prompt.confirm({ message: `${target} already exists. Overwrite?`, initial: false })
3585
+ if (import_effect28.Option.isSome(existing) && !yes) {
3586
+ const overwrite = yield* import_cli14.Prompt.run(
3587
+ import_cli14.Prompt.confirm({ message: `${target} already exists. Overwrite?`, initial: false })
2992
3588
  );
2993
3589
  if (!overwrite) {
2994
- return yield* import_effect27.Console.log("Cancelled.");
3590
+ return yield* import_effect28.Console.log("Cancelled.");
2995
3591
  }
2996
3592
  }
2997
3593
  const credentialEntries2 = yield* localCredentials.provision({
2998
3594
  applicationId,
2999
3595
  rotate,
3000
- existingContent: import_effect27.Option.getOrUndefined(existing)
3596
+ existingContent: import_effect28.Option.getOrUndefined(existing)
3001
3597
  });
3002
3598
  const entries = [...items.map((v) => ({ key: v.key, value: v.value })), ...credentialEntries2];
3003
3599
  yield* envFile.write(target, entries);
3004
3600
  const gitignored = yield* envFile.ensureGitignored(cwd, target);
3005
- yield* import_effect27.Console.log("\nLocal dev environment ready.");
3006
- yield* import_effect27.Console.log(` \u2022 Wrote ${items.length} variable(s) and API credentials to ${target}.`);
3601
+ yield* import_effect28.Console.log("\nLocal dev environment ready.");
3602
+ yield* import_effect28.Console.log(` \u2022 Wrote ${items.length} variable(s) and API credentials to ${target}.`);
3007
3603
  if (omittedSensitive > 0) {
3008
- yield* import_effect27.Console.log(
3604
+ yield* import_effect28.Console.log(
3009
3605
  ` \u2022 Skipped ${omittedSensitive} sensitive variable(s) (only production/preview hold secrets).`
3010
3606
  );
3011
3607
  }
3012
3608
  if (gitignored) {
3013
- yield* import_effect27.Console.log(` \u2022 Added ${target} to .gitignore.`);
3609
+ yield* import_effect28.Console.log(` \u2022 Added ${target} to .gitignore.`);
3014
3610
  }
3015
- yield* import_effect27.Console.log(" \u2022 Your app can now call the Gigadrive API via the SDK (GIGADRIVE_CLIENT_ID/SECRET).");
3611
+ yield* import_effect28.Console.log(" \u2022 Your app can now call the Gigadrive API via the SDK (GIGADRIVE_CLIENT_ID/SECRET).");
3016
3612
  }).pipe(
3017
- import_effect27.Effect.catchTags({
3613
+ import_effect28.Effect.catchTags({
3018
3614
  // Ctrl+C during a prompt is a deliberate cancel — exit 0.
3019
- QuitException: () => import_effect27.Console.log("Cancelled."),
3020
- NotAuthenticatedError: (err) => import_effect27.Console.error('You are not logged in. Run "gigadrive login" to authenticate.').pipe(
3021
- import_effect27.Effect.andThen(import_effect27.Effect.fail(err))
3615
+ QuitException: () => import_effect28.Console.log("Cancelled."),
3616
+ NotAuthenticatedError: (err) => import_effect28.Console.error('You are not logged in. Run "gigadrive login" to authenticate.').pipe(
3617
+ import_effect28.Effect.andThen(import_effect28.Effect.fail(err))
3022
3618
  ),
3023
- ApiRequestError: (err) => import_effect27.Console.error(`Setup failed: ${err.message}`).pipe(import_effect27.Effect.andThen(import_effect27.Effect.fail(err))),
3024
- NoApplicationsFoundError: (err) => import_effect27.Console.error(err.message).pipe(import_effect27.Effect.andThen(import_effect27.Effect.fail(err))),
3025
- ApplicationNotFoundError: (err) => import_effect27.Console.error(err.message).pipe(import_effect27.Effect.andThen(import_effect27.Effect.fail(err))),
3026
- ProjectLinkReadError: (err) => import_effect27.Console.error(err.message).pipe(import_effect27.Effect.andThen(import_effect27.Effect.fail(err))),
3027
- ProjectLinkWriteError: (err) => import_effect27.Console.error(err.message).pipe(import_effect27.Effect.andThen(import_effect27.Effect.fail(err))),
3028
- EnvFileReadError: (err) => import_effect27.Console.error(err.message).pipe(import_effect27.Effect.andThen(import_effect27.Effect.fail(err))),
3029
- EnvFileWriteError: (err) => import_effect27.Console.error(err.message).pipe(import_effect27.Effect.andThen(import_effect27.Effect.fail(err))),
3030
- DevCredentialsStoreReadError: (err) => import_effect27.Console.error(err.message).pipe(import_effect27.Effect.andThen(import_effect27.Effect.fail(err))),
3031
- DevCredentialsStoreWriteError: (err) => import_effect27.Console.error(err.message).pipe(import_effect27.Effect.andThen(import_effect27.Effect.fail(err)))
3619
+ ApiRequestError: (err) => import_effect28.Console.error(`Setup failed: ${err.message}`).pipe(import_effect28.Effect.andThen(import_effect28.Effect.fail(err))),
3620
+ NoApplicationsFoundError: (err) => import_effect28.Console.error(err.message).pipe(import_effect28.Effect.andThen(import_effect28.Effect.fail(err))),
3621
+ ApplicationNotFoundError: (err) => import_effect28.Console.error(err.message).pipe(import_effect28.Effect.andThen(import_effect28.Effect.fail(err))),
3622
+ ProjectLinkReadError: (err) => import_effect28.Console.error(err.message).pipe(import_effect28.Effect.andThen(import_effect28.Effect.fail(err))),
3623
+ ProjectLinkWriteError: (err) => import_effect28.Console.error(err.message).pipe(import_effect28.Effect.andThen(import_effect28.Effect.fail(err))),
3624
+ EnvFileReadError: (err) => import_effect28.Console.error(err.message).pipe(import_effect28.Effect.andThen(import_effect28.Effect.fail(err))),
3625
+ EnvFileWriteError: (err) => import_effect28.Console.error(err.message).pipe(import_effect28.Effect.andThen(import_effect28.Effect.fail(err))),
3626
+ DevCredentialsStoreReadError: (err) => import_effect28.Console.error(err.message).pipe(import_effect28.Effect.andThen(import_effect28.Effect.fail(err))),
3627
+ DevCredentialsStoreWriteError: (err) => import_effect28.Console.error(err.message).pipe(import_effect28.Effect.andThen(import_effect28.Effect.fail(err)))
3032
3628
  })
3033
3629
  )
3034
3630
  );
3035
3631
 
3036
3632
  // src/commands/whoami/index.ts
3037
- var import_cli14 = require("@effect/cli");
3038
- var import_effect28 = require("effect");
3039
- var whoamiCommand = import_cli14.Command.make(
3633
+ var import_cli15 = require("@effect/cli");
3634
+ var import_effect29 = require("effect");
3635
+ var whoamiCommand = import_cli15.Command.make(
3040
3636
  "whoami",
3041
3637
  {},
3042
- () => import_effect28.Effect.gen(function* () {
3638
+ () => import_effect29.Effect.gen(function* () {
3043
3639
  const auth = yield* AuthService;
3044
3640
  const info = yield* auth.getUserInfo;
3045
- yield* import_effect28.Console.log(JSON.stringify(info, null, 2));
3641
+ yield* import_effect29.Console.log(JSON.stringify(info, null, 2));
3046
3642
  }).pipe(
3047
- import_effect28.Effect.catchTags({
3048
- NotAuthenticatedError: () => import_effect28.Console.log('You are not logged in. Run "gigadrive login" to authenticate.'),
3049
- UserInfoFetchError: (err) => import_effect28.Console.error(`Failed to retrieve user info: ${err.message}`),
3050
- OAuthDiscoveryError: (err) => import_effect28.Console.error(`Failed to retrieve user info: ${err.message}`)
3643
+ import_effect29.Effect.catchTags({
3644
+ NotAuthenticatedError: () => import_effect29.Console.log('You are not logged in. Run "gigadrive login" to authenticate.'),
3645
+ UserInfoFetchError: (err) => import_effect29.Console.error(`Failed to retrieve user info: ${err.message}`),
3646
+ OAuthDiscoveryError: (err) => import_effect29.Console.error(`Failed to retrieve user info: ${err.message}`)
3051
3647
  })
3052
3648
  )
3053
3649
  );
3054
3650
 
3055
3651
  // src/index.ts
3056
- var gigadrive = import_cli15.Command.make("gigadrive", {}, () => import_effect29.Effect.void).pipe(
3057
- import_cli15.Command.withSubcommands([
3652
+ var gigadrive = import_cli16.Command.make("gigadrive", {}, () => import_effect30.Effect.void).pipe(
3653
+ import_cli16.Command.withSubcommands([
3058
3654
  loginCommand,
3059
3655
  logoutCommand,
3060
3656
  whoamiCommand,
@@ -3063,6 +3659,7 @@ var gigadrive = import_cli15.Command.make("gigadrive", {}, () => import_effect29
3063
3659
  appsCommand,
3064
3660
  envCommand,
3065
3661
  deploymentsCommand,
3662
+ domainsCommand,
3066
3663
  aiCommand,
3067
3664
  buildCommand,
3068
3665
  debugCommand,
@@ -3071,11 +3668,11 @@ var gigadrive = import_cli15.Command.make("gigadrive", {}, () => import_effect29
3071
3668
  setupCommand
3072
3669
  ])
3073
3670
  );
3074
- var cli = import_cli15.Command.run(gigadrive, {
3671
+ var cli = import_cli16.Command.run(gigadrive, {
3075
3672
  name: "Gigadrive CLI",
3076
3673
  version: package_default.version
3077
3674
  });
3078
- var BaseServices = import_effect29.Layer.mergeAll(
3675
+ var BaseServices = import_effect30.Layer.mergeAll(
3079
3676
  OAuthConfigService.Default,
3080
3677
  AuthStorageService.Default,
3081
3678
  PackageManagerService.Default,
@@ -3085,13 +3682,13 @@ var BaseServices = import_effect29.Layer.mergeAll(
3085
3682
  ProjectLinkService.Default,
3086
3683
  EnvFileService.Default,
3087
3684
  DevCredentialsStore.Default
3088
- ).pipe(import_effect29.Layer.provideMerge(AuthService.Default));
3089
- var ApiClientLive = import_effect29.Layer.provide(ApiClientService.Default, BaseServices);
3090
- var DeploymentApiLive = import_effect29.Layer.provide(DeploymentApiService.Default, BaseServices);
3091
- var LocalCredentialsLive = import_effect29.Layer.provide(LocalCredentialsService.Default, BaseServices);
3092
- var ServicesLive = import_effect29.Layer.mergeAll(BaseServices, ApiClientLive, DeploymentApiLive, LocalCredentialsLive);
3093
- var AppLive = import_effect29.Layer.mergeAll(ServicesLive, import_effect29.Logger.minimumLogLevel(import_effect29.LogLevel.Info)).pipe(
3094
- import_effect29.Layer.provideMerge(import_platform_node.NodeContext.layer)
3095
- );
3096
- import_platform_node.NodeRuntime.runMain(import_effect29.Effect.provide(cli(process.argv), AppLive));
3685
+ ).pipe(import_effect30.Layer.provideMerge(AuthService.Default));
3686
+ var ApiClientLive = import_effect30.Layer.provide(ApiClientService.Default, BaseServices);
3687
+ var DeploymentApiLive = import_effect30.Layer.provide(DeploymentApiService.Default, BaseServices);
3688
+ var LocalCredentialsLive = import_effect30.Layer.provide(LocalCredentialsService.Default, BaseServices);
3689
+ var ServicesLive = import_effect30.Layer.mergeAll(BaseServices, ApiClientLive, DeploymentApiLive, LocalCredentialsLive);
3690
+ var AppLive = import_effect30.Layer.mergeAll(ServicesLive, import_effect30.Logger.minimumLogLevel(import_effect30.LogLevel.Info)).pipe(
3691
+ import_effect30.Layer.provideMerge(import_platform_node.NodeContext.layer)
3692
+ );
3693
+ import_platform_node.NodeRuntime.runMain(import_effect30.Effect.provide(cli(process.argv), AppLive));
3097
3694
  //# sourceMappingURL=index.cjs.map