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 +1047 -450
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +1039 -441
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
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
|
|
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
|
|
30
|
+
var import_effect30 = require("effect");
|
|
31
31
|
|
|
32
32
|
// package.json
|
|
33
33
|
var package_default = {
|
|
34
34
|
name: "gigadrive",
|
|
35
|
-
version: "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({
|
|
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
|
-
|
|
1658
|
-
|
|
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/
|
|
1840
|
+
// src/commands/domains/index.ts
|
|
1803
1841
|
var import_cli7 = require("@effect/cli");
|
|
1804
|
-
var
|
|
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
|
|
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
|
|
2444
|
+
var EnvFileService = class extends import_effect17.Effect.Service()("EnvFileService", {
|
|
1867
2445
|
accessors: true,
|
|
1868
|
-
effect:
|
|
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 =
|
|
1872
|
-
return yield* fs.exists(filePath).pipe(
|
|
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 =
|
|
2452
|
+
const read = import_effect17.Effect.fn("EnvFileService.read")(function* (filePath) {
|
|
1875
2453
|
const present = yield* exists(filePath);
|
|
1876
|
-
if (!present) return
|
|
1877
|
-
const contents = yield* fs.readFileString(filePath, "utf8").pipe(
|
|
1878
|
-
return
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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
|
|
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
|
|
2504
|
+
var import_effect18 = require("effect");
|
|
1927
2505
|
var os2 = __toESM(require("os"), 1);
|
|
1928
|
-
var DevCredentialsStore = class extends
|
|
2506
|
+
var DevCredentialsStore = class extends import_effect18.Effect.Service()("DevCredentialsStore", {
|
|
1929
2507
|
accessors: true,
|
|
1930
|
-
effect:
|
|
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 =
|
|
2514
|
+
const ensureDirectory = import_effect18.Effect.gen(function* () {
|
|
1937
2515
|
yield* fs.makeDirectory(storeDir, { recursive: true }).pipe(
|
|
1938
|
-
|
|
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
|
-
|
|
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 =
|
|
1952
|
-
const present = yield* fs.exists(storeFile).pipe(
|
|
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(
|
|
1955
|
-
const json = yield*
|
|
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*
|
|
1960
|
-
|
|
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 =
|
|
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 ?
|
|
2544
|
+
return entry ? import_effect18.Option.some(entry) : import_effect18.Option.none();
|
|
1967
2545
|
});
|
|
1968
|
-
const set =
|
|
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
|
-
|
|
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 =
|
|
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
|
|
2570
|
+
var LocalCredentialsService = class extends import_effect19.Effect.Service()("LocalCredentialsService", {
|
|
1993
2571
|
accessors: true,
|
|
1994
2572
|
dependencies: [ApiClientService.Default, DevCredentialsStore.Default],
|
|
1995
|
-
effect:
|
|
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 =
|
|
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 &&
|
|
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 (
|
|
2010
|
-
yield* apiClient.request((client) => client.apiKeys.delete(stored.value.apiKeyId)).pipe(
|
|
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
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
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
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
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 =
|
|
2039
|
-
|
|
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 =
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
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 =
|
|
2047
|
-
|
|
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 =
|
|
2050
|
-
var fileArg =
|
|
2051
|
-
|
|
2052
|
-
|
|
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 =
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
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
|
|
2060
|
-
|
|
2061
|
-
|
|
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 =
|
|
2064
|
-
|
|
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 =
|
|
2067
|
-
|
|
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) =>
|
|
2070
|
-
if (
|
|
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*
|
|
2075
|
-
onSome: (value) =>
|
|
2076
|
-
onNone: () => projectLink.resolve(process.cwd()).pipe(
|
|
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 =
|
|
2658
|
+
var envListCommand = import_cli8.Command.make(
|
|
2081
2659
|
"list",
|
|
2082
|
-
{ app:
|
|
2083
|
-
({ app, org }) =>
|
|
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*
|
|
2668
|
+
yield* import_effect20.Console.log("No environment variables set.");
|
|
2091
2669
|
return;
|
|
2092
2670
|
}
|
|
2093
2671
|
for (const v of items) {
|
|
2094
|
-
yield*
|
|
2672
|
+
yield* import_effect20.Console.log(`${v.key}=${v.sensitive ? "***" : v.value ?? ""}`);
|
|
2095
2673
|
}
|
|
2096
2674
|
}).pipe(
|
|
2097
|
-
|
|
2098
|
-
NotAuthenticatedError: (err) =>
|
|
2099
|
-
|
|
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) =>
|
|
2102
|
-
ProjectNotLinkedError: (err) =>
|
|
2103
|
-
ProjectLinkReadError: (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 =
|
|
2685
|
+
var envSetCommand = import_cli8.Command.make(
|
|
2108
2686
|
"set",
|
|
2109
|
-
{ keyValue: keyValueArg, app:
|
|
2110
|
-
({ keyValue, app, org, sensitive, env }) =>
|
|
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*
|
|
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 =
|
|
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*
|
|
2705
|
+
yield* import_effect20.Console.log(`Set ${created.key}.`);
|
|
2128
2706
|
}).pipe(
|
|
2129
|
-
|
|
2130
|
-
InvalidEnvVarFormatError: (err) =>
|
|
2131
|
-
NotAuthenticatedError: (err) =>
|
|
2132
|
-
|
|
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) =>
|
|
2135
|
-
ProjectNotLinkedError: (err) =>
|
|
2136
|
-
ProjectLinkReadError: (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 =
|
|
2718
|
+
var envRmCommand = import_cli8.Command.make(
|
|
2141
2719
|
"rm",
|
|
2142
|
-
{ keyOrId: keyOrIdArg, app:
|
|
2143
|
-
({ keyOrId, app, org }) =>
|
|
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*
|
|
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*
|
|
2736
|
+
yield* import_effect20.Console.log(`Removed ${target.key}.`);
|
|
2159
2737
|
}).pipe(
|
|
2160
|
-
|
|
2161
|
-
EnvVarNotFoundError: (err) =>
|
|
2162
|
-
NotAuthenticatedError: (err) =>
|
|
2163
|
-
|
|
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) =>
|
|
2166
|
-
ProjectNotLinkedError: (err) =>
|
|
2167
|
-
ProjectLinkReadError: (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 =
|
|
2749
|
+
var envPullCommand = import_cli8.Command.make(
|
|
2172
2750
|
"pull",
|
|
2173
2751
|
{
|
|
2174
2752
|
file: fileArg,
|
|
2175
|
-
app:
|
|
2753
|
+
app: appOption4,
|
|
2176
2754
|
environment: environmentOption,
|
|
2177
|
-
yes:
|
|
2755
|
+
yes: yesOption2,
|
|
2178
2756
|
withCredentials: withCredentialsOption,
|
|
2179
2757
|
rotate: rotateOption
|
|
2180
2758
|
},
|
|
2181
|
-
({ file, app, environment, yes, withCredentials, rotate }) =>
|
|
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*
|
|
2186
|
-
onSome: (value) =>
|
|
2187
|
-
onNone: () => projectLink.resolve(process.cwd()).pipe(
|
|
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 =
|
|
2190
|
-
const environmentSlug =
|
|
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 (
|
|
2196
|
-
const overwrite = yield*
|
|
2197
|
-
|
|
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*
|
|
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:
|
|
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*
|
|
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*
|
|
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*
|
|
2802
|
+
yield* import_effect20.Console.log(`Added ${target} to .gitignore.`);
|
|
2225
2803
|
}
|
|
2226
2804
|
}).pipe(
|
|
2227
|
-
|
|
2805
|
+
import_effect20.Effect.catchTags({
|
|
2228
2806
|
// Ctrl+C during the overwrite prompt is a deliberate cancel — exit 0.
|
|
2229
|
-
QuitException: () =>
|
|
2230
|
-
NotAuthenticatedError: (err) =>
|
|
2231
|
-
|
|
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) =>
|
|
2234
|
-
ProjectNotLinkedError: (err) =>
|
|
2235
|
-
ProjectLinkReadError: (err) =>
|
|
2236
|
-
EnvFileReadError: (err) =>
|
|
2237
|
-
EnvFileWriteError: (err) =>
|
|
2238
|
-
DevCredentialsStoreReadError: (err) =>
|
|
2239
|
-
DevCredentialsStoreWriteError: (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 =
|
|
2821
|
+
var envBase = import_cli8.Command.make("env", {}, () => import_effect20.Effect.void);
|
|
2244
2822
|
var envCommand = envBase.pipe(
|
|
2245
|
-
|
|
2823
|
+
import_cli8.Command.withSubcommands([envListCommand, envSetCommand, envRmCommand, envPullCommand])
|
|
2246
2824
|
);
|
|
2247
2825
|
|
|
2248
2826
|
// src/commands/link/index.ts
|
|
2249
|
-
var
|
|
2250
|
-
var
|
|
2251
|
-
var
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
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
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
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 =
|
|
2839
|
+
var linkCommand = import_cli9.Command.make(
|
|
2262
2840
|
"link",
|
|
2263
|
-
{ app:
|
|
2264
|
-
({ app, org }) =>
|
|
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 =
|
|
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*
|
|
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 =
|
|
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*
|
|
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*
|
|
2296
|
-
|
|
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*
|
|
2306
|
-
yield*
|
|
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
|
-
|
|
2886
|
+
import_effect21.Effect.catchTags({
|
|
2309
2887
|
// Ctrl+C during the picker is a deliberate cancel — exit 0.
|
|
2310
|
-
QuitException: () =>
|
|
2311
|
-
NotAuthenticatedError: (err) =>
|
|
2312
|
-
|
|
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) =>
|
|
2315
|
-
NoApplicationsFoundError: (err) =>
|
|
2316
|
-
ApplicationNotFoundError: (err) =>
|
|
2317
|
-
ProjectLinkWriteError: (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 =
|
|
2899
|
+
var unlinkCommand = import_cli9.Command.make(
|
|
2322
2900
|
"unlink",
|
|
2323
2901
|
{},
|
|
2324
|
-
() =>
|
|
2902
|
+
() => import_effect21.Effect.gen(function* () {
|
|
2325
2903
|
const projectLink = yield* ProjectLinkService;
|
|
2326
2904
|
yield* projectLink.remove(process.cwd());
|
|
2327
|
-
yield*
|
|
2905
|
+
yield* import_effect21.Console.log("Unlinked this directory.");
|
|
2328
2906
|
}).pipe(
|
|
2329
|
-
|
|
2330
|
-
ProjectLinkWriteError: (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
|
|
2337
|
-
var
|
|
2338
|
-
var loginCommand =
|
|
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
|
-
() =>
|
|
2342
|
-
yield*
|
|
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(
|
|
2923
|
+
const info = yield* auth.getUserInfo.pipe(import_effect22.Effect.catchAll(() => import_effect22.Effect.succeed({})));
|
|
2346
2924
|
const name = auth.inferUserName(info);
|
|
2347
|
-
yield*
|
|
2925
|
+
yield* import_effect22.Console.log(`You are now logged in as ${name}.`);
|
|
2348
2926
|
}).pipe(
|
|
2349
|
-
|
|
2350
|
-
LoginFlowError: (err) =>
|
|
2351
|
-
DeviceAuthorizationError: (err) =>
|
|
2352
|
-
AuthorizationDeniedError: (err) =>
|
|
2353
|
-
DeviceCodeExpiredError: (err) =>
|
|
2354
|
-
TokenExchangeError: (err) =>
|
|
2355
|
-
OAuthDiscoveryError: (err) =>
|
|
2356
|
-
AuthStorageWriteError: (err) =>
|
|
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
|
|
2363
|
-
var
|
|
2364
|
-
var logoutCommand =
|
|
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
|
-
() =>
|
|
2945
|
+
() => import_effect23.Effect.gen(function* () {
|
|
2368
2946
|
const auth = yield* AuthService;
|
|
2369
2947
|
yield* auth.logout;
|
|
2370
|
-
yield*
|
|
2948
|
+
yield* import_effect23.Console.log("Logged out.");
|
|
2371
2949
|
}).pipe(
|
|
2372
|
-
|
|
2373
|
-
AuthStorageWriteError: (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
|
|
2380
|
-
var
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
2409
|
-
|
|
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) =>
|
|
2412
|
-
const items = yield* fs.readDirectory(dir).pipe(
|
|
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*
|
|
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
|
|
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(
|
|
2437
|
-
var initializeIgnoreRules = (fs, pathService, baseDir, useIgnoreFiles, useManagedIgnore) =>
|
|
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
|
|
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) =>
|
|
3047
|
+
var getFilesToInclude = (fs, pathService, dir, ignoreRules) => import_effect24.Effect.gen(function* () {
|
|
2457
3048
|
const filesToInclude = [];
|
|
2458
|
-
const walkDir = (currentDir) =>
|
|
2459
|
-
const items = yield* fs.readDirectory(currentDir).pipe(
|
|
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*
|
|
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(
|
|
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
|
|
3072
|
+
var ArchiveService = class extends import_effect24.Effect.Service()("ArchiveService", {
|
|
2482
3073
|
accessors: true,
|
|
2483
|
-
effect:
|
|
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 =
|
|
2487
|
-
yield*
|
|
2488
|
-
yield*
|
|
2489
|
-
yield*
|
|
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*
|
|
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*
|
|
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
|
-
|
|
3102
|
+
import_effect24.Effect.map((files) => [files])
|
|
2511
3103
|
);
|
|
2512
3104
|
});
|
|
2513
|
-
const archiveExists = yield* fs.exists(outputFile).pipe(
|
|
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
|
-
|
|
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*
|
|
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
|
-
|
|
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*
|
|
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
|
|
2559
|
-
var DeploymentApiService = class extends
|
|
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:
|
|
3154
|
+
effect: import_effect25.Effect.gen(function* () {
|
|
2563
3155
|
const apiClient = yield* ApiClientService;
|
|
2564
3156
|
const getClient = apiClient.getClient.pipe(
|
|
2565
|
-
|
|
3157
|
+
import_effect25.Effect.mapError((err) => new DeploymentAuthError({ message: `Authentication failed: ${err.message}` }))
|
|
2566
3158
|
);
|
|
2567
|
-
const createDeployment =
|
|
2568
|
-
yield*
|
|
2569
|
-
yield*
|
|
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*
|
|
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*
|
|
3169
|
+
yield* import_effect25.Effect.log("Deployment created", { deploymentId: deployment.id });
|
|
2578
3170
|
return deployment.id;
|
|
2579
3171
|
});
|
|
2580
|
-
const startMultipartUpload =
|
|
2581
|
-
yield*
|
|
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*
|
|
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 =
|
|
3183
|
+
const getPresignedUrl = import_effect25.Effect.fn("DeploymentApiService.getPresignedUrl")(function* (deploymentId, uploadId, partNumber) {
|
|
2592
3184
|
const client = yield* getClient;
|
|
2593
|
-
const result = yield*
|
|
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 =
|
|
2603
|
-
yield*
|
|
2604
|
-
yield*
|
|
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*
|
|
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 =
|
|
2616
|
-
yield*
|
|
2617
|
-
yield*
|
|
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*
|
|
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*
|
|
3217
|
+
yield* import_effect25.Effect.log("Upload completed successfully");
|
|
2626
3218
|
});
|
|
2627
|
-
const getDeploymentStatus =
|
|
3219
|
+
const getDeploymentStatus = import_effect25.Effect.fn("DeploymentApiService.getDeploymentStatus")(function* (deploymentId) {
|
|
2628
3220
|
const client = yield* getClient;
|
|
2629
|
-
const deployment = yield*
|
|
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 =
|
|
3229
|
+
const getLogs = import_effect25.Effect.fn("DeploymentApiService.getLogs")(function* (deploymentId, options) {
|
|
2638
3230
|
const client = yield* getClient;
|
|
2639
|
-
const result = yield*
|
|
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 =
|
|
3239
|
+
const getHostnames = import_effect25.Effect.fn("DeploymentApiService.getHostnames")(function* (deploymentId) {
|
|
2648
3240
|
const client = yield* getClient;
|
|
2649
|
-
const result = yield*
|
|
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
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
);
|
|
2677
|
-
var
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
);
|
|
2682
|
-
var nameOption2 =
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
);
|
|
2687
|
-
var createAndLinkDeploymentApplication = (input) =>
|
|
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 =
|
|
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:
|
|
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*
|
|
2704
|
-
|
|
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 =
|
|
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*
|
|
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) =>
|
|
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*
|
|
3325
|
+
return yield* import_effect26.Option.match(existingLink, {
|
|
2734
3326
|
onNone: () => createAndLinkDeploymentApplication(input),
|
|
2735
|
-
onSome: (link) =>
|
|
3327
|
+
onSome: (link) => import_effect26.Effect.succeed(link.applicationId)
|
|
2736
3328
|
});
|
|
2737
3329
|
});
|
|
2738
|
-
var resolveDeploymentApplication = (input) =>
|
|
3330
|
+
var resolveDeploymentApplication = (input) => import_effect26.Option.match(input.app, {
|
|
2739
3331
|
onNone: () => resolveLinkedDeploymentApplication(input),
|
|
2740
|
-
onSome:
|
|
3332
|
+
onSome: import_effect26.Effect.succeed
|
|
2741
3333
|
});
|
|
2742
|
-
var deployCommand =
|
|
3334
|
+
var deployCommand = import_cli12.Command.make(
|
|
2743
3335
|
"deploy",
|
|
2744
|
-
{ app:
|
|
2745
|
-
({ app, org, name }) =>
|
|
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*
|
|
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*
|
|
3346
|
+
yield* import_effect26.Console.log("Creating deployment...");
|
|
2755
3347
|
const deploymentId = yield* deploymentApi.createDeployment(applicationId);
|
|
2756
|
-
yield*
|
|
2757
|
-
yield*
|
|
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*
|
|
2764
|
-
yield*
|
|
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*
|
|
2767
|
-
yield*
|
|
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
|
-
|
|
2771
|
-
QuitException: () =>
|
|
2772
|
-
NotAuthenticatedError: (err) =>
|
|
2773
|
-
|
|
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) =>
|
|
2776
|
-
NoOrganizationsFoundError: (err) =>
|
|
2777
|
-
ProjectLinkReadError: (err) =>
|
|
2778
|
-
ProjectLinkWriteError: (err) =>
|
|
2779
|
-
ConfigNotFoundError: (err) =>
|
|
2780
|
-
ConfigParseError: (err) =>
|
|
2781
|
-
ConfigValidationError: (err) =>
|
|
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*
|
|
3379
|
+
yield* import_effect26.Console.error(e);
|
|
2784
3380
|
}
|
|
2785
|
-
yield*
|
|
2786
|
-
}).pipe(
|
|
2787
|
-
DeploymentCreateError: (err) =>
|
|
2788
|
-
ArchiveCreateError: (err) =>
|
|
2789
|
-
UploadStartError: (err) =>
|
|
2790
|
-
UploadPartError: (err) =>
|
|
2791
|
-
UploadCompleteError: (err) =>
|
|
2792
|
-
PresignedUrlError: (err) =>
|
|
2793
|
-
DeploymentAuthError: (err) =>
|
|
2794
|
-
DeploymentFailedError: (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) =>
|
|
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*
|
|
2805
|
-
const parts = yield*
|
|
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
|
|
3406
|
+
return import_effect26.Effect.gen(function* () {
|
|
2811
3407
|
const presignedUrl = yield* deploymentApi.getPresignedUrl(deploymentId, uploadId, partNumber);
|
|
2812
|
-
const chunkData = yield*
|
|
2813
|
-
|
|
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
|
-
|
|
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*
|
|
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) =>
|
|
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*
|
|
2837
|
-
yield*
|
|
2838
|
-
|
|
2839
|
-
const newStatus = yield* deploymentApi.getDeploymentStatus(deploymentId).pipe(
|
|
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*
|
|
3439
|
+
yield* import_effect26.Console.log(`Status: ${label}`);
|
|
2844
3440
|
}
|
|
2845
|
-
const logsPage = yield* deploymentApi.getLogs(deploymentId, { offset: logOffset, limit: 100 }).pipe(
|
|
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(
|
|
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*
|
|
3452
|
+
yield* import_effect26.Console.log(`Deployed to https://${active.hostname}`);
|
|
2857
3453
|
} else {
|
|
2858
|
-
yield*
|
|
3454
|
+
yield* import_effect26.Console.log("Deployment is live.");
|
|
2859
3455
|
}
|
|
2860
|
-
return yield*
|
|
3456
|
+
return yield* import_effect26.Effect.fail("done");
|
|
2861
3457
|
}
|
|
2862
3458
|
if (newStatus === "FAILED") {
|
|
2863
|
-
return yield*
|
|
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
|
-
|
|
3466
|
+
import_effect26.Schedule.addDelay(import_effect26.Schedule.forever, () => import_effect26.Duration.seconds(1))
|
|
2871
3467
|
).pipe(
|
|
2872
|
-
|
|
2873
|
-
if (err === "done") return
|
|
2874
|
-
return
|
|
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
|
|
3477
|
+
return import_effect26.Console.error(logEntry.message);
|
|
2882
3478
|
case "WARN":
|
|
2883
|
-
return
|
|
3479
|
+
return import_effect26.Console.warn(logEntry.message);
|
|
2884
3480
|
default:
|
|
2885
|
-
return
|
|
3481
|
+
return import_effect26.Console.log(logEntry.message);
|
|
2886
3482
|
}
|
|
2887
3483
|
};
|
|
2888
3484
|
|
|
2889
3485
|
// src/commands/platform/index.ts
|
|
2890
|
-
var platformBase =
|
|
2891
|
-
var platformCommand = platformBase.pipe(
|
|
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
|
|
2895
|
-
var
|
|
2896
|
-
var fileArg2 =
|
|
2897
|
-
|
|
2898
|
-
|
|
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
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
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
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
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 =
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
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
|
|
2916
|
-
|
|
2917
|
-
|
|
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 =
|
|
2920
|
-
|
|
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 =
|
|
3518
|
+
var setupCommand = import_cli14.Command.make(
|
|
2923
3519
|
"setup",
|
|
2924
3520
|
{
|
|
2925
3521
|
file: fileArg2,
|
|
2926
|
-
app:
|
|
2927
|
-
org:
|
|
3522
|
+
app: appOption7,
|
|
3523
|
+
org: orgOption7,
|
|
2928
3524
|
environment: environmentOption2,
|
|
2929
|
-
yes:
|
|
3525
|
+
yes: yesOption3,
|
|
2930
3526
|
rotate: rotateOption2
|
|
2931
3527
|
},
|
|
2932
|
-
({ file, app, org, environment, yes, rotate }) =>
|
|
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 (
|
|
3536
|
+
if (import_effect28.Option.isSome(existingLink)) {
|
|
2941
3537
|
applicationId = existingLink.value.applicationId;
|
|
2942
|
-
if (
|
|
2943
|
-
yield*
|
|
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 =
|
|
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*
|
|
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 =
|
|
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*
|
|
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*
|
|
2973
|
-
|
|
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*
|
|
3577
|
+
yield* import_effect28.Console.log(`Linked this directory to application ${applicationId}.`);
|
|
2982
3578
|
}
|
|
2983
|
-
const target =
|
|
2984
|
-
const environmentSlug =
|
|
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 (
|
|
2990
|
-
const overwrite = yield*
|
|
2991
|
-
|
|
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*
|
|
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:
|
|
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*
|
|
3006
|
-
yield*
|
|
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*
|
|
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*
|
|
3609
|
+
yield* import_effect28.Console.log(` \u2022 Added ${target} to .gitignore.`);
|
|
3014
3610
|
}
|
|
3015
|
-
yield*
|
|
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
|
-
|
|
3613
|
+
import_effect28.Effect.catchTags({
|
|
3018
3614
|
// Ctrl+C during a prompt is a deliberate cancel — exit 0.
|
|
3019
|
-
QuitException: () =>
|
|
3020
|
-
NotAuthenticatedError: (err) =>
|
|
3021
|
-
|
|
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) =>
|
|
3024
|
-
NoApplicationsFoundError: (err) =>
|
|
3025
|
-
ApplicationNotFoundError: (err) =>
|
|
3026
|
-
ProjectLinkReadError: (err) =>
|
|
3027
|
-
ProjectLinkWriteError: (err) =>
|
|
3028
|
-
EnvFileReadError: (err) =>
|
|
3029
|
-
EnvFileWriteError: (err) =>
|
|
3030
|
-
DevCredentialsStoreReadError: (err) =>
|
|
3031
|
-
DevCredentialsStoreWriteError: (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
|
|
3038
|
-
var
|
|
3039
|
-
var whoamiCommand =
|
|
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
|
-
() =>
|
|
3638
|
+
() => import_effect29.Effect.gen(function* () {
|
|
3043
3639
|
const auth = yield* AuthService;
|
|
3044
3640
|
const info = yield* auth.getUserInfo;
|
|
3045
|
-
yield*
|
|
3641
|
+
yield* import_effect29.Console.log(JSON.stringify(info, null, 2));
|
|
3046
3642
|
}).pipe(
|
|
3047
|
-
|
|
3048
|
-
NotAuthenticatedError: () =>
|
|
3049
|
-
UserInfoFetchError: (err) =>
|
|
3050
|
-
OAuthDiscoveryError: (err) =>
|
|
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 =
|
|
3057
|
-
|
|
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 =
|
|
3671
|
+
var cli = import_cli16.Command.run(gigadrive, {
|
|
3075
3672
|
name: "Gigadrive CLI",
|
|
3076
3673
|
version: package_default.version
|
|
3077
3674
|
});
|
|
3078
|
-
var BaseServices =
|
|
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(
|
|
3089
|
-
var ApiClientLive =
|
|
3090
|
-
var DeploymentApiLive =
|
|
3091
|
-
var LocalCredentialsLive =
|
|
3092
|
-
var ServicesLive =
|
|
3093
|
-
var AppLive =
|
|
3094
|
-
|
|
3095
|
-
);
|
|
3096
|
-
import_platform_node.NodeRuntime.runMain(
|
|
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
|