sproutboat 0.53.0 → 0.54.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/CHANGELOG.md +45 -1
- package/README.md +114 -13
- package/SURFACE.md +40 -20
- package/package.json +7 -7
- package/src/account-field.ts +69 -0
- package/src/build.ts +12 -1
- package/src/cloud-deploy.ts +752 -0
- package/src/cloud-fake.ts +633 -0
- package/src/cloud-secrets.ts +121 -0
- package/src/cloud.ts +375 -0
- package/src/compile.ts +16 -3
- package/src/credentials.ts +455 -52
- package/src/d1-cli.ts +455 -0
- package/src/data-errors.ts +139 -0
- package/src/deployments-cli.ts +184 -0
- package/src/fake-login.ts +28 -0
- package/src/global-flags.ts +113 -0
- package/src/init-package.ts +100 -0
- package/src/main.ts +1184 -81
- package/src/options.ts +233 -0
- package/src/r2-objects.ts +365 -0
- package/src/run.ts +12 -6
- package/src/secrets-bulk.ts +51 -0
- package/src/sql-split.ts +68 -0
- package/src/standalone-build.ts +21 -3
- package/src/surface.ts +187 -59
- package/src/target.ts +95 -0
package/src/target.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which endpoint and which stored profile a command talks to. One pure function, so the precedence is written down
|
|
3
|
+
* once and tested:
|
|
4
|
+
*
|
|
5
|
+
* 1. `--api-url` and `--profile`, the flags. Both given must agree.
|
|
6
|
+
* 2. `SPROUTBOAT_API_URL` and `SPROUTBOAT_PROFILE`, the environment. Both set must agree. A flag beats the other
|
|
7
|
+
* kind of variable: `--profile` beats `SPROUTBOAT_API_URL`, and `--api-url` beats `SPROUTBOAT_PROFILE`.
|
|
8
|
+
* 3. The machine's active profile.
|
|
9
|
+
* 4. The default endpoint.
|
|
10
|
+
*
|
|
11
|
+
* A profile fixes its endpoint, so a profile named next to a different URL is an error, never a quiet pick. That
|
|
12
|
+
* is the mistake this exists to stop: a stored Community login deploying to Community when the Cloud was meant.
|
|
13
|
+
*/
|
|
14
|
+
import { PROFILE_NAME } from "./credentials";
|
|
15
|
+
|
|
16
|
+
export type ProfileSource = "--profile" | "SPROUTBOAT_PROFILE" | "active profile";
|
|
17
|
+
export type UrlSource = "--api-url" | "SPROUTBOAT_API_URL" | "profile" | "default";
|
|
18
|
+
|
|
19
|
+
export type Target = {
|
|
20
|
+
apiUrl: string;
|
|
21
|
+
source: UrlSource;
|
|
22
|
+
/** The profile selected by name, or the active one used for lack of anything else. Unset when the URL decided. */
|
|
23
|
+
profile?: { name: string; source: ProfileSource; exists: boolean };
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export type TargetInput = {
|
|
27
|
+
flagUrl?: string;
|
|
28
|
+
flagProfile?: string;
|
|
29
|
+
envUrl?: string;
|
|
30
|
+
envProfile?: string;
|
|
31
|
+
/** Stored profiles by name, with their endpoints. */
|
|
32
|
+
profiles: Readonly<Record<string, { apiUrl: string }>>;
|
|
33
|
+
activeProfile?: string;
|
|
34
|
+
defaultUrl: string;
|
|
35
|
+
/** `login` may name a profile that does not exist yet; it is made on save. */
|
|
36
|
+
allowNew?: boolean;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export class TargetError extends Error {}
|
|
40
|
+
|
|
41
|
+
const trim = (url: string) => url.replace(/\/$/, "");
|
|
42
|
+
|
|
43
|
+
export function chooseTarget(input: TargetInput): Target {
|
|
44
|
+
const flagUrl = input.flagUrl ? trim(input.flagUrl) : undefined;
|
|
45
|
+
const envUrl = input.envUrl ? trim(input.envUrl) : undefined;
|
|
46
|
+
|
|
47
|
+
const named = (
|
|
48
|
+
name: string,
|
|
49
|
+
source: "--profile" | "SPROUTBOAT_PROFILE",
|
|
50
|
+
otherUrl?: string,
|
|
51
|
+
otherSource?: "--api-url" | "SPROUTBOAT_API_URL",
|
|
52
|
+
newUrl?: string,
|
|
53
|
+
) => {
|
|
54
|
+
if (!PROFILE_NAME.test(name))
|
|
55
|
+
throw new TargetError(`${source} "${name}" is not a profile name (letters, digits, . _ -; at most 64)`);
|
|
56
|
+
const stored = input.profiles[name];
|
|
57
|
+
if (stored === undefined) {
|
|
58
|
+
if (!input.allowNew) {
|
|
59
|
+
const known = Object.keys(input.profiles);
|
|
60
|
+
throw new TargetError(
|
|
61
|
+
`no profile named "${name}"${known.length > 0 ? ` (profiles: ${known.join(", ")})` : ""}; create it with \`sproutboat login --profile ${name}\``,
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
const apiUrl = otherUrl ?? newUrl ?? trim(input.defaultUrl);
|
|
65
|
+
return {
|
|
66
|
+
apiUrl,
|
|
67
|
+
source:
|
|
68
|
+
otherUrl !== undefined && otherSource ? otherSource : newUrl !== undefined ? "SPROUTBOAT_API_URL" : "default",
|
|
69
|
+
profile: { name, source, exists: false },
|
|
70
|
+
} satisfies Target;
|
|
71
|
+
}
|
|
72
|
+
const apiUrl = trim(stored.apiUrl);
|
|
73
|
+
if (otherUrl !== undefined && otherUrl !== apiUrl)
|
|
74
|
+
throw new TargetError(
|
|
75
|
+
`the profile "${name}" is for ${apiUrl}, but ${otherSource} says ${otherUrl}; drop one of them`,
|
|
76
|
+
);
|
|
77
|
+
return { apiUrl, source: "profile", profile: { name, source, exists: true } } satisfies Target;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
if (input.flagProfile !== undefined) return named(input.flagProfile, "--profile", flagUrl, "--api-url", envUrl);
|
|
81
|
+
if (flagUrl !== undefined) return { apiUrl: flagUrl, source: "--api-url" };
|
|
82
|
+
if (input.envProfile !== undefined) {
|
|
83
|
+
// The environment names a profile and also a URL: they must be the same place.
|
|
84
|
+
return named(input.envProfile, "SPROUTBOAT_PROFILE", envUrl, "SPROUTBOAT_API_URL");
|
|
85
|
+
}
|
|
86
|
+
if (envUrl !== undefined) return { apiUrl: envUrl, source: "SPROUTBOAT_API_URL" };
|
|
87
|
+
const active = input.activeProfile;
|
|
88
|
+
if (active !== undefined && input.profiles[active])
|
|
89
|
+
return {
|
|
90
|
+
apiUrl: trim(input.profiles[active].apiUrl),
|
|
91
|
+
source: "profile",
|
|
92
|
+
profile: { name: active, source: "active profile", exists: true },
|
|
93
|
+
};
|
|
94
|
+
return { apiUrl: trim(input.defaultUrl), source: "default" };
|
|
95
|
+
}
|