eoas 3.0.5 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/bin/dev.js +3 -0
- package/bin/run.js +3 -0
- package/dist/commands/generate-certs.js +22 -2
- package/dist/commands/init.js +2 -2
- package/dist/commands/publish.js +55 -31
- package/dist/commands/republish.js +87 -27
- package/dist/commands/server/init.d.ts +17 -0
- package/dist/commands/server/init.js +654 -0
- package/dist/commands/server/validate.d.ts +10 -0
- package/dist/commands/server/validate.js +115 -0
- package/dist/lib/assets.d.ts +30 -8
- package/dist/lib/assets.js +158 -4
- package/dist/lib/auth.js +2 -1
- package/dist/lib/log.d.ts +8 -2
- package/dist/lib/log.js +47 -31
- package/dist/lib/ora.d.ts +10 -9
- package/dist/lib/ora.js +49 -88
- package/dist/lib/packageRunner.js +2 -1
- package/dist/lib/prompts.d.ts +32 -0
- package/dist/lib/prompts.js +86 -1
- package/dist/lib/serverConfig/choices.d.ts +62 -0
- package/dist/lib/serverConfig/choices.js +65 -0
- package/dist/lib/serverConfig/envCatalog.d.ts +41 -0
- package/dist/lib/serverConfig/envCatalog.js +582 -0
- package/dist/lib/serverConfig/helmValues.d.ts +22 -0
- package/dist/lib/serverConfig/helmValues.js +281 -0
- package/dist/lib/serverConfig/passwordPolicy.d.ts +3 -0
- package/dist/lib/serverConfig/passwordPolicy.js +36 -0
- package/dist/lib/serverUpdates.d.ts +45 -0
- package/dist/lib/serverUpdates.js +108 -0
- package/dist/lib/utils.d.ts +1 -0
- package/dist/lib/utils.js +18 -14
- package/package.json +8 -6
package/dist/lib/ora.js
CHANGED
|
@@ -2,101 +2,62 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ora = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
//
|
|
5
|
+
// Spinner drawn with the @clack/prompts spinner so it matches the CLI's
|
|
6
|
+
// visual identity. Keeps the ora-like call surface the commands already use
|
|
7
|
+
// (start/succeed/fail/warn/stop). In CI, non-TTY or debug runs the spinner
|
|
8
|
+
// degrades to plain log lines so output stays deterministic.
|
|
9
|
+
const clack = tslib_1.__importStar(require("@clack/prompts"));
|
|
10
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
6
11
|
const getenv_1 = require("getenv");
|
|
7
|
-
// eslint-disable-next-line
|
|
8
|
-
const ora_1 = tslib_1.__importDefault(require("ora"));
|
|
9
12
|
const log_1 = tslib_1.__importDefault(require("./log"));
|
|
10
|
-
// eslint-disable-next-line no-console
|
|
11
|
-
const logReal = console.log;
|
|
12
|
-
// eslint-disable-next-line no-console
|
|
13
|
-
const infoReal = console.info;
|
|
14
|
-
// eslint-disable-next-line no-console
|
|
15
|
-
const warnReal = console.warn;
|
|
16
|
-
// eslint-disable-next-line no-console
|
|
17
|
-
const errorReal = console.error;
|
|
18
13
|
const isCi = (0, getenv_1.boolish)('CI', false);
|
|
19
|
-
/**
|
|
20
|
-
* A custom ora spinner that sends the stream to stdout in CI, or non-TTY, instead of stderr (the default).
|
|
21
|
-
*
|
|
22
|
-
* @param options
|
|
23
|
-
* @returns
|
|
24
|
-
*/
|
|
25
14
|
function ora(options) {
|
|
26
|
-
const inputOptions = typeof options === 'string' ? { text: options } : options ?? {};
|
|
27
15
|
const disabled = log_1.default.isDebug || !process.stdin.isTTY || isCi;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const oraStopAndPersist = spinner.stopAndPersist.bind(spinner);
|
|
38
|
-
const logWrap = (method, args) => {
|
|
39
|
-
oraStop();
|
|
40
|
-
method(...args);
|
|
41
|
-
spinner.start();
|
|
42
|
-
};
|
|
43
|
-
const wrapNativeLogs = () => {
|
|
44
|
-
// eslint-disable-next-line no-console
|
|
45
|
-
console.log = (...args) => {
|
|
46
|
-
logWrap(logReal, args);
|
|
47
|
-
};
|
|
48
|
-
// eslint-disable-next-line no-console
|
|
49
|
-
console.info = (...args) => {
|
|
50
|
-
logWrap(infoReal, args);
|
|
51
|
-
};
|
|
52
|
-
// eslint-disable-next-line no-console
|
|
53
|
-
console.warn = (...args) => {
|
|
54
|
-
logWrap(warnReal, args);
|
|
55
|
-
};
|
|
56
|
-
// eslint-disable-next-line no-console
|
|
57
|
-
console.error = (...args) => {
|
|
58
|
-
logWrap(errorReal, args);
|
|
59
|
-
};
|
|
60
|
-
};
|
|
61
|
-
const resetNativeLogs = () => {
|
|
62
|
-
// eslint-disable-next-line no-console
|
|
63
|
-
console.log = logReal;
|
|
64
|
-
// eslint-disable-next-line no-console
|
|
65
|
-
console.info = infoReal;
|
|
66
|
-
// eslint-disable-next-line no-console
|
|
67
|
-
console.warn = warnReal;
|
|
68
|
-
// eslint-disable-next-line no-console
|
|
69
|
-
console.error = errorReal;
|
|
70
|
-
};
|
|
71
|
-
spinner.start = (text) => {
|
|
72
|
-
// wrapNativeLogs wraps calls to console so they always:
|
|
73
|
-
// 1. stop the spinner
|
|
74
|
-
// 2. log the message
|
|
75
|
-
// 3. start the spinner again
|
|
76
|
-
// Every restart of the spinner causes the spinner message to be logged again
|
|
77
|
-
// which makes logs look like
|
|
78
|
-
//
|
|
79
|
-
// - Exporting...
|
|
80
|
-
// [expo-cli] Starting Metro Bundler
|
|
81
|
-
// - Exporting...
|
|
82
|
-
// [expo-cli] Android Bundling complete 3492ms
|
|
83
|
-
// - Exporting...
|
|
84
|
-
//
|
|
85
|
-
// Skipping wrapping native logs removes the repeated interleaved "Exporting..." messages.
|
|
86
|
-
if (!disabled) {
|
|
87
|
-
wrapNativeLogs();
|
|
16
|
+
let text = typeof options === 'string' ? options : options?.text ?? '';
|
|
17
|
+
let active;
|
|
18
|
+
const finish = (message, code, fallback) => {
|
|
19
|
+
if (active) {
|
|
20
|
+
active.stop(message, code);
|
|
21
|
+
active = undefined;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
fallback(message);
|
|
88
25
|
}
|
|
89
|
-
return oraStart(text);
|
|
90
|
-
};
|
|
91
|
-
spinner.stopAndPersist = (options) => {
|
|
92
|
-
const result = oraStopAndPersist(options);
|
|
93
|
-
resetNativeLogs();
|
|
94
|
-
return result;
|
|
95
26
|
};
|
|
96
|
-
spinner
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
27
|
+
const spinner = {
|
|
28
|
+
start(nextText) {
|
|
29
|
+
text = nextText ?? text;
|
|
30
|
+
if (disabled) {
|
|
31
|
+
log_1.default.log(text);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
active = clack.spinner();
|
|
35
|
+
active.start(text);
|
|
36
|
+
}
|
|
37
|
+
return spinner;
|
|
38
|
+
},
|
|
39
|
+
succeed(nextText) {
|
|
40
|
+
finish(nextText ?? text, 0, message => {
|
|
41
|
+
log_1.default.succeed(message);
|
|
42
|
+
});
|
|
43
|
+
return spinner;
|
|
44
|
+
},
|
|
45
|
+
fail(nextText) {
|
|
46
|
+
finish(nextText ?? text, 2, message => {
|
|
47
|
+
log_1.default.fail(message);
|
|
48
|
+
});
|
|
49
|
+
return spinner;
|
|
50
|
+
},
|
|
51
|
+
warn(nextText) {
|
|
52
|
+
finish(chalk_1.default.yellow(nextText ?? text), 0, message => {
|
|
53
|
+
log_1.default.warn(message);
|
|
54
|
+
});
|
|
55
|
+
return spinner;
|
|
56
|
+
},
|
|
57
|
+
stop() {
|
|
58
|
+
finish(chalk_1.default.dim(text), 0, () => { });
|
|
59
|
+
return spinner;
|
|
60
|
+
},
|
|
100
61
|
};
|
|
101
62
|
return spinner;
|
|
102
63
|
}
|
package/dist/lib/prompts.d.ts
CHANGED
|
@@ -10,4 +10,36 @@ export declare function selectAsync<T>(message: string, choices: ExpoChoice<T>[]
|
|
|
10
10
|
warningMessageForDisabledEntries?: string;
|
|
11
11
|
}): Promise<T>;
|
|
12
12
|
export declare function toggleConfirmAsync(questions: prompts.PromptObject<any>, options?: Options): Promise<boolean>;
|
|
13
|
+
/** Returned by the clack-based prompts below when the user asks to go back one step. */
|
|
14
|
+
export declare const BACK: unique symbol;
|
|
15
|
+
export declare const BACK_INPUT = "<";
|
|
16
|
+
export type TextStepOptions = {
|
|
17
|
+
initial?: string;
|
|
18
|
+
/** Empty answers are allowed and become undefined. */
|
|
19
|
+
optional?: boolean;
|
|
20
|
+
secret?: boolean;
|
|
21
|
+
allowBack?: boolean;
|
|
22
|
+
validate?: (value: string) => true | string;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* clack redraws break as soon as a prompt line wraps, so the message plus the
|
|
26
|
+
* suffix must stay well under a terminal width; keep messages short and never
|
|
27
|
+
* use clack placeholders (Tab types them into the buffer and a skipped answer
|
|
28
|
+
* renders them as if submitted).
|
|
29
|
+
*/
|
|
30
|
+
export declare function textStep(message: string, options?: TextStepOptions): Promise<string | undefined | typeof BACK>;
|
|
31
|
+
export type SelectStepChoice<T> = {
|
|
32
|
+
title: string;
|
|
33
|
+
value: T;
|
|
34
|
+
description?: string;
|
|
35
|
+
};
|
|
36
|
+
export declare function selectStep<T>(message: string, choices: SelectStepChoice<T>[], options: {
|
|
37
|
+
allowBack: boolean;
|
|
38
|
+
initial?: T;
|
|
39
|
+
}): Promise<T | typeof BACK>;
|
|
40
|
+
export declare function yesNoStep(message: string, options: {
|
|
41
|
+
allowBack: boolean;
|
|
42
|
+
initial?: boolean;
|
|
43
|
+
}): Promise<boolean | typeof BACK>;
|
|
44
|
+
export declare function confirmStep(message: string, initial?: boolean): Promise<boolean>;
|
|
13
45
|
export declare function pressAnyKeyToContinueAsync(): Promise<void>;
|
package/dist/lib/prompts.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.pressAnyKeyToContinueAsync = exports.toggleConfirmAsync = exports.selectAsync = exports.confirmAsync = exports.promptAsync = void 0;
|
|
3
|
+
exports.pressAnyKeyToContinueAsync = exports.confirmStep = exports.yesNoStep = exports.selectStep = exports.textStep = exports.BACK_INPUT = exports.BACK = exports.toggleConfirmAsync = exports.selectAsync = exports.confirmAsync = exports.promptAsync = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
// This file is copied from eas-cli[https://github.com/expo/eas-cli] to ensure consistent user experience across the CLI.
|
|
6
|
+
const clack = tslib_1.__importStar(require("@clack/prompts"));
|
|
7
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
6
8
|
const os_1 = require("os");
|
|
7
9
|
const prompts_1 = tslib_1.__importDefault(require("prompts"));
|
|
8
10
|
async function promptAsync(questions, options = {}) {
|
|
@@ -52,6 +54,89 @@ async function toggleConfirmAsync(questions, options) {
|
|
|
52
54
|
return value ?? null;
|
|
53
55
|
}
|
|
54
56
|
exports.toggleConfirmAsync = toggleConfirmAsync;
|
|
57
|
+
/** Returned by the clack-based prompts below when the user asks to go back one step. */
|
|
58
|
+
exports.BACK = Symbol('back');
|
|
59
|
+
exports.BACK_INPUT = '<';
|
|
60
|
+
function ensureNotCancelled(value) {
|
|
61
|
+
if (clack.isCancel(value)) {
|
|
62
|
+
clack.cancel('Cancelled, nothing was written.');
|
|
63
|
+
process.exit(os_1.constants.signals.SIGINT + 128);
|
|
64
|
+
}
|
|
65
|
+
return value;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* clack redraws break as soon as a prompt line wraps, so the message plus the
|
|
69
|
+
* suffix must stay well under a terminal width; keep messages short and never
|
|
70
|
+
* use clack placeholders (Tab types them into the buffer and a skipped answer
|
|
71
|
+
* renders them as if submitted).
|
|
72
|
+
*/
|
|
73
|
+
async function textStep(message, options = {}) {
|
|
74
|
+
const hints = [];
|
|
75
|
+
if (options.optional) {
|
|
76
|
+
hints.push('optional');
|
|
77
|
+
}
|
|
78
|
+
if (options.allowBack) {
|
|
79
|
+
hints.push(`${exports.BACK_INPUT} back`);
|
|
80
|
+
}
|
|
81
|
+
const suffix = hints.length > 0 ? ` ${chalk_1.default.dim(`(${hints.join(' · ')})`)}` : '';
|
|
82
|
+
const validate = (v) => {
|
|
83
|
+
const value = v ?? '';
|
|
84
|
+
if ((options.allowBack && value === exports.BACK_INPUT) || (options.optional && value === '')) {
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
if (!options.validate) {
|
|
88
|
+
return options.optional || value !== '' ? undefined : 'Cannot be empty';
|
|
89
|
+
}
|
|
90
|
+
const result = options.validate(value);
|
|
91
|
+
return result === true ? undefined : result;
|
|
92
|
+
};
|
|
93
|
+
const value = ensureNotCancelled(options.secret
|
|
94
|
+
? await clack.password({ message: `${message}${suffix}`, validate })
|
|
95
|
+
: await clack.text({
|
|
96
|
+
message: `${message}${suffix}`,
|
|
97
|
+
initialValue: options.initial,
|
|
98
|
+
validate,
|
|
99
|
+
}));
|
|
100
|
+
const answer = (value ?? '').trim();
|
|
101
|
+
if (options.allowBack && answer === exports.BACK_INPUT) {
|
|
102
|
+
return exports.BACK;
|
|
103
|
+
}
|
|
104
|
+
return answer !== '' ? answer : undefined;
|
|
105
|
+
}
|
|
106
|
+
exports.textStep = textStep;
|
|
107
|
+
// Selection happens on indices (clack's Option type does not resolve with an
|
|
108
|
+
// open generic); -1 is the Back entry.
|
|
109
|
+
async function selectStep(message, choices, options) {
|
|
110
|
+
const list = choices.map((choice, index) => ({
|
|
111
|
+
value: index,
|
|
112
|
+
label: choice.title,
|
|
113
|
+
hint: choice.description,
|
|
114
|
+
}));
|
|
115
|
+
if (options.allowBack) {
|
|
116
|
+
list.push({ value: -1, label: '← Back', hint: 'previous step' });
|
|
117
|
+
}
|
|
118
|
+
const initialIndex = options.initial === undefined
|
|
119
|
+
? undefined
|
|
120
|
+
: choices.findIndex(choice => choice.value === options.initial);
|
|
121
|
+
const picked = ensureNotCancelled(await clack.select({
|
|
122
|
+
message,
|
|
123
|
+
options: list,
|
|
124
|
+
initialValue: initialIndex !== undefined && initialIndex >= 0 ? initialIndex : undefined,
|
|
125
|
+
}));
|
|
126
|
+
return picked === -1 ? exports.BACK : choices[picked].value;
|
|
127
|
+
}
|
|
128
|
+
exports.selectStep = selectStep;
|
|
129
|
+
async function yesNoStep(message, options) {
|
|
130
|
+
return await selectStep(message, [
|
|
131
|
+
{ title: 'Yes', value: true },
|
|
132
|
+
{ title: 'No', value: false },
|
|
133
|
+
], { allowBack: options.allowBack, initial: options.initial ?? false });
|
|
134
|
+
}
|
|
135
|
+
exports.yesNoStep = yesNoStep;
|
|
136
|
+
async function confirmStep(message, initial = false) {
|
|
137
|
+
return ensureNotCancelled(await clack.confirm({ message, initialValue: initial }));
|
|
138
|
+
}
|
|
139
|
+
exports.confirmStep = confirmStep;
|
|
55
140
|
async function pressAnyKeyToContinueAsync() {
|
|
56
141
|
process.stdin.setRawMode(true);
|
|
57
142
|
process.stdin.resume();
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export type Storage = 'aws-s3' | 's3-compatible' | 'gcs' | 'azure';
|
|
2
|
+
export type S3Provider = 'cloudflare-r2' | 'minio' | 'digitalocean-spaces' | 'supabase';
|
|
3
|
+
export type Delivery = 'cloudfront' | 'presigned' | 'through-server' | 'generic-cdn';
|
|
4
|
+
export type MasterKeySource = 'environment' | 'aws-secrets-manager';
|
|
5
|
+
export type AwsAuth = 'iam-role' | 'access-keys';
|
|
6
|
+
export type CacheMode = 'redis' | 'redis-sentinel' | 'local';
|
|
7
|
+
export type Replicas = 'single' | 'multi';
|
|
8
|
+
export type Deployment = 'docker' | 'binary' | 'helm';
|
|
9
|
+
export type GeoipStrategy = 'proxy-headers' | 'maxmind';
|
|
10
|
+
export type ServerChoices = {
|
|
11
|
+
baseUrl?: string;
|
|
12
|
+
jwtSecret?: string;
|
|
13
|
+
dbUrl?: string;
|
|
14
|
+
masterKeySource: MasterKeySource;
|
|
15
|
+
/** Generated value, only when masterKeySource is 'environment'. */
|
|
16
|
+
masterKey?: string;
|
|
17
|
+
masterKeySecretId?: string;
|
|
18
|
+
/** How the server authenticates against AWS (S3 and/or Secrets Manager). */
|
|
19
|
+
awsAuth?: AwsAuth;
|
|
20
|
+
storage: Storage;
|
|
21
|
+
s3Provider?: S3Provider;
|
|
22
|
+
s3BucketName?: string;
|
|
23
|
+
awsRegion?: string;
|
|
24
|
+
awsBaseEndpoint?: string;
|
|
25
|
+
forcePathStyle?: boolean;
|
|
26
|
+
gcsBucketName?: string;
|
|
27
|
+
azureContainerName?: string;
|
|
28
|
+
azureAccountName?: string;
|
|
29
|
+
delivery: Delivery;
|
|
30
|
+
cdnBaseUrl?: string;
|
|
31
|
+
replicas: Replicas;
|
|
32
|
+
cacheMode: CacheMode;
|
|
33
|
+
redisHost?: string;
|
|
34
|
+
redisPort?: string;
|
|
35
|
+
/** Always true in the wizard; only inference from an existing file can turn it off. */
|
|
36
|
+
dashboard?: boolean;
|
|
37
|
+
adminEmail?: string;
|
|
38
|
+
adminPassword?: string;
|
|
39
|
+
deployment: Deployment;
|
|
40
|
+
observe: boolean;
|
|
41
|
+
clickhouseUrl?: string;
|
|
42
|
+
geoip: boolean;
|
|
43
|
+
geoipStrategy?: GeoipStrategy;
|
|
44
|
+
maxmindAccountId?: string;
|
|
45
|
+
maxmindLicenseKey?: string;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Delivery routes available per storage backend. GCS and Azure sign URLs with
|
|
49
|
+
* the storage credential itself and have no server-side switch to stream
|
|
50
|
+
* assets instead, so 'through-server' only exists for the s3 family
|
|
51
|
+
* (DISABLE_S3_DIRECT_CDN). Generic CDN is always listed last.
|
|
52
|
+
*/
|
|
53
|
+
export declare function deliveryOptionsFor(storage: Storage): Delivery[];
|
|
54
|
+
export declare function cacheOptionsFor(replicas: Replicas): CacheMode[];
|
|
55
|
+
export declare const S3_PROVIDER_DEFAULTS: Record<S3Provider, {
|
|
56
|
+
label: string;
|
|
57
|
+
endpoint: string;
|
|
58
|
+
region: string;
|
|
59
|
+
forcePathStyle: boolean;
|
|
60
|
+
}>;
|
|
61
|
+
/** True when the generated env must carry AWS access keys. */
|
|
62
|
+
export declare function needsAwsAccessKeys(choices: ServerChoices): boolean;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// The server:init decision model: every choice the wizard collects, and the
|
|
3
|
+
// option sets that depend on previous answers. The env catalog
|
|
4
|
+
// (envCatalog.ts) and the helm generator (helmValues.ts) consume it.
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.needsAwsAccessKeys = exports.S3_PROVIDER_DEFAULTS = exports.cacheOptionsFor = exports.deliveryOptionsFor = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Delivery routes available per storage backend. GCS and Azure sign URLs with
|
|
9
|
+
* the storage credential itself and have no server-side switch to stream
|
|
10
|
+
* assets instead, so 'through-server' only exists for the s3 family
|
|
11
|
+
* (DISABLE_S3_DIRECT_CDN). Generic CDN is always listed last.
|
|
12
|
+
*/
|
|
13
|
+
function deliveryOptionsFor(storage) {
|
|
14
|
+
switch (storage) {
|
|
15
|
+
case 'aws-s3':
|
|
16
|
+
return ['cloudfront', 'presigned', 'through-server', 'generic-cdn'];
|
|
17
|
+
case 's3-compatible':
|
|
18
|
+
return ['presigned', 'through-server', 'generic-cdn'];
|
|
19
|
+
case 'gcs':
|
|
20
|
+
case 'azure':
|
|
21
|
+
return ['presigned', 'generic-cdn'];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.deliveryOptionsFor = deliveryOptionsFor;
|
|
25
|
+
function cacheOptionsFor(replicas) {
|
|
26
|
+
return replicas === 'multi' ? ['redis', 'redis-sentinel'] : ['redis', 'redis-sentinel', 'local'];
|
|
27
|
+
}
|
|
28
|
+
exports.cacheOptionsFor = cacheOptionsFor;
|
|
29
|
+
exports.S3_PROVIDER_DEFAULTS = {
|
|
30
|
+
'cloudflare-r2': {
|
|
31
|
+
label: 'Cloudflare R2',
|
|
32
|
+
endpoint: 'https://<account-id>.r2.cloudflarestorage.com',
|
|
33
|
+
region: 'auto',
|
|
34
|
+
forcePathStyle: false,
|
|
35
|
+
},
|
|
36
|
+
minio: {
|
|
37
|
+
label: 'MinIO',
|
|
38
|
+
endpoint: 'https://<your-minio-host>',
|
|
39
|
+
region: 'us-east-1',
|
|
40
|
+
forcePathStyle: true,
|
|
41
|
+
},
|
|
42
|
+
'digitalocean-spaces': {
|
|
43
|
+
label: 'DigitalOcean Spaces',
|
|
44
|
+
endpoint: 'https://<region>.digitaloceanspaces.com',
|
|
45
|
+
region: 'us-east-1',
|
|
46
|
+
forcePathStyle: false,
|
|
47
|
+
},
|
|
48
|
+
supabase: {
|
|
49
|
+
label: 'Supabase Storage',
|
|
50
|
+
endpoint: 'https://<project-ref>.storage.supabase.co/storage/v1/s3',
|
|
51
|
+
region: '<project-region>',
|
|
52
|
+
forcePathStyle: true,
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
/** True when the generated env must carry AWS access keys. */
|
|
56
|
+
function needsAwsAccessKeys(choices) {
|
|
57
|
+
if (choices.storage === 's3-compatible') {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
const usesAws = choices.storage === 'aws-s3' ||
|
|
61
|
+
choices.masterKeySource === 'aws-secrets-manager' ||
|
|
62
|
+
choices.delivery === 'cloudfront';
|
|
63
|
+
return usesAws && choices.awsAuth === 'access-keys';
|
|
64
|
+
}
|
|
65
|
+
exports.needsAwsAccessKeys = needsAwsAccessKeys;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type ServerChoices } from './choices';
|
|
2
|
+
export type EnvVarSpec = {
|
|
3
|
+
name: string;
|
|
4
|
+
applies: (c: ServerChoices) => boolean;
|
|
5
|
+
/** Required to boot the server; false renders the var commented out. */
|
|
6
|
+
required: boolean;
|
|
7
|
+
value: (c: ServerChoices) => string;
|
|
8
|
+
comment?: string;
|
|
9
|
+
/** Helm values key when the chart computes this var from a toggle. */
|
|
10
|
+
helmKey?: string;
|
|
11
|
+
/** Missing or placeholder value is a warning, not an error (the server boots without it). */
|
|
12
|
+
lenient?: boolean;
|
|
13
|
+
};
|
|
14
|
+
export type EnvSection = {
|
|
15
|
+
title: string;
|
|
16
|
+
note?: (c: ServerChoices) => string | undefined;
|
|
17
|
+
vars: EnvVarSpec[];
|
|
18
|
+
};
|
|
19
|
+
export declare const ENV_SECTIONS: EnvSection[];
|
|
20
|
+
export declare function applicableVars(choices: ServerChoices): EnvVarSpec[];
|
|
21
|
+
export declare function isPlaceholder(value: string): boolean;
|
|
22
|
+
/** Renders the .env.xprem content for the wizard's choices. */
|
|
23
|
+
export declare function renderEnvFile(choices: ServerChoices): string;
|
|
24
|
+
/** Parses a dotenv-style file into a name/value map. Commented vars are skipped. */
|
|
25
|
+
export declare function parseEnvFile(content: string): Record<string, string>;
|
|
26
|
+
export type ValidationIssue = {
|
|
27
|
+
level: 'error' | 'warning';
|
|
28
|
+
message: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Rebuilds the wizard choices implied by an env map, so the catalog's
|
|
32
|
+
* applicability rules can run against an existing file.
|
|
33
|
+
*/
|
|
34
|
+
export declare function inferChoicesFromEnv(env: Record<string, string>): ServerChoices;
|
|
35
|
+
/**
|
|
36
|
+
* Validates an env map against the catalog: every applicable required var is
|
|
37
|
+
* present, no placeholder is left, and the server's own consistency rules
|
|
38
|
+
* hold. Local storage mode is accepted (it has working defaults) even though
|
|
39
|
+
* the wizard never generates it.
|
|
40
|
+
*/
|
|
41
|
+
export declare function validateEnvMap(env: Record<string, string>, overrides?: Partial<ServerChoices>): ValidationIssue[];
|