netlify-cli 27.11.2 → 27.12.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/base-command.js +2 -2
- package/dist/commands/dev/dev.js +1 -2
- package/dist/commands/env/env-clone.js +1 -1
- package/dist/commands/env/env-set.js +1 -1
- package/dist/commands/env/env-unset.js +1 -1
- package/dist/commands/functions/functions-create.js +3 -93
- package/dist/commands/init/index.js +6 -1
- package/dist/commands/init/init.d.ts +3 -1
- package/dist/commands/init/init.js +22 -2
- package/dist/commands/serve/serve.js +1 -2
- package/dist/commands/sites/sites-list.js +1 -1
- package/dist/commands/unlink/unlink.js +1 -1
- package/dist/lib/edge-functions/registry.js +0 -1
- package/dist/lib/exec-fetcher.js +1 -1
- package/dist/lib/functions/form-submissions-handler.js +2 -1
- package/dist/recipes/ai-context/context.js +2 -2
- package/dist/utils/dev.d.ts +0 -1
- package/dist/utils/dev.js +1 -27
- package/dist/utils/env/index.js +1 -3
- package/dist/utils/get-repo-data.js +1 -1
- package/dist/utils/init/agent-skills.d.ts +96 -0
- package/dist/utils/init/agent-skills.js +653 -0
- package/dist/utils/parse-raw-flags.js +1 -1
- package/dist/utils/proxy-server.d.ts +1 -2
- package/dist/utils/proxy-server.js +1 -2
- package/dist/utils/proxy.d.ts +1 -1
- package/dist/utils/proxy.js +7 -35
- package/dist/utils/types.d.ts +1 -1
- package/package.json +9 -10
- package/dist/utils/addons/prepare.d.ts +0 -13
- package/dist/utils/addons/prepare.js +0 -26
|
@@ -248,7 +248,7 @@ export default class BaseCommand extends Command {
|
|
|
248
248
|
};
|
|
249
249
|
help.longestSubcommandTermLength = (command) => getCommands(command).reduce((max, cmd) => Math.max(max, cmd.name().length), 0);
|
|
250
250
|
/** override the longestOptionTermLength to react on hide options flag */
|
|
251
|
-
help.longestOptionTermLength = (command, helper) => (command.noBaseOptions
|
|
251
|
+
help.longestOptionTermLength = (command, helper) => (!command.noBaseOptions &&
|
|
252
252
|
helper.visibleOptions(command).reduce((max, option) => Math.max(max, helper.optionTerm(option).length), 0)) ||
|
|
253
253
|
0;
|
|
254
254
|
help.formatHelp = (command, helper) => {
|
|
@@ -284,7 +284,7 @@ export default class BaseCommand extends Command {
|
|
|
284
284
|
if (argumentList.length !== 0) {
|
|
285
285
|
output = [...output, chalk.bold('ARGUMENTS'), formatHelpList(argumentList), ''];
|
|
286
286
|
}
|
|
287
|
-
if (command.#noBaseOptions
|
|
287
|
+
if (!command.#noBaseOptions) {
|
|
288
288
|
// Options
|
|
289
289
|
const optionList = helper
|
|
290
290
|
.visibleOptions(command)
|
package/dist/commands/dev/dev.js
CHANGED
|
@@ -91,7 +91,7 @@ export const dev = async (options, command) => {
|
|
|
91
91
|
log(`${NETLIFYDEVLOG} Injecting environment variable values for ${chalk.yellow('all scopes')}`);
|
|
92
92
|
}
|
|
93
93
|
env = await getDotEnvVariables({ devConfig, env, site });
|
|
94
|
-
const { accountId,
|
|
94
|
+
const { accountId, capabilities, siteUrl, timeouts } = await getSiteInformation({
|
|
95
95
|
// inherited from base command --offline
|
|
96
96
|
offline: options.offline,
|
|
97
97
|
api,
|
|
@@ -217,7 +217,6 @@ export const dev = async (options, command) => {
|
|
|
217
217
|
};
|
|
218
218
|
const inspectSettings = generateInspectSettings(options.edgeInspect, options.edgeInspectBrk);
|
|
219
219
|
await startProxyServer({
|
|
220
|
-
addonsUrls,
|
|
221
220
|
aiGatewayContext,
|
|
222
221
|
api,
|
|
223
222
|
blobsContext,
|
|
@@ -30,7 +30,7 @@ const cloneEnvVars = async ({ api, force, siteFrom, siteTo }) => {
|
|
|
30
30
|
const siteId = siteTo.id;
|
|
31
31
|
// @ts-expect-error TS(7031) FIXME: Binding element 'key' implicitly has an 'any' type... Remove this comment to see the full error message
|
|
32
32
|
const envVarsToDelete = envelopeTo.filter(({ key }) => keysFrom.includes(key));
|
|
33
|
-
if (envVarsToDelete.length !== 0 &&
|
|
33
|
+
if (envVarsToDelete.length !== 0 && !force) {
|
|
34
34
|
await promptEnvCloneOverwrite(siteTo.id, envVarsToDelete);
|
|
35
35
|
}
|
|
36
36
|
// delete marked env vars in parallel
|
|
@@ -34,7 +34,7 @@ const setInEnvelope = async ({ api, context, force, key, scope, secret, siteInfo
|
|
|
34
34
|
// @ts-expect-error TS(7006) FIXME: Parameter 'envVar' implicitly has an 'any' type.
|
|
35
35
|
const existing = envelopeVariables.find((envVar) => envVar.key === key);
|
|
36
36
|
// Checks if --force is passed and if it is an existing variaible, then we need to prompt the user
|
|
37
|
-
if (
|
|
37
|
+
if (!force && existing) {
|
|
38
38
|
await promptOverwriteEnvVariable(key);
|
|
39
39
|
}
|
|
40
40
|
const params = { accountId, siteId, key };
|
|
@@ -21,7 +21,7 @@ const unsetInEnvelope = async ({ api, context, force, key, siteInfo }) => {
|
|
|
21
21
|
// if not, no need to call delete; return early
|
|
22
22
|
return env;
|
|
23
23
|
}
|
|
24
|
-
if (
|
|
24
|
+
if (!force) {
|
|
25
25
|
await promptOverwriteEnvVariable(key);
|
|
26
26
|
}
|
|
27
27
|
const params = { accountId, siteId, key };
|
|
@@ -5,13 +5,12 @@ import { createRequire } from 'module';
|
|
|
5
5
|
import path, { dirname, join, relative } from 'path';
|
|
6
6
|
import process from 'process';
|
|
7
7
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
8
|
-
import {
|
|
8
|
+
import { input, search, select, Separator } from '@inquirer/prompts';
|
|
9
9
|
import { findUp } from 'find-up';
|
|
10
10
|
import fuzzy from 'fuzzy';
|
|
11
11
|
import fetch from 'node-fetch';
|
|
12
12
|
import { createSpinner } from 'nanospinner';
|
|
13
13
|
import { fileExistsAsync } from '../../lib/fs.js';
|
|
14
|
-
import { getAddons, getCurrentAddon, getSiteData } from '../../utils/addons/prepare.js';
|
|
15
14
|
import { NETLIFYDEVERR, NETLIFYDEVLOG, NETLIFYDEVWARN, chalk, logAndThrowError, log, } from '../../utils/command-helpers.js';
|
|
16
15
|
import { copyTemplateDir } from '../../utils/copy-template-dir/copy-template-dir.js';
|
|
17
16
|
import { getDotEnvVariables, injectEnvVariables } from '../../utils/dev.js';
|
|
@@ -313,8 +312,7 @@ const downloadFromURL = async function (command, options, argumentName, function
|
|
|
313
312
|
// read, execute, and delete function template file if exists
|
|
314
313
|
const fnTemplateFile = path.join(fnFolder, '.netlify-function-template.mjs');
|
|
315
314
|
if (await fileExistsAsync(fnTemplateFile)) {
|
|
316
|
-
const { default: {
|
|
317
|
-
await installAddons(command, addons, path.resolve(fnFolder));
|
|
315
|
+
const { default: { onComplete }, } = await import(pathToFileURL(fnTemplateFile).href);
|
|
318
316
|
await handleOnComplete({ command, onComplete });
|
|
319
317
|
// delete
|
|
320
318
|
await unlink(fnTemplateFile);
|
|
@@ -400,7 +398,7 @@ const scaffoldFromTemplate = async function (command, options, argumentName, fun
|
|
|
400
398
|
log(`${NETLIFYDEVLOG} Open in browser: https://github.com/netlify/cli/issues/new`);
|
|
401
399
|
}
|
|
402
400
|
else {
|
|
403
|
-
const {
|
|
401
|
+
const { lang, name: templateName, onComplete } = chosenTemplate;
|
|
404
402
|
const pathToTemplate = path.join(templatesDir, lang, templateName);
|
|
405
403
|
if (!fs.existsSync(pathToTemplate)) {
|
|
406
404
|
throw new Error(`There isn't a corresponding directory to the selected name. Template '${templateName}' is misconfigured`);
|
|
@@ -435,33 +433,12 @@ const scaffoldFromTemplate = async function (command, options, argumentName, fun
|
|
|
435
433
|
if (funcType === 'edge') {
|
|
436
434
|
await registerEFInToml(name, command.netlify);
|
|
437
435
|
}
|
|
438
|
-
await installAddons(command, addons, path.resolve(functionPath));
|
|
439
436
|
await handleOnComplete({ command, onComplete });
|
|
440
437
|
log();
|
|
441
438
|
log(chalk.greenBright(`Function created!`));
|
|
442
439
|
}
|
|
443
440
|
};
|
|
444
441
|
const TEMPLATE_PERMISSIONS = 0o777;
|
|
445
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'addonName' implicitly has an 'any... Remove this comment to see the full error message
|
|
446
|
-
const createFunctionAddon = async function ({ addonName, addons, api, siteData, siteId }) {
|
|
447
|
-
try {
|
|
448
|
-
const addon = getCurrentAddon({ addons, addonName });
|
|
449
|
-
if (addon && addon.id) {
|
|
450
|
-
log(`The "${addonName} add-on" already exists for ${siteData.name}`);
|
|
451
|
-
return false;
|
|
452
|
-
}
|
|
453
|
-
await api.createServiceInstance({
|
|
454
|
-
siteId,
|
|
455
|
-
addon: addonName,
|
|
456
|
-
body: { config: {} },
|
|
457
|
-
});
|
|
458
|
-
log(`Add-on "${addonName}" created for ${siteData.name}`);
|
|
459
|
-
return true;
|
|
460
|
-
}
|
|
461
|
-
catch (error_) {
|
|
462
|
-
return logAndThrowError(error_.message);
|
|
463
|
-
}
|
|
464
|
-
};
|
|
465
442
|
/**
|
|
466
443
|
*
|
|
467
444
|
* @param {object} config
|
|
@@ -481,73 +458,6 @@ const handleOnComplete = async ({ command, onComplete }) => {
|
|
|
481
458
|
await onComplete.call(command);
|
|
482
459
|
}
|
|
483
460
|
};
|
|
484
|
-
/**
|
|
485
|
-
*
|
|
486
|
-
* @param {object} config
|
|
487
|
-
* @param {*} config.addonCreated
|
|
488
|
-
* @param {*} config.addonDidInstall
|
|
489
|
-
* @param {import('../base-command.js').default} config.command
|
|
490
|
-
* @param {string} config.fnPath
|
|
491
|
-
*/
|
|
492
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'addonCreated' implicitly has an '... Remove this comment to see the full error message
|
|
493
|
-
const handleAddonDidInstall = async ({ addonCreated, addonDidInstall, command, fnPath }) => {
|
|
494
|
-
const { config } = command.netlify;
|
|
495
|
-
if (!addonCreated || !addonDidInstall) {
|
|
496
|
-
return;
|
|
497
|
-
}
|
|
498
|
-
const confirmPostInstall = await confirm({
|
|
499
|
-
message: `This template has an optional setup script that runs after addon install. This can be helpful for first time users to try out templates. Run the script?`,
|
|
500
|
-
default: false,
|
|
501
|
-
});
|
|
502
|
-
if (!confirmPostInstall) {
|
|
503
|
-
return;
|
|
504
|
-
}
|
|
505
|
-
await injectEnvVariables({
|
|
506
|
-
devConfig: { ...config.dev },
|
|
507
|
-
env: command.netlify.cachedConfig.env,
|
|
508
|
-
site: command.netlify.site,
|
|
509
|
-
});
|
|
510
|
-
addonDidInstall(fnPath);
|
|
511
|
-
};
|
|
512
|
-
/**
|
|
513
|
-
*
|
|
514
|
-
* @param {import('../base-command.js').default} command
|
|
515
|
-
* @param {*} functionAddons
|
|
516
|
-
* @param {*} fnPath
|
|
517
|
-
* @returns
|
|
518
|
-
*/
|
|
519
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'command' implicitly has an 'any' type.
|
|
520
|
-
const installAddons = async function (command, functionAddons, fnPath) {
|
|
521
|
-
if (functionAddons.length === 0) {
|
|
522
|
-
return;
|
|
523
|
-
}
|
|
524
|
-
const { api, site } = command.netlify;
|
|
525
|
-
const siteId = site.id;
|
|
526
|
-
if (!siteId) {
|
|
527
|
-
log('No project id found, please run inside a project directory or `netlify link`');
|
|
528
|
-
return false;
|
|
529
|
-
}
|
|
530
|
-
log(`${NETLIFYDEVLOG} checking Netlify APIs...`);
|
|
531
|
-
const [siteData, siteAddons] = await Promise.all([getSiteData({ api, siteId }), getAddons({ api, siteId })]);
|
|
532
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'addonDidInstall' implicitly has a... Remove this comment to see the full error message
|
|
533
|
-
const arr = functionAddons.map(async ({ addonDidInstall, addonName }) => {
|
|
534
|
-
log(`${NETLIFYDEVLOG} installing addon: ${chalk.yellow.inverse(addonName)}`);
|
|
535
|
-
try {
|
|
536
|
-
const addonCreated = await createFunctionAddon({
|
|
537
|
-
api,
|
|
538
|
-
addons: siteAddons,
|
|
539
|
-
siteId,
|
|
540
|
-
addonName,
|
|
541
|
-
siteData,
|
|
542
|
-
});
|
|
543
|
-
await handleAddonDidInstall({ addonCreated, addonDidInstall, command, fnPath });
|
|
544
|
-
}
|
|
545
|
-
catch (error_) {
|
|
546
|
-
return logAndThrowError(`${NETLIFYDEVERR} Error installing addon: ${error_}`);
|
|
547
|
-
}
|
|
548
|
-
});
|
|
549
|
-
return Promise.all(arr);
|
|
550
|
-
};
|
|
551
461
|
/**
|
|
552
462
|
*
|
|
553
463
|
* @param {string} funcName
|
|
@@ -4,6 +4,8 @@ export const createInitCommand = (program) => program
|
|
|
4
4
|
.description('Configure continuous deployment for a new or existing project. To create a new project without continuous deployment, use `netlify sites:create`')
|
|
5
5
|
.option('-m, --manual', 'Manually configure a git remote for CI')
|
|
6
6
|
.option('--git-remote-name <name>', 'Name of Git remote to use. e.g. "origin"')
|
|
7
|
+
.option('--skip-agent-setup', 'Skip installing Netlify skills for AI coding agents into the project')
|
|
8
|
+
.option('--reset-context', 'Replace locally edited Netlify skills with the latest release, and migrate or delete edited copies under renamed or deprecated names')
|
|
7
9
|
.addHelpText('after', () => {
|
|
8
10
|
const docsUrl = 'https://docs.netlify.com/cli/get-started/';
|
|
9
11
|
return `
|
|
@@ -12,6 +14,9 @@ For more information about getting started with Netlify CLI, see ${terminalLink(
|
|
|
12
14
|
})
|
|
13
15
|
.action(async (options, command) => {
|
|
14
16
|
const { init } = await import('./init.js');
|
|
15
|
-
await init(options, command
|
|
17
|
+
await init(options, command, {
|
|
18
|
+
setupAgentSkills: !options.skipAgentSetup,
|
|
19
|
+
resetContext: Boolean(options.resetContext),
|
|
20
|
+
});
|
|
16
21
|
});
|
|
17
22
|
//# sourceMappingURL=index.js.map
|
|
@@ -6,7 +6,9 @@ type InitExitMessageCustomizer = (code: InitExitCode, defaultMessage: string) =>
|
|
|
6
6
|
type InitExtraOptions = {
|
|
7
7
|
customizeExitMessage?: InitExitMessageCustomizer | undefined;
|
|
8
8
|
exitAfterConfiguringRepo?: boolean | undefined;
|
|
9
|
+
setupAgentSkills?: boolean | undefined;
|
|
10
|
+
resetContext?: boolean | undefined;
|
|
9
11
|
};
|
|
10
|
-
export declare const init: (options: OptionValues, command: BaseCommand, { customizeExitMessage, exitAfterConfiguringRepo }?: InitExtraOptions) => Promise<SiteInfo>;
|
|
12
|
+
export declare const init: (options: OptionValues, command: BaseCommand, { customizeExitMessage, exitAfterConfiguringRepo, setupAgentSkills: shouldSetupAgentSkills, resetContext, }?: InitExtraOptions) => Promise<SiteInfo>;
|
|
11
13
|
export {};
|
|
12
14
|
//# sourceMappingURL=init.d.ts.map
|
|
@@ -7,6 +7,7 @@ import { configureRepo } from '../../utils/init/config.js';
|
|
|
7
7
|
import { track } from '../../utils/telemetry/index.js';
|
|
8
8
|
import { link } from '../link/link.js';
|
|
9
9
|
import { sitesCreate } from '../sites/sites-create.js';
|
|
10
|
+
import { setupAgentSkills } from '../../utils/init/agent-skills.js';
|
|
10
11
|
import { getBuildSettings, saveNetlifyToml } from '../../utils/init/utils.js';
|
|
11
12
|
import { LINKED_EXISTING_SITE_EXIT_CODE, LINKED_NEW_SITE_EXIT_CODE } from './constants.js';
|
|
12
13
|
const persistState = ({ siteInfo, state }) => {
|
|
@@ -147,14 +148,33 @@ const logExistingRepoSetupAndExit = ({ repoUrl, siteName, customizeExitMessage,
|
|
|
147
148
|
// TODO add support for changing GitHub repo in site:config command
|
|
148
149
|
exit();
|
|
149
150
|
};
|
|
150
|
-
|
|
151
|
-
|
|
151
|
+
const installAgentSkills = async (command, reset) => {
|
|
152
|
+
log();
|
|
153
|
+
const result = await setupAgentSkills({ workingDir: command.netlify.repositoryRoot, reset });
|
|
154
|
+
await track('sites_agentSkillsSetup', {
|
|
155
|
+
installed: result.installed,
|
|
156
|
+
directories: result.directories,
|
|
157
|
+
skillsVersion: result.skillsVersion,
|
|
158
|
+
resetContext: reset,
|
|
159
|
+
...result.summary,
|
|
160
|
+
});
|
|
161
|
+
};
|
|
162
|
+
export const init = async (options, command, { customizeExitMessage, exitAfterConfiguringRepo = false, setupAgentSkills: shouldSetupAgentSkills = false, resetContext = false, } = {}) => {
|
|
163
|
+
command.setAnalyticsPayload({
|
|
164
|
+
manual: options.manual,
|
|
165
|
+
force: options.force,
|
|
166
|
+
skipAgentSetup: options.skipAgentSetup,
|
|
167
|
+
resetContext: options.resetContext,
|
|
168
|
+
});
|
|
152
169
|
const { repositoryRoot, state } = command.netlify;
|
|
153
170
|
const { siteInfo: existingSiteInfo } = command.netlify;
|
|
154
171
|
// Check logged in status
|
|
155
172
|
await command.authenticate();
|
|
156
173
|
// Add .netlify to .gitignore file
|
|
157
174
|
await ensureNetlifyIgnore(repositoryRoot);
|
|
175
|
+
if (shouldSetupAgentSkills) {
|
|
176
|
+
await installAgentSkills(command, resetContext);
|
|
177
|
+
}
|
|
158
178
|
const repoUrl = getRepoUrl(existingSiteInfo);
|
|
159
179
|
if (repoUrl && !options.force) {
|
|
160
180
|
logExistingAndExit({ siteInfo: existingSiteInfo });
|
|
@@ -33,7 +33,7 @@ export const serve = async (options, command) => {
|
|
|
33
33
|
log(`${NETLIFYDEVLOG} Injecting environment variable values for ${chalk.yellow('all scopes')}`);
|
|
34
34
|
}
|
|
35
35
|
env = await getDotEnvVariables({ devConfig, env, site });
|
|
36
|
-
const { accountId,
|
|
36
|
+
const { accountId, capabilities, siteUrl, timeouts } = await getSiteInformation({
|
|
37
37
|
// inherited from base command --offline
|
|
38
38
|
offline: options.offline,
|
|
39
39
|
api,
|
|
@@ -145,7 +145,6 @@ export const serve = async (options, command) => {
|
|
|
145
145
|
};
|
|
146
146
|
const inspectSettings = generateInspectSettings(options.edgeInspect, options.edgeInspectBrk);
|
|
147
147
|
const url = await startProxyServer({
|
|
148
|
-
addonsUrls,
|
|
149
148
|
blobsContext: runtimeBlobsContext,
|
|
150
149
|
command,
|
|
151
150
|
config: mergedConfig,
|
|
@@ -20,7 +20,7 @@ export const sitesList = async (options, command) => {
|
|
|
20
20
|
ssl_url: site.ssl_url,
|
|
21
21
|
account_name: site.account_name,
|
|
22
22
|
};
|
|
23
|
-
if (site.build_settings
|
|
23
|
+
if (site.build_settings?.repo_url) {
|
|
24
24
|
siteInfo.repo_url = site.build_settings.repo_url;
|
|
25
25
|
}
|
|
26
26
|
return siteInfo;
|
|
@@ -13,7 +13,7 @@ export const unlink = async (_options, command) => {
|
|
|
13
13
|
await track('sites_unlinked', {
|
|
14
14
|
siteId: siteData.id || siteId,
|
|
15
15
|
});
|
|
16
|
-
if (site
|
|
16
|
+
if (site?.configPath) {
|
|
17
17
|
log(`Unlinked ${site.configPath} from ${siteData ? siteData.name : siteId}`);
|
|
18
18
|
}
|
|
19
19
|
else {
|
|
@@ -235,7 +235,6 @@ export class EdgeFunctionsRegistryImpl {
|
|
|
235
235
|
Object.entries(envConfig).forEach(([key, variable]) => {
|
|
236
236
|
if (variable.sources.includes('ui') ||
|
|
237
237
|
variable.sources.includes('account') ||
|
|
238
|
-
variable.sources.includes('addons') ||
|
|
239
238
|
variable.sources.includes('internal') ||
|
|
240
239
|
variable.sources.some((source) => source.startsWith('.env'))) {
|
|
241
240
|
env[key] = variable.value;
|
package/dist/lib/exec-fetcher.js
CHANGED
|
@@ -105,7 +105,7 @@ export const shouldFetchLatestVersion = async ({ binPath, execArgs, execName, la
|
|
|
105
105
|
if (!stdout) {
|
|
106
106
|
return false;
|
|
107
107
|
}
|
|
108
|
-
const match =
|
|
108
|
+
const match = new RegExp(pattern).exec(stdout);
|
|
109
109
|
if (!match) {
|
|
110
110
|
return false;
|
|
111
111
|
}
|
|
@@ -46,7 +46,8 @@ export const createFormSubmissionHandler = function ({ functionsRegistry, siteUr
|
|
|
46
46
|
}
|
|
47
47
|
const originalUrl = new URL(req.url, 'http://localhost');
|
|
48
48
|
req.url = `/.netlify/functions/${handlerName}${originalUrl.search}`;
|
|
49
|
-
|
|
49
|
+
// A missing header parses to an empty type and takes the unsupported-type branch below.
|
|
50
|
+
const ct = parseContentType(req.headers['content-type'] ?? '');
|
|
50
51
|
let fields = {};
|
|
51
52
|
let files = {};
|
|
52
53
|
if (ct.type.endsWith('/x-www-form-urlencoded')) {
|
|
@@ -73,7 +73,7 @@ export const parseContextFile = (contents) => {
|
|
|
73
73
|
const result = {
|
|
74
74
|
contents,
|
|
75
75
|
};
|
|
76
|
-
const providerContext =
|
|
76
|
+
const providerContext = PROVIDER_CONTEXT_REGEX.exec(contents);
|
|
77
77
|
if (providerContext) {
|
|
78
78
|
const [, attributes, innerContents] = providerContext;
|
|
79
79
|
result.innerContents = innerContents;
|
|
@@ -90,7 +90,7 @@ export const parseContextFile = (contents) => {
|
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
|
-
const contextOverrides =
|
|
93
|
+
const contextOverrides = PROVIDER_CONTEXT_OVERRIDES_REGEX.exec(contents);
|
|
94
94
|
if (contextOverrides) {
|
|
95
95
|
const [overrideContents, , innerContents] = contextOverrides;
|
|
96
96
|
result.overrides = {
|
package/dist/utils/dev.d.ts
CHANGED
package/dist/utils/dev.js
CHANGED
|
@@ -10,10 +10,6 @@ const ENV_VAR_SOURCES = {
|
|
|
10
10
|
name: 'shared',
|
|
11
11
|
printFn: chalk.magenta,
|
|
12
12
|
},
|
|
13
|
-
addons: {
|
|
14
|
-
name: 'addon',
|
|
15
|
-
printFn: chalk.yellow,
|
|
16
|
-
},
|
|
17
13
|
configFile: {
|
|
18
14
|
name: 'netlify.toml file',
|
|
19
15
|
printFn: chalk.green,
|
|
@@ -47,25 +43,6 @@ const getAccounts = async ({ api }) => {
|
|
|
47
43
|
return logAndThrowError(`Failed retrieving user account: ${error_.message}. ${ERROR_CALL_TO_ACTION}`);
|
|
48
44
|
}
|
|
49
45
|
};
|
|
50
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message
|
|
51
|
-
const getAddons = async ({ api, site }) => {
|
|
52
|
-
try {
|
|
53
|
-
const addons = await api.listServiceInstancesForSite({ siteId: site.id });
|
|
54
|
-
return addons;
|
|
55
|
-
}
|
|
56
|
-
catch (error_) {
|
|
57
|
-
return logAndThrowError(`Failed retrieving addons for site ${chalk.yellow(site.id)}: ${error_.message}. ${ERROR_CALL_TO_ACTION}`);
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'addons' implicitly has an 'any' t... Remove this comment to see the full error message
|
|
61
|
-
const getAddonsInformation = ({ addons, siteInfo }) => {
|
|
62
|
-
const urls = Object.fromEntries(
|
|
63
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'addon' implicitly has an 'any' type.
|
|
64
|
-
addons.map((addon) => [addon.service_slug, `${siteInfo.ssl_url}${addon.service_path}`]));
|
|
65
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'addon' implicitly has an 'any' type.
|
|
66
|
-
const env = Object.assign({}, ...addons.map((addon) => addon.env));
|
|
67
|
-
return { urls, env };
|
|
68
|
-
};
|
|
69
46
|
const getSiteAccount = ({ accounts, siteInfo }) => {
|
|
70
47
|
const siteAccount = accounts.find((account) => account.slug === siteInfo.account_slug);
|
|
71
48
|
if (!siteAccount) {
|
|
@@ -81,11 +58,9 @@ const BACKGROUND_FUNCTION_TIMEOUT = 900;
|
|
|
81
58
|
export const getSiteInformation = async ({ api, offline, site, siteInfo, }) => {
|
|
82
59
|
if (site.id && !offline) {
|
|
83
60
|
validateSiteInfo({ site, siteInfo });
|
|
84
|
-
const
|
|
85
|
-
const { urls: addonsUrls } = getAddonsInformation({ siteInfo, addons });
|
|
61
|
+
const accounts = await getAccounts({ api });
|
|
86
62
|
const account = getSiteAccount({ siteInfo, accounts });
|
|
87
63
|
return {
|
|
88
|
-
addonsUrls,
|
|
89
64
|
siteUrl: siteInfo.ssl_url,
|
|
90
65
|
accountId: account?.id,
|
|
91
66
|
capabilities: {
|
|
@@ -100,7 +75,6 @@ export const getSiteInformation = async ({ api, offline, site, siteInfo, }) => {
|
|
|
100
75
|
}
|
|
101
76
|
// best defaults we can have without retrieving site information
|
|
102
77
|
return {
|
|
103
|
-
addonsUrls: {},
|
|
104
78
|
siteUrl: '',
|
|
105
79
|
capabilities: {
|
|
106
80
|
aiGatewayDisabled: false,
|
package/dist/utils/env/index.js
CHANGED
|
@@ -180,7 +180,6 @@ export const getEnvelopeEnv = async ({ api, context = 'dev', env, key = '', raw
|
|
|
180
180
|
}
|
|
181
181
|
const generalEnv = filterEnvBySource(env, 'general');
|
|
182
182
|
const internalEnv = filterEnvBySource(env, 'internal');
|
|
183
|
-
const addonsEnv = filterEnvBySource(env, 'addons');
|
|
184
183
|
const configFileEnv = filterEnvBySource(env, 'configFile');
|
|
185
184
|
// filter out configFile env vars if a non-configFile scope is passed
|
|
186
185
|
const includeConfigEnvVars = /any|builds|post[-_]processing/.test(scope);
|
|
@@ -188,7 +187,6 @@ export const getEnvelopeEnv = async ({ api, context = 'dev', env, key = '', raw
|
|
|
188
187
|
return {
|
|
189
188
|
...generalEnv,
|
|
190
189
|
...accountEnv,
|
|
191
|
-
...(includeConfigEnvVars ? addonsEnv : {}),
|
|
192
190
|
...siteEnv,
|
|
193
191
|
...(includeConfigEnvVars ? configFileEnv : {}),
|
|
194
192
|
...internalEnv,
|
|
@@ -249,7 +247,7 @@ export const translateFromEnvelopeToMongo = (envVars = [], context = 'dev') => e
|
|
|
249
247
|
.sort((a, b) => (a.key.toLowerCase() < b.key.toLowerCase() ? -1 : 1))
|
|
250
248
|
.reduce((acc, cur) => {
|
|
251
249
|
const envVar = cur.values.find((val) => [context, 'all'].includes((val.context_parameter ?? '') || val.context));
|
|
252
|
-
if (envVar
|
|
250
|
+
if (envVar?.value) {
|
|
253
251
|
return {
|
|
254
252
|
...acc,
|
|
255
253
|
[cur.key]: envVar.value,
|
|
@@ -11,7 +11,7 @@ const getRepoData = async ({ remoteName, workingDir, }) => {
|
|
|
11
11
|
util.promisify(gitconfiglocal)(workingDir),
|
|
12
12
|
findUp('.git', { cwd: workingDir, type: 'directory' }),
|
|
13
13
|
]);
|
|
14
|
-
if (!gitDirectory || !gitConfig
|
|
14
|
+
if (!gitDirectory || !gitConfig?.remote || Object.keys(gitConfig.remote).length === 0) {
|
|
15
15
|
throw new Error('No Git remote found');
|
|
16
16
|
}
|
|
17
17
|
const baseGitPath = dirname(gitDirectory);
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
export declare const DEFAULT_SKILLS_HOST = "https://netlify-agent-skills.netlify.app";
|
|
2
|
+
export declare const SKILLS_HOST_ENV = "NETLIFY_SKILLS_HOST";
|
|
3
|
+
export declare const DEFAULT_SKILLS_DIRECTORY: string;
|
|
4
|
+
export interface SkillHistoryEntry {
|
|
5
|
+
version: string | null;
|
|
6
|
+
name?: string;
|
|
7
|
+
tree_hash: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ManifestSkill {
|
|
10
|
+
name: string;
|
|
11
|
+
status: 'active' | 'deprecated';
|
|
12
|
+
version: string | null;
|
|
13
|
+
prior_names?: string[];
|
|
14
|
+
description?: string;
|
|
15
|
+
tree_hash: string | null;
|
|
16
|
+
files?: Record<string, string>;
|
|
17
|
+
executable?: string[];
|
|
18
|
+
history?: SkillHistoryEntry[];
|
|
19
|
+
deprecated?: {
|
|
20
|
+
since: string;
|
|
21
|
+
replaced_by?: string;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export interface SkillsManifest {
|
|
25
|
+
schema_version: number;
|
|
26
|
+
version: string;
|
|
27
|
+
skills: ManifestSkill[];
|
|
28
|
+
}
|
|
29
|
+
export type SkillRecord = {
|
|
30
|
+
name: string;
|
|
31
|
+
status: 'current';
|
|
32
|
+
version: string | null;
|
|
33
|
+
} | {
|
|
34
|
+
name: string;
|
|
35
|
+
status: 'stale';
|
|
36
|
+
version: string | null;
|
|
37
|
+
have: string | null;
|
|
38
|
+
} | {
|
|
39
|
+
name: string;
|
|
40
|
+
status: 'modified';
|
|
41
|
+
version: string | null;
|
|
42
|
+
} | {
|
|
43
|
+
name: string;
|
|
44
|
+
status: 'renamed';
|
|
45
|
+
currentName: string;
|
|
46
|
+
modified: boolean;
|
|
47
|
+
} | {
|
|
48
|
+
name: string;
|
|
49
|
+
status: 'deprecated';
|
|
50
|
+
replacedBy: string | null;
|
|
51
|
+
modified: boolean;
|
|
52
|
+
} | {
|
|
53
|
+
name: string;
|
|
54
|
+
status: 'unknown';
|
|
55
|
+
};
|
|
56
|
+
export interface SkillsClassification {
|
|
57
|
+
skills: SkillRecord[];
|
|
58
|
+
missing: string[];
|
|
59
|
+
}
|
|
60
|
+
export type SkillAction = 'current' | 'added' | 'updated' | 'reset' | 'renamed' | 'removed' | 'kept' | 'ignored' | 'failed';
|
|
61
|
+
export interface SkillActionRecord {
|
|
62
|
+
name: string;
|
|
63
|
+
action: SkillAction;
|
|
64
|
+
detail?: string;
|
|
65
|
+
}
|
|
66
|
+
export interface SkillsSyncResult {
|
|
67
|
+
directory: string;
|
|
68
|
+
actions: SkillActionRecord[];
|
|
69
|
+
}
|
|
70
|
+
export declare const resolveSkillsHost: (env?: NodeJS.ProcessEnv) => string;
|
|
71
|
+
export declare const fetchSkillsManifest: (host: string) => Promise<SkillsManifest>;
|
|
72
|
+
export declare const hashSkillTree: (dir: string, declaredExecutable?: Set<string>) => Promise<string>;
|
|
73
|
+
export declare const classifySkillsDirectory: (root: string, manifest: SkillsManifest) => Promise<SkillsClassification>;
|
|
74
|
+
export declare const installSkill: (host: string, dest: string, skill: ManifestSkill, { force }?: {
|
|
75
|
+
force?: boolean;
|
|
76
|
+
}) => Promise<number>;
|
|
77
|
+
export declare const syncSkills: ({ host, directory, manifest, reset, }: {
|
|
78
|
+
host: string;
|
|
79
|
+
directory: string;
|
|
80
|
+
manifest: SkillsManifest;
|
|
81
|
+
reset?: boolean;
|
|
82
|
+
}) => Promise<SkillsSyncResult>;
|
|
83
|
+
export declare const resolveSkillsDirectories: (workingDir: string, env?: NodeJS.ProcessEnv) => Promise<string[]>;
|
|
84
|
+
export interface AgentSkillsSetupSummary {
|
|
85
|
+
installed: boolean;
|
|
86
|
+
directories: string[];
|
|
87
|
+
skillsVersion?: string;
|
|
88
|
+
summary: Record<SkillAction, number>;
|
|
89
|
+
error?: string;
|
|
90
|
+
}
|
|
91
|
+
export declare const setupAgentSkills: ({ workingDir, env, reset, }: {
|
|
92
|
+
workingDir: string;
|
|
93
|
+
env?: NodeJS.ProcessEnv;
|
|
94
|
+
reset?: boolean;
|
|
95
|
+
}) => Promise<AgentSkillsSetupSummary>;
|
|
96
|
+
//# sourceMappingURL=agent-skills.d.ts.map
|