netlify 27.10.1 → 27.11.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/commands/agents/agents-create.js +19 -33
- package/dist/commands/base-command.d.ts +1 -1
- package/dist/commands/base-command.js +8 -11
- package/dist/commands/clone/clone.js +5 -10
- package/dist/commands/completion/completion.js +5 -9
- package/dist/commands/create/create-action.js +16 -28
- package/dist/commands/database/db-init.js +17 -31
- package/dist/commands/database/db-migration-new.js +13 -23
- package/dist/commands/database/db-migration-pull.js +5 -9
- package/dist/commands/database/db-reset.js +5 -9
- package/dist/commands/deploy/deploy.js +23 -36
- package/dist/commands/env/env-list.js +5 -9
- package/dist/commands/functions/functions-create.js +35 -71
- package/dist/commands/functions/functions-invoke.js +5 -10
- package/dist/commands/init/init.js +12 -25
- package/dist/commands/link/link.js +26 -52
- package/dist/commands/logs/build.js +2 -4
- package/dist/commands/main.js +10 -17
- package/dist/commands/recipes/recipes.js +6 -16
- package/dist/commands/sites/sites-create.js +12 -22
- package/dist/commands/sites/sites-delete.js +3 -7
- package/dist/commands/switch/switch.js +5 -9
- package/dist/lib/edge-functions/editor-helper.js +3 -5
- package/dist/recipes/ai-context/index.js +9 -17
- package/dist/recipes/blobs-migrate/index.js +3 -7
- package/dist/recipes/vscode/index.js +6 -10
- package/dist/utils/build-info.js +3 -6
- package/dist/utils/deploy/deploy-site.js +21 -12
- package/dist/utils/deploy/upload-files.js +6 -2
- package/dist/utils/deploy/util.d.ts +1 -0
- package/dist/utils/deploy/util.js +1 -0
- package/dist/utils/exit-codes.d.ts +2 -0
- package/dist/utils/exit-codes.js +2 -0
- package/dist/utils/gh-auth.js +10 -22
- package/dist/utils/github-api.d.ts +22 -0
- package/dist/utils/github-api.js +47 -0
- package/dist/utils/init/config-github.js +29 -45
- package/dist/utils/init/config-manual.js +8 -28
- package/dist/utils/init/utils.js +14 -38
- package/dist/utils/prompts/confirm-prompt.js +4 -15
- package/dist/utils/proxy.js +7 -48
- package/dist/utils/redirects.js +3 -2
- package/dist/utils/rules-proxy.js +31 -29
- package/dist/utils/types.d.ts +2 -2
- package/package.json +10 -14
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { input, select } from '@inquirer/prompts';
|
|
2
2
|
import { chalk, logAndThrowError, log, logJson } from '../../utils/command-helpers.js';
|
|
3
3
|
import { startSpinner, stopSpinner } from '../../lib/spinner.js';
|
|
4
4
|
import { validatePrompt, validateAgent, formatStatus, getAgentName } from './utils.js';
|
|
@@ -13,15 +13,10 @@ export const agentsCreate = async (promptArg, options, command) => {
|
|
|
13
13
|
const isGitBased = Boolean(siteInfo.build_settings?.repo_branch);
|
|
14
14
|
// Interactive prompt if not provided
|
|
15
15
|
if (!prompt && !promptArg) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
message: 'What would you like the agent to do?',
|
|
21
|
-
validate: validatePrompt,
|
|
22
|
-
},
|
|
23
|
-
]);
|
|
24
|
-
finalPrompt = promptInput;
|
|
16
|
+
finalPrompt = await input({
|
|
17
|
+
message: 'What would you like the agent to do?',
|
|
18
|
+
validate: validatePrompt,
|
|
19
|
+
});
|
|
25
20
|
}
|
|
26
21
|
else {
|
|
27
22
|
finalPrompt = (promptArg || prompt) ?? '';
|
|
@@ -32,16 +27,11 @@ export const agentsCreate = async (promptArg, options, command) => {
|
|
|
32
27
|
}
|
|
33
28
|
// Agent selection if not provided
|
|
34
29
|
if (!agent) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
choices: AVAILABLE_AGENTS,
|
|
41
|
-
default: 'claude',
|
|
42
|
-
},
|
|
43
|
-
]);
|
|
44
|
-
agent = agentInput;
|
|
30
|
+
agent = await select({
|
|
31
|
+
message: 'Which agent would you like to use?',
|
|
32
|
+
choices: AVAILABLE_AGENTS,
|
|
33
|
+
default: 'claude',
|
|
34
|
+
});
|
|
45
35
|
}
|
|
46
36
|
else {
|
|
47
37
|
const agentIsValid = validateAgent(agent);
|
|
@@ -52,20 +42,16 @@ export const agentsCreate = async (promptArg, options, command) => {
|
|
|
52
42
|
if (isGitBased) {
|
|
53
43
|
if (!branch) {
|
|
54
44
|
const defaultBranch = siteInfo.build_settings?.repo_branch;
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return 'Branch name is required';
|
|
64
|
-
}
|
|
65
|
-
return true;
|
|
66
|
-
},
|
|
45
|
+
const branchInput = await input({
|
|
46
|
+
message: 'Which branch would you like to work on?',
|
|
47
|
+
default: defaultBranch,
|
|
48
|
+
validate: (value) => {
|
|
49
|
+
if (!value || value.trim().length === 0) {
|
|
50
|
+
return 'Branch name is required';
|
|
51
|
+
}
|
|
52
|
+
return true;
|
|
67
53
|
},
|
|
68
|
-
|
|
54
|
+
});
|
|
69
55
|
branch = branchInput.trim();
|
|
70
56
|
}
|
|
71
57
|
}
|
|
@@ -64,7 +64,7 @@ export default class BaseCommand extends Command {
|
|
|
64
64
|
/** Overrides the help output of commander with custom styling */
|
|
65
65
|
createHelp(): Help;
|
|
66
66
|
/** Will be called on the end of an action to track the metrics */
|
|
67
|
-
onEnd(error_?: unknown): Promise<
|
|
67
|
+
onEnd(error_?: unknown): Promise<undefined>;
|
|
68
68
|
authenticate(tokenFromFlag?: string): Promise<string>;
|
|
69
69
|
private refreshAccounts;
|
|
70
70
|
expensivelyAuthenticate(): Promise<string>;
|
|
@@ -8,23 +8,21 @@ import { NodeFS, NoopLogger } from '@netlify/build-info/node';
|
|
|
8
8
|
import { resolveConfig } from '@netlify/config';
|
|
9
9
|
import { getGlobalConfigStore, LocalState } from '@netlify/dev-utils';
|
|
10
10
|
import { isCI } from 'ci-info';
|
|
11
|
+
import { search } from '@inquirer/prompts';
|
|
11
12
|
import { Command, Option } from 'commander';
|
|
12
13
|
import debug from 'debug';
|
|
13
14
|
import { findUp } from 'find-up';
|
|
14
|
-
import inquirer from 'inquirer';
|
|
15
|
-
import inquirerAutocompletePrompt from 'inquirer-autocomplete-prompt';
|
|
16
15
|
import { deepMerge, pick } from '../utils/object-utilities.js';
|
|
17
16
|
import { getAgent } from '../lib/http-agent.js';
|
|
18
17
|
import { NETLIFY_CYAN, USER_AGENT, chalk, logAndThrowError, logJson, exit, getRequestUserAgent, getToken, log, version, normalizeConfig, padLeft, pollForToken, sortOptions, warn, logError, } from '../utils/command-helpers.js';
|
|
19
18
|
import { handleOptionError, isOptionError } from '../utils/command-error-handler.js';
|
|
19
|
+
import { EXIT_CODES } from '../utils/exit-codes.js';
|
|
20
20
|
import { getFrameworksAPIPaths } from '../utils/frameworks-api.js';
|
|
21
21
|
import { getSiteByName } from '../utils/get-site.js';
|
|
22
22
|
import { buildAuthorizeUrl } from '../utils/login-url.js';
|
|
23
23
|
import openBrowser from '../utils/open-browser.js';
|
|
24
24
|
import { isInteractive } from '../utils/scripted-commands.js';
|
|
25
25
|
import { identify, reportError, setCommandForErrorReporting, track } from '../utils/telemetry/index.js';
|
|
26
|
-
// load the autocomplete plugin
|
|
27
|
-
inquirer.registerPrompt('autocomplete', inquirerAutocompletePrompt);
|
|
28
26
|
/** Netlify CLI client id. Lives in bot@netlify.com */
|
|
29
27
|
// TODO: setup client for multiple environments
|
|
30
28
|
export const CLIENT_ID = 'd6f37de6614df7ae58664cfca524744d73807a377f5ee71f1a254f78412e3750';
|
|
@@ -97,20 +95,15 @@ async function selectWorkspace(project, filter) {
|
|
|
97
95
|
.map((pkg) => pkg.name || pkg.path)
|
|
98
96
|
.join(', ')}. Configure the project you want to work with and try again. Refer to https://ntl.fyi/configure-site for more information.`);
|
|
99
97
|
}
|
|
100
|
-
|
|
101
|
-
name: 'result',
|
|
102
|
-
// @ts-expect-error(serhalp) -- I think this is because `inquirer-autocomplete-prompt` extends known
|
|
103
|
-
// `type`s but TS doesn't know about it
|
|
104
|
-
type: 'autocomplete',
|
|
98
|
+
return await search({
|
|
105
99
|
message: 'Select the project you want to work with',
|
|
106
|
-
source: (
|
|
100
|
+
source: (input = '') => (project.workspace?.packages || [])
|
|
107
101
|
.filter((pkg) => pkg.path.includes(input))
|
|
108
102
|
.map((pkg) => ({
|
|
109
103
|
name: `${pkg.name ? `${chalk.bold(pkg.name)} ` : ''}${pkg.path} ${chalk.dim(`--filter ${pkg.name || pkg.path}`)}`,
|
|
110
104
|
value: pkg.path,
|
|
111
105
|
})),
|
|
112
106
|
});
|
|
113
|
-
return result;
|
|
114
107
|
}
|
|
115
108
|
return selected.path;
|
|
116
109
|
}
|
|
@@ -346,6 +339,10 @@ export default class BaseCommand extends Command {
|
|
|
346
339
|
catch (err) {
|
|
347
340
|
debug(`${this.name()}:onEnd`)(`Command: ${command}. Telemetry tracking failed: ${err instanceof Error ? err.message : err?.toString()}`);
|
|
348
341
|
}
|
|
342
|
+
// Inquirer prompts reject with this on Ctrl+C, but the error class isn't exported.
|
|
343
|
+
if (error_ instanceof Error && error_.name === 'ExitPromptError') {
|
|
344
|
+
return exit(EXIT_CODES.INTERRUPTED);
|
|
345
|
+
}
|
|
349
346
|
if (error_ !== undefined) {
|
|
350
347
|
logError(error_ instanceof Error ? error_ : format(error_));
|
|
351
348
|
exit(1);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { resolve } from 'path';
|
|
2
2
|
import { LocalState } from '@netlify/dev-utils';
|
|
3
|
-
import
|
|
3
|
+
import { input } from '@inquirer/prompts';
|
|
4
4
|
import { normalizeRepoUrl } from '../../utils/normalize-repo-url.js';
|
|
5
5
|
import { chalk, logAndThrowError, log, getToken, netlifyCommand } from '../../utils/command-helpers.js';
|
|
6
6
|
import { runGit } from '../../utils/run-git.js';
|
|
@@ -19,15 +19,10 @@ const isNetlifyGitServiceUrl = (repoUrl) => {
|
|
|
19
19
|
}
|
|
20
20
|
};
|
|
21
21
|
const getTargetDir = async (defaultDir) => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
message: 'Where should we clone the repository?',
|
|
27
|
-
default: defaultDir,
|
|
28
|
-
},
|
|
29
|
-
]);
|
|
30
|
-
return selectedDir;
|
|
22
|
+
return await input({
|
|
23
|
+
message: 'Where should we clone the repository?',
|
|
24
|
+
default: defaultDir,
|
|
25
|
+
});
|
|
31
26
|
};
|
|
32
27
|
const cloneRepo = async (repoUrl, targetDir, debug) => {
|
|
33
28
|
try {
|
|
@@ -2,7 +2,7 @@ import fs from 'fs';
|
|
|
2
2
|
import { homedir } from 'os';
|
|
3
3
|
import { dirname, join } from 'path';
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
|
-
import
|
|
5
|
+
import { confirm } from '@inquirer/prompts';
|
|
6
6
|
import { install, uninstall } from '@pnpm/tabtab';
|
|
7
7
|
import { generateAutocompletion } from '../../lib/completion/index.js';
|
|
8
8
|
import { logAndThrowError, log, chalk, checkFileForLine, TABTAB_CONFIG_LINE, AUTOLOAD_COMPINIT, } from '../../utils/command-helpers.js';
|
|
@@ -30,14 +30,10 @@ export const completionGenerate = async (_options, command) => {
|
|
|
30
30
|
!checkFileForLine(zshConfigFilepath, AUTOLOAD_COMPINIT)) {
|
|
31
31
|
log(`To enable Tabtab autocompletion with zsh, the following line may need to be added to your ~/.zshrc:`);
|
|
32
32
|
log(chalk.bold.cyan(`\n${AUTOLOAD_COMPINIT}\n`));
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
message: `Would you like to add it?`,
|
|
38
|
-
default: true,
|
|
39
|
-
},
|
|
40
|
-
]);
|
|
33
|
+
const compinitAdded = await confirm({
|
|
34
|
+
message: `Would you like to add it?`,
|
|
35
|
+
default: true,
|
|
36
|
+
});
|
|
41
37
|
if (compinitAdded) {
|
|
42
38
|
fs.readFile(zshConfigFilepath, 'utf8', (_err, data) => {
|
|
43
39
|
const updatedZshFile = AUTOLOAD_COMPINIT + '\n' + data;
|
|
@@ -6,13 +6,13 @@ import process from 'process';
|
|
|
6
6
|
import readline from 'readline';
|
|
7
7
|
import { pipeline } from 'stream/promises';
|
|
8
8
|
import { promisify } from 'util';
|
|
9
|
-
import inquirer from 'inquirer';
|
|
10
9
|
import fetch from 'node-fetch';
|
|
10
|
+
import { select } from '@inquirer/prompts';
|
|
11
11
|
import { LocalState } from '@netlify/dev-utils';
|
|
12
|
-
import { Octokit } from '@octokit/rest';
|
|
13
12
|
import { chalk, logAndThrowError, log, logJson, warn } from '../../utils/command-helpers.js';
|
|
14
13
|
import { ensureNetlifyIgnore } from '../../utils/gitignore.js';
|
|
15
14
|
import { getGitHubToken as promptForGitHubToken } from '../../utils/gh-auth.js';
|
|
15
|
+
import { requestGitHub } from '../../utils/github-api.js';
|
|
16
16
|
import { startSpinner, stopSpinner } from '../../lib/spinner.js';
|
|
17
17
|
import { isInteractive } from '../../utils/scripted-commands.js';
|
|
18
18
|
import { track } from '../../utils/telemetry/index.js';
|
|
@@ -25,8 +25,7 @@ const resolveGitHubToken = async (globalConfig) => {
|
|
|
25
25
|
const cached = globalConfig.get(`users.${userId}.auth.github`);
|
|
26
26
|
if (cached?.token) {
|
|
27
27
|
try {
|
|
28
|
-
|
|
29
|
-
await octokit.rest.users.getAuthenticated();
|
|
28
|
+
await requestGitHub(cached.token, 'GET', '/user');
|
|
30
29
|
return cached.token;
|
|
31
30
|
}
|
|
32
31
|
catch {
|
|
@@ -91,9 +90,8 @@ const selectRepoOwner = async (ghToken, repoOwnerFlag) => {
|
|
|
91
90
|
if (repoOwnerFlag) {
|
|
92
91
|
return repoOwnerFlag;
|
|
93
92
|
}
|
|
94
|
-
const
|
|
95
|
-
const
|
|
96
|
-
const { data: orgs } = await octokit.rest.orgs.listForAuthenticatedUser();
|
|
93
|
+
const user = await requestGitHub(ghToken, 'GET', '/user');
|
|
94
|
+
const orgs = await requestGitHub(ghToken, 'GET', '/user/orgs');
|
|
97
95
|
if (orgs.length === 0) {
|
|
98
96
|
return user.login;
|
|
99
97
|
}
|
|
@@ -101,15 +99,10 @@ const selectRepoOwner = async (ghToken, repoOwnerFlag) => {
|
|
|
101
99
|
{ name: `${user.login} (personal)`, value: user.login },
|
|
102
100
|
...orgs.map((org) => ({ name: org.login, value: org.login })),
|
|
103
101
|
];
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
message: 'Where should the GitHub repo be created?',
|
|
109
|
-
choices,
|
|
110
|
-
},
|
|
111
|
-
]);
|
|
112
|
-
return owner;
|
|
102
|
+
return await select({
|
|
103
|
+
message: 'Where should the GitHub repo be created?',
|
|
104
|
+
choices,
|
|
105
|
+
});
|
|
113
106
|
};
|
|
114
107
|
// TODO: Replace with api client call once the site repo endpoint is added to @netlify/open-api
|
|
115
108
|
const createGitHubRepo = async (siteId, repoName, providerToken, repoOwner, api, apiOpts) => {
|
|
@@ -197,18 +190,13 @@ export const createAction = async (promptArg, options, command) => {
|
|
|
197
190
|
accountSlug = accountSlugFlag;
|
|
198
191
|
}
|
|
199
192
|
else if (accounts.length > 1) {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
name: account.name,
|
|
208
|
-
})),
|
|
209
|
-
},
|
|
210
|
-
]);
|
|
211
|
-
accountSlug = selected;
|
|
193
|
+
accountSlug = await select({
|
|
194
|
+
message: 'Team:',
|
|
195
|
+
choices: accounts.map((account) => ({
|
|
196
|
+
value: account.slug,
|
|
197
|
+
name: account.name,
|
|
198
|
+
})),
|
|
199
|
+
});
|
|
212
200
|
}
|
|
213
201
|
else {
|
|
214
202
|
accountSlug = accounts[0]?.slug;
|
|
@@ -2,7 +2,7 @@ import { existsSync } from 'fs';
|
|
|
2
2
|
import { mkdir, readdir, writeFile } from 'fs/promises';
|
|
3
3
|
import { join } from 'path';
|
|
4
4
|
import { applyMigrations } from '@netlify/dev';
|
|
5
|
-
import
|
|
5
|
+
import { confirm, select } from '@inquirer/prompts';
|
|
6
6
|
import { chalk, log, netlifyCommand } from '../../utils/command-helpers.js';
|
|
7
7
|
import { startSpinner, stopSpinner } from '../../lib/spinner.js';
|
|
8
8
|
import { isInteractive } from '../../utils/scripted-commands.js';
|
|
@@ -32,14 +32,10 @@ const success = (text) => {
|
|
|
32
32
|
};
|
|
33
33
|
const carefullyWriteFile = async (filePath, data, projectRoot) => {
|
|
34
34
|
if (existsSync(filePath)) {
|
|
35
|
-
const
|
|
36
|
-
{
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
message: `Overwrite existing file .${filePath.replace(projectRoot, '')}?`,
|
|
40
|
-
},
|
|
41
|
-
]);
|
|
42
|
-
if (answers.overwrite) {
|
|
35
|
+
const overwrite = await confirm({
|
|
36
|
+
message: `Overwrite existing file .${filePath.replace(projectRoot, '')}?`,
|
|
37
|
+
});
|
|
38
|
+
if (overwrite) {
|
|
43
39
|
await writeFile(filePath, data);
|
|
44
40
|
}
|
|
45
41
|
}
|
|
@@ -62,19 +58,14 @@ const promptForQueryStyle = async (interactive) => {
|
|
|
62
58
|
return 'drizzle';
|
|
63
59
|
}
|
|
64
60
|
log('');
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
{ name: 'Direct SQL', value: 'raw' },
|
|
74
|
-
],
|
|
75
|
-
},
|
|
76
|
-
]);
|
|
77
|
-
return queryStyle;
|
|
61
|
+
return await select({
|
|
62
|
+
message: 'What is your preferred style?',
|
|
63
|
+
default: 'drizzle',
|
|
64
|
+
choices: [
|
|
65
|
+
{ name: 'Drizzle ORM (recommended)', value: 'drizzle' },
|
|
66
|
+
{ name: 'Direct SQL', value: 'raw' },
|
|
67
|
+
],
|
|
68
|
+
});
|
|
78
69
|
};
|
|
79
70
|
const promptForStarter = async (interactive) => {
|
|
80
71
|
if (!interactive) {
|
|
@@ -84,15 +75,10 @@ const promptForStarter = async (interactive) => {
|
|
|
84
75
|
log('To see the database in action, we can create some migrations with sample data');
|
|
85
76
|
log('and then query it. Alternatively, you can do this yourself at any time.');
|
|
86
77
|
log('');
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
message: 'Do you want to create sample data?',
|
|
92
|
-
default: true,
|
|
93
|
-
},
|
|
94
|
-
]);
|
|
95
|
-
return answer;
|
|
78
|
+
return await confirm({
|
|
79
|
+
message: 'Do you want to create sample data?',
|
|
80
|
+
default: true,
|
|
81
|
+
});
|
|
96
82
|
};
|
|
97
83
|
const installDependencies = async (pm, projectRoot, migrationsDirectory, queryStyle) => {
|
|
98
84
|
sectionHeading('Install dependencies');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readdir, mkdir, writeFile } from 'fs/promises';
|
|
2
2
|
import { join } from 'path';
|
|
3
|
-
import
|
|
3
|
+
import { input, select } from '@inquirer/prompts';
|
|
4
4
|
import { log, logJson } from '../../utils/command-helpers.js';
|
|
5
5
|
import { resolveMigrationsDirectory } from './util/migrations-path.js';
|
|
6
6
|
import { utcTimestampPrefix } from './util/timestamp.js';
|
|
@@ -69,15 +69,10 @@ export const migrationNew = async (options, command) => {
|
|
|
69
69
|
let scheme = options.scheme;
|
|
70
70
|
if (!description) {
|
|
71
71
|
if (isInteractive()) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
message: 'What is the purpose of this migration?',
|
|
77
|
-
validate: (input) => (input.trim().length > 0 ? true : 'Description cannot be empty'),
|
|
78
|
-
},
|
|
79
|
-
]);
|
|
80
|
-
description = answers.description;
|
|
72
|
+
description = await input({
|
|
73
|
+
message: 'What is the purpose of this migration?',
|
|
74
|
+
validate: (value) => (value.trim().length > 0 ? true : 'Description cannot be empty'),
|
|
75
|
+
});
|
|
81
76
|
}
|
|
82
77
|
else {
|
|
83
78
|
throw new Error(`--description <description> argument is required when not running interactively. Provide a description of the migration (e.g. --description "add users table").`);
|
|
@@ -86,19 +81,14 @@ export const migrationNew = async (options, command) => {
|
|
|
86
81
|
if (!scheme) {
|
|
87
82
|
const defaultScheme = detectedScheme ?? 'timestamp';
|
|
88
83
|
if (isInteractive()) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
name: '
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
],
|
|
98
|
-
default: defaultScheme,
|
|
99
|
-
},
|
|
100
|
-
]);
|
|
101
|
-
scheme = answers.scheme;
|
|
84
|
+
scheme = await select({
|
|
85
|
+
message: 'Numbering scheme:',
|
|
86
|
+
choices: [
|
|
87
|
+
{ name: 'Timestamp (e.g. 20260312143000) [Recommended]', value: 'timestamp' },
|
|
88
|
+
{ name: 'Sequential (e.g. 0001, 0002, ...)', value: 'sequential' },
|
|
89
|
+
],
|
|
90
|
+
default: defaultScheme,
|
|
91
|
+
});
|
|
102
92
|
}
|
|
103
93
|
else {
|
|
104
94
|
scheme = defaultScheme;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { rm, mkdir, writeFile } from 'fs/promises';
|
|
2
2
|
import { dirname, resolve, isAbsolute } from 'path';
|
|
3
|
-
import
|
|
3
|
+
import { confirm } from '@inquirer/prompts';
|
|
4
4
|
import { log, logJson } from '../../utils/command-helpers.js';
|
|
5
5
|
import execa from '../../utils/execa.js';
|
|
6
6
|
import { readApiErrorMessage } from './util/api-errors.js';
|
|
@@ -95,14 +95,10 @@ export const migrationPull = async (options, command) => {
|
|
|
95
95
|
return filePath;
|
|
96
96
|
});
|
|
97
97
|
if (!force) {
|
|
98
|
-
const
|
|
99
|
-
{
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
message: `This will overwrite all local migrations in ${migrationsDirectory} with ${String(migrations.length)} migration${migrations.length === 1 ? '' : 's'} from ${branch}. Continue?`,
|
|
103
|
-
default: false,
|
|
104
|
-
},
|
|
105
|
-
]);
|
|
98
|
+
const confirmed = await confirm({
|
|
99
|
+
message: `This will overwrite all local migrations in ${migrationsDirectory} with ${String(migrations.length)} migration${migrations.length === 1 ? '' : 's'} from ${branch}. Continue?`,
|
|
100
|
+
default: false,
|
|
101
|
+
});
|
|
106
102
|
if (!confirmed) {
|
|
107
103
|
log('Pull cancelled.');
|
|
108
104
|
return;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { rm } from 'fs/promises';
|
|
2
|
-
import
|
|
2
|
+
import { confirm } from '@inquirer/prompts';
|
|
3
3
|
import { resetDatabase } from '@netlify/dev';
|
|
4
4
|
import { log, logJson } from '../../utils/command-helpers.js';
|
|
5
5
|
import { isInteractive } from '../../utils/scripted-commands.js';
|
|
@@ -12,14 +12,10 @@ const discardLocalDatabase = async (error, options) => {
|
|
|
12
12
|
throw new Error(`${error.summary}\nRe-run with --force to delete ${directory} and start from an empty database.`);
|
|
13
13
|
}
|
|
14
14
|
log(error.summary);
|
|
15
|
-
const
|
|
16
|
-
{
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
message: `Delete ${directory} and start from an empty database?`,
|
|
20
|
-
default: false,
|
|
21
|
-
},
|
|
22
|
-
]);
|
|
15
|
+
const confirmed = await confirm({
|
|
16
|
+
message: `Delete ${directory} and start from an empty database?`,
|
|
17
|
+
default: false,
|
|
18
|
+
});
|
|
23
19
|
if (!confirmed) {
|
|
24
20
|
log('Reset cancelled.');
|
|
25
21
|
return;
|
|
@@ -2,8 +2,8 @@ import { randomBytes } from 'crypto';
|
|
|
2
2
|
import { stat } from 'fs/promises';
|
|
3
3
|
import { basename, resolve } from 'path';
|
|
4
4
|
import { stdin, stdout } from 'process';
|
|
5
|
+
import { confirm, input, select } from '@inquirer/prompts';
|
|
5
6
|
import { runCoreSteps } from '@netlify/build';
|
|
6
|
-
import inquirer from 'inquirer';
|
|
7
7
|
import { parseAllHeaders } from '@netlify/headers-parser';
|
|
8
8
|
import { parseAllRedirects } from '@netlify/redirect-parser';
|
|
9
9
|
import prettyjson from 'prettyjson';
|
|
@@ -89,16 +89,11 @@ const getDeployFolder = async ({ command, config, options, site, siteData, }) =>
|
|
|
89
89
|
// Generate copy-pasteable command with current options
|
|
90
90
|
const copyableCommand = generateDeployCommand({ ...options, dir: '<PATH>' }, [], command);
|
|
91
91
|
log(`\nTo specify directory non-interactively, use: ${copyableCommand}\n`);
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
default: '.',
|
|
98
|
-
filter: (input) => resolve(command.workingDir, input),
|
|
99
|
-
},
|
|
100
|
-
]);
|
|
101
|
-
deployFolder = promptPath;
|
|
92
|
+
const promptPath = await input({
|
|
93
|
+
message: 'Publish directory',
|
|
94
|
+
default: '.',
|
|
95
|
+
});
|
|
96
|
+
deployFolder = resolve(command.workingDir, promptPath);
|
|
102
97
|
}
|
|
103
98
|
return deployFolder;
|
|
104
99
|
};
|
|
@@ -276,14 +271,10 @@ const prepareProductionDeploy = async ({ api, siteData, options, command }) => {
|
|
|
276
271
|
log('\nTo override deployment lock (USE WITH CAUTION), use:');
|
|
277
272
|
log(` ${overrideCommand}`);
|
|
278
273
|
log('\nWarning: Only use --prod-if-unlocked if you are absolutely sure you want to override the deployment lock.\n');
|
|
279
|
-
const
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
message: 'Would you like to "unlock" deployments for production context to proceed?',
|
|
284
|
-
default: false,
|
|
285
|
-
},
|
|
286
|
-
]);
|
|
274
|
+
const unlockChoice = await confirm({
|
|
275
|
+
message: 'Would you like to "unlock" deployments for production context to proceed?',
|
|
276
|
+
default: false,
|
|
277
|
+
});
|
|
287
278
|
if (!unlockChoice)
|
|
288
279
|
exit(0);
|
|
289
280
|
await api.unlockDeploy({ deploy_id: siteData.published_deploy.id });
|
|
@@ -812,23 +803,19 @@ const promptForSiteAction = async (options, command, site) => {
|
|
|
812
803
|
if (availableTeams.length > 1) {
|
|
813
804
|
log(`\nYou must pick a --team: ${availableTeams.map((team) => team.slug).join(', ')}`);
|
|
814
805
|
}
|
|
815
|
-
const
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
},
|
|
829
|
-
],
|
|
830
|
-
},
|
|
831
|
-
]);
|
|
806
|
+
const initChoice = await select({
|
|
807
|
+
message: 'What would you like to do?',
|
|
808
|
+
choices: [
|
|
809
|
+
{
|
|
810
|
+
name: '⇄ Link this directory to an existing project',
|
|
811
|
+
value: 'link',
|
|
812
|
+
},
|
|
813
|
+
{
|
|
814
|
+
name: '+ Create & configure a new project',
|
|
815
|
+
value: 'create',
|
|
816
|
+
},
|
|
817
|
+
],
|
|
818
|
+
});
|
|
832
819
|
const siteData = initChoice === 'create' ? await sitesCreate({}, command) : await link({}, command);
|
|
833
820
|
site.id = siteData.id;
|
|
834
821
|
return siteData;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import ansiEscapes from 'ansi-escapes';
|
|
2
2
|
import AsciiTable from 'ascii-table';
|
|
3
3
|
import { isCI } from 'ci-info';
|
|
4
|
-
import
|
|
4
|
+
import { confirm } from '@inquirer/prompts';
|
|
5
5
|
import logUpdate from 'log-update';
|
|
6
6
|
import { chalk, log, logJson } from '../../utils/command-helpers.js';
|
|
7
7
|
import { SUPPORTED_CONTEXTS, getEnvelopeEnv, getHumanReadableScopes } from '../../utils/env/index.js';
|
|
@@ -69,14 +69,10 @@ export const envList = async (options, command) => {
|
|
|
69
69
|
return false;
|
|
70
70
|
}
|
|
71
71
|
logUpdate(getTable({ environment, hideValues: true, scopesColumn: true }));
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
message: 'Show values?',
|
|
77
|
-
default: false,
|
|
78
|
-
},
|
|
79
|
-
]);
|
|
72
|
+
const showValues = await confirm({
|
|
73
|
+
message: 'Show values?',
|
|
74
|
+
default: false,
|
|
75
|
+
});
|
|
80
76
|
if (showValues) {
|
|
81
77
|
// since inquirer adds a prompt, we need to account for it when printing the table again
|
|
82
78
|
log(ansiEscapes.eraseLines(3));
|