netlify-cli 18.0.4 → 19.0.0-pre.1579ae4
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.d.ts.map +1 -1
- package/dist/commands/base-command.js +2 -13
- package/dist/commands/blobs/blobs.js +2 -2
- package/dist/commands/build/build.d.ts +4 -11
- package/dist/commands/build/build.d.ts.map +1 -1
- package/dist/commands/build/build.js +1 -7
- package/dist/commands/build/index.js +1 -1
- package/dist/commands/completion/completion.d.ts +4 -4
- package/dist/commands/completion/completion.d.ts.map +1 -1
- package/dist/commands/completion/completion.js +4 -5
- package/dist/commands/deploy/index.d.ts.map +1 -1
- package/dist/commands/deploy/index.js +5 -6
- package/dist/commands/dev/dev.d.ts.map +1 -1
- package/dist/commands/dev/dev.js +1 -15
- package/dist/commands/env/env-list.d.ts +2 -2
- package/dist/commands/env/env-list.d.ts.map +1 -1
- package/dist/commands/env/env.d.ts.map +1 -1
- package/dist/commands/env/env.js +5 -4
- package/dist/commands/functions/functions.d.ts +1 -1
- package/dist/commands/functions/functions.d.ts.map +1 -1
- package/dist/commands/functions/functions.js +4 -2
- package/dist/commands/init/index.d.ts.map +1 -1
- package/dist/commands/init/index.js +0 -2
- package/dist/commands/link/index.d.ts.map +1 -1
- package/dist/commands/link/index.js +0 -2
- package/dist/commands/main.d.ts.map +1 -1
- package/dist/commands/main.js +0 -3
- package/dist/commands/recipes/recipes.d.ts +1 -2
- package/dist/commands/recipes/recipes.d.ts.map +1 -1
- package/dist/commands/serve/index.d.ts.map +1 -1
- package/dist/commands/serve/index.js +1 -4
- package/dist/commands/status/index.d.ts +1 -1
- package/dist/commands/status/index.d.ts.map +1 -1
- package/dist/commands/status/index.js +2 -1
- package/dist/lib/build.d.ts +36 -67
- package/dist/lib/build.d.ts.map +1 -1
- package/dist/lib/build.js +6 -41
- package/dist/lib/completion/script.js +3 -13
- package/dist/lib/functions/form-submissions-handler.d.ts.map +1 -1
- package/dist/lib/functions/form-submissions-handler.js +0 -2
- package/dist/lib/functions/runtimes/js/builders/netlify-lambda.d.ts.map +1 -1
- package/dist/lib/functions/runtimes/js/builders/netlify-lambda.js +8 -7
- package/dist/lib/functions/runtimes/js/builders/zisi.d.ts.map +1 -1
- package/dist/lib/functions/runtimes/js/builders/zisi.js +0 -1
- package/dist/lib/functions/runtimes/js/worker.js +0 -1
- package/dist/recipes/ai-context/context.d.ts +33 -0
- package/dist/recipes/ai-context/context.d.ts.map +1 -0
- package/dist/recipes/ai-context/context.js +100 -0
- package/dist/recipes/ai-context/index.d.ts +4 -0
- package/dist/recipes/ai-context/index.d.ts.map +1 -0
- package/dist/recipes/ai-context/index.js +85 -0
- package/dist/recipes/vscode/settings.d.ts.map +1 -1
- package/dist/recipes/vscode/settings.js +5 -4
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/command-helpers.d.ts +2 -2
- package/dist/utils/command-helpers.js +1 -1
- package/dist/utils/deploy/hash-files.js +3 -3
- package/dist/utils/deploy/hash-fns.d.ts.map +1 -1
- package/dist/utils/deploy/hash-fns.js +3 -2
- package/dist/utils/deploy/hasher-segments.d.ts +3 -3
- package/dist/utils/deploy/hasher-segments.d.ts.map +1 -1
- package/dist/utils/deploy/hasher-segments.js +2 -9
- package/dist/utils/get-global-config.d.ts.map +1 -1
- package/dist/utils/get-global-config.js +2 -2
- package/dist/utils/get-repo-data.d.ts +4 -4
- package/dist/utils/get-repo-data.d.ts.map +1 -1
- package/dist/utils/get-repo-data.js +7 -6
- package/dist/utils/open-browser.d.ts.map +1 -1
- package/dist/utils/open-browser.js +1 -2
- package/dist/utils/proxy.d.ts.map +1 -1
- package/dist/utils/proxy.js +3 -5
- package/dist/utils/rules-proxy.d.ts.map +1 -1
- package/dist/utils/rules-proxy.js +0 -1
- package/dist/utils/run-build.d.ts.map +1 -1
- package/dist/utils/run-build.js +7 -2
- package/dist/utils/sites/create-template.d.ts.map +1 -1
- package/dist/utils/sites/create-template.js +2 -3
- package/dist/utils/state-config.d.ts.map +1 -1
- package/dist/utils/state-config.js +0 -1
- package/dist/utils/types.d.ts +7 -0
- package/dist/utils/types.d.ts.map +1 -1
- package/functions-templates/javascript/scheduled-function/package.json +1 -1
- package/functions-templates/typescript/hello-world/package-lock.json +15 -46
- package/functions-templates/typescript/hello-world/package.json +1 -1
- package/functions-templates/typescript/scheduled-function/package.json +1 -1
- package/npm-shrinkwrap.json +650 -742
- package/package.json +16 -18
- package/dist/commands/integration/deploy.d.ts +0 -8
- package/dist/commands/integration/deploy.d.ts.map +0 -1
- package/dist/commands/integration/deploy.js +0 -353
- package/dist/commands/integration/index.d.ts +0 -4
- package/dist/commands/integration/index.d.ts.map +0 -1
- package/dist/commands/integration/index.js +0 -26
package/dist/lib/build.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/lib/build.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/lib/build.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,EAAc,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAGpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAG7C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAK7D,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,oBAAoB,CAAA;IACzB,QAAQ,EAAE;QACR,EAAE,CAAC,EAAE,MAAM,CAAA;QACX,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC,CAAA;KAC3D,CAAA;IAED,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACrB;AAED,UAAU,aAAa;IAErB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACrB;AAGD,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG;IACtD,YAAY,EAAE,YAAY,CAAA;IAC1B,aAAa,EAAE,aAAa,CAAA;IAE5B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,yBAAyB,EAAE,MAAM,CAAA;CAClC,CAAA;AAED,UAAU,aAAa;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACxC,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,KAAK,kBAAkB,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CACvE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KACnB,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAA;AAU3C,eAAO,MAAM,eAAe,kJAQzB;IACD,YAAY,EAAE,YAAY,CAAA;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,aAAa,CAAC,EAAE,kBAAkB,CAAC,WAAW,CAAC,CAAA;IAC/C,OAAO,EAAE,YAAY,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,IAAI,GAAG,MAAM,CAAA;CACtB,KAAG,OAAO,CAAC,WAAW,CAiDtB,CAAA;AAED,eAAO,MAAM,QAAQ,YAAmB,WAAW;;;;EAgBlD,CAAA"}
|
package/dist/lib/build.js
CHANGED
|
@@ -6,43 +6,12 @@ import tomlify from 'tomlify-j0.4';
|
|
|
6
6
|
import { getFeatureFlagsFromSiteInfo } from '../utils/feature-flags.js';
|
|
7
7
|
import { getBootstrapURL } from './edge-functions/bootstrap.js';
|
|
8
8
|
import { featureFlags as edgeFunctionsFeatureFlags } from './edge-functions/consts.js';
|
|
9
|
-
/**
|
|
10
|
-
* The buildConfig + a missing cachedConfig
|
|
11
|
-
* @typedef BuildConfig
|
|
12
|
-
* @type {Parameters<import('@netlify/build/src/core/main.js')>[0] & {cachedConfig: any}}
|
|
13
|
-
*/
|
|
14
9
|
// We have already resolved the configuration using `@netlify/config`
|
|
15
10
|
// This is stored as `netlify.cachedConfig` and can be passed to
|
|
16
11
|
// `@netlify/build --cachedConfig`.
|
|
17
|
-
|
|
18
|
-
*
|
|
19
|
-
* @param {object} config
|
|
20
|
-
* @param {*} config.cachedConfig
|
|
21
|
-
* @param {string} [config.packagePath]
|
|
22
|
-
* @param {string} config.currentDir
|
|
23
|
-
* @param {string} config.token
|
|
24
|
-
* @param {import('commander').OptionValues} config.options
|
|
25
|
-
* @param {*} config.deployHandler
|
|
26
|
-
* @returns {BuildConfig}
|
|
27
|
-
*/
|
|
28
|
-
export const getBuildOptions = async ({
|
|
29
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'cachedConfig' implicitly has an '... Remove this comment to see the full error message
|
|
30
|
-
cachedConfig,
|
|
31
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'currentDir' implicitly has an 'an... Remove this comment to see the full error message
|
|
32
|
-
currentDir,
|
|
33
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'defaultConfig' implicitly has an '... Remove this comment to see the full error message
|
|
34
|
-
defaultConfig,
|
|
35
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'deployHandler' implicitly has an ... Remove this comment to see the full error message
|
|
36
|
-
deployHandler,
|
|
37
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'context' implicitly has an 'any' ... Remove this comment to see the full error message
|
|
38
|
-
options: { context, cwd, debug, dry, json, offline, silent },
|
|
39
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'packagePath' implicitly has an 'a... Remove this comment to see the full error message
|
|
40
|
-
packagePath,
|
|
41
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'token' implicitly has an 'any' ty... Remove this comment to see the full error message
|
|
42
|
-
token, }) => {
|
|
12
|
+
export const getBuildOptions = async ({ cachedConfig, currentDir, defaultConfig, deployHandler, options: { context, cwd, debug, dry, json, offline, silent }, packagePath, token, }) => {
|
|
43
13
|
const eventHandlers = {
|
|
44
14
|
onEnd: {
|
|
45
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'netlifyConfig' implicitly has an ... Remove this comment to see the full error message
|
|
46
15
|
handler: ({ netlifyConfig }) => {
|
|
47
16
|
const string = tomlify.toToml(netlifyConfig);
|
|
48
17
|
if (!fs.existsSync(`${currentDir}/.netlify`)) {
|
|
@@ -55,7 +24,6 @@ token, }) => {
|
|
|
55
24
|
},
|
|
56
25
|
};
|
|
57
26
|
if (deployHandler) {
|
|
58
|
-
// @ts-expect-error TS(2339) FIXME: Property 'onPostBuild' does not exist on type '{ o... Remove this comment to see the full error message
|
|
59
27
|
eventHandlers.onPostBuild = {
|
|
60
28
|
handler: deployHandler,
|
|
61
29
|
description: 'Deploy Site',
|
|
@@ -63,11 +31,11 @@ token, }) => {
|
|
|
63
31
|
}
|
|
64
32
|
return {
|
|
65
33
|
cachedConfig,
|
|
66
|
-
defaultConfig,
|
|
34
|
+
defaultConfig: defaultConfig ?? {},
|
|
67
35
|
siteId: cachedConfig.siteInfo.id,
|
|
68
36
|
accountId: cachedConfig.siteInfo.account_id,
|
|
69
37
|
packagePath,
|
|
70
|
-
token,
|
|
38
|
+
token: token ?? undefined,
|
|
71
39
|
dry,
|
|
72
40
|
debug,
|
|
73
41
|
context,
|
|
@@ -82,16 +50,11 @@ token, }) => {
|
|
|
82
50
|
...getFeatureFlagsFromSiteInfo(cachedConfig.siteInfo),
|
|
83
51
|
functionsBundlingManifest: true,
|
|
84
52
|
},
|
|
53
|
+
// @ts-expect-error(serhalp) -- TODO(serhalp) Upstream the type fixes above into @netlify/build
|
|
85
54
|
eventHandlers,
|
|
86
55
|
edgeFunctionsBootstrapURL: await getBootstrapURL(),
|
|
87
56
|
};
|
|
88
57
|
};
|
|
89
|
-
/**
|
|
90
|
-
* run the build command
|
|
91
|
-
* @param {BuildConfig} options
|
|
92
|
-
* @returns
|
|
93
|
-
*/
|
|
94
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type.
|
|
95
58
|
export const runBuild = async (options) => {
|
|
96
59
|
// If netlify NETLIFY_API_URL is set we need to pass this information to @netlify/build
|
|
97
60
|
// TODO don't use testOpts, but add real properties to do this.
|
|
@@ -101,6 +64,8 @@ export const runBuild = async (options) => {
|
|
|
101
64
|
scheme: apiUrl.protocol.slice(0, -1),
|
|
102
65
|
host: apiUrl.host,
|
|
103
66
|
};
|
|
67
|
+
// @ts-expect-error(serhalp) -- I don't know what's going on here and I can't convince myself it even works as
|
|
68
|
+
// intended. TODO(serhalp) Investigate and fix types.
|
|
104
69
|
options = { ...options, testOpts };
|
|
105
70
|
}
|
|
106
71
|
const { configMutations, netlifyConfig: newConfig, severityCode: exitCode } = await build(options);
|
|
@@ -4,25 +4,15 @@
|
|
|
4
4
|
// if this file is renamed or moved then it needs to be adapted there
|
|
5
5
|
import { existsSync, readFileSync } from 'fs';
|
|
6
6
|
import process from 'process';
|
|
7
|
-
|
|
8
|
-
import { log, parseEnv } from 'tabtab';
|
|
7
|
+
import { getShellFromEnv, log, parseEnv } from '@pnpm/tabtab';
|
|
9
8
|
import { AUTOCOMPLETION_FILE } from './constants.js';
|
|
10
9
|
import getAutocompletion from './get-autocompletion.js';
|
|
11
|
-
/**
|
|
12
|
-
* @typedef CompletionItem
|
|
13
|
-
* @type import('tabtab').CompletionItem
|
|
14
|
-
*/
|
|
15
|
-
/**
|
|
16
|
-
*
|
|
17
|
-
* @param {import('tabtab').TabtabEnv} env
|
|
18
|
-
* @param {Record<string, CompletionItem & {options: CompletionItem[]}>} program
|
|
19
|
-
* @returns {CompletionItem[]|void}
|
|
20
|
-
*/
|
|
21
10
|
const env = parseEnv(process.env);
|
|
11
|
+
const shell = getShellFromEnv(process.env);
|
|
22
12
|
if (existsSync(AUTOCOMPLETION_FILE)) {
|
|
23
13
|
const program = JSON.parse(readFileSync(AUTOCOMPLETION_FILE, 'utf-8'));
|
|
24
14
|
const autocomplete = getAutocompletion(env, program);
|
|
25
15
|
if (autocomplete && autocomplete.length !== 0) {
|
|
26
|
-
log(autocomplete);
|
|
16
|
+
log(autocomplete, shell);
|
|
27
17
|
}
|
|
28
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-submissions-handler.d.ts","sourceRoot":"","sources":["../../../src/lib/functions/form-submissions-handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"form-submissions-handler.d.ts","sourceRoot":"","sources":["../../../src/lib/functions/form-submissions-handler.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAS7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAEtD,eAAO,MAAM,cAAc,uCAGxB;IACD,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB,uBAmBA,CAAA;AAED,eAAO,MAAM,2BAA2B,oCAGrC;IACD,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,OAAO,EAAE,MAAM,CAAA;CAChB,KAAG,cAwIH,CAAA"}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { Readable } from 'stream';
|
|
2
|
-
// @ts-expect-error TS(7016) FIXME: Could not find a declaration file for module 'cont... Remove this comment to see the full error message
|
|
3
2
|
import { parse as parseContentType } from 'content-type';
|
|
4
|
-
// @ts-expect-error TS(7016) FIXME: Could not find a declaration file for module 'mult... Remove this comment to see the full error message
|
|
5
3
|
import multiparty from 'multiparty';
|
|
6
4
|
import getRawBody from 'raw-body';
|
|
7
5
|
import { warn } from '../../utils/command-helpers.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"netlify-lambda.d.ts","sourceRoot":"","sources":["../../../../../../src/lib/functions/runtimes/js/builders/netlify-lambda.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,mBAAmB;;;;;;;;
|
|
1
|
+
{"version":3,"file":"netlify-lambda.d.ts","sourceRoot":"","sources":["../../../../../../src/lib/functions/runtimes/js/builders/netlify-lambda.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,mBAAmB;;;;;;;;EAuD/B,CAAA;AAED,wBAA8B,OAAO;;;;;;;;GASpC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFile } from 'fs/promises';
|
|
2
2
|
import { resolve } from 'path';
|
|
3
|
-
import {
|
|
3
|
+
import { Command } from 'commander';
|
|
4
4
|
import execa from '../../../../../utils/execa.js';
|
|
5
5
|
import { fileExistsAsync } from '../../../../fs.js';
|
|
6
6
|
import { memoizedBuild } from '../../../memoized-build.js';
|
|
@@ -10,17 +10,18 @@ export const detectNetlifyLambda = async function ({ packageJson } = {}) {
|
|
|
10
10
|
if (!((dependencies && dependencies['netlify-lambda']) || (devDependencies && devDependencies['netlify-lambda']))) {
|
|
11
11
|
return false;
|
|
12
12
|
}
|
|
13
|
+
const program = new Command()
|
|
14
|
+
.option('-s, --static')
|
|
15
|
+
.option('-c, --config [file]')
|
|
16
|
+
.option('-p, --port [number]')
|
|
17
|
+
.option('-b, --babelrc [file]')
|
|
18
|
+
.option('-t, --timeout [delay]');
|
|
19
|
+
program.allowExcessArguments();
|
|
13
20
|
// @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'.
|
|
14
21
|
const matchingScripts = Object.entries(scripts).filter(([, script]) => script.match(/netlify-lambda\s+build/));
|
|
15
22
|
for (const [key, script] of matchingScripts) {
|
|
16
23
|
// E.g. ["netlify-lambda", "build", "functions/folder"]
|
|
17
24
|
// these are all valid options for netlify-lambda
|
|
18
|
-
program
|
|
19
|
-
.option('-s, --static')
|
|
20
|
-
.option('-c, --config [file]')
|
|
21
|
-
.option('-p, --port [number]')
|
|
22
|
-
.option('-b, --babelrc [file]')
|
|
23
|
-
.option('-t, --timeout [delay]');
|
|
24
25
|
program.parse(script.split(' ') ?? []);
|
|
25
26
|
// We are not interested in 'netlify-lambda' and 'build' commands
|
|
26
27
|
const functionDirectories = program.args.filter((arg) => !['netlify-lambda', 'build'].includes(arg));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zisi.d.ts","sourceRoot":"","sources":["../../../../../../src/lib/functions/runtimes/js/builders/zisi.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"zisi.d.ts","sourceRoot":"","sources":["../../../../../../src/lib/functions/runtimes/js/builders/zisi.ts"],"names":[],"mappings":"AA+GA;;;;;GAKG;AAEH,eAAO,MAAM,wBAAwB;;;;+EAMjC,CAAA;AAoCJ;;;;;;;;;GASG;AAEH,wBAA8B,OAAO,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE;;;;;;;CAAA;;;;;;;;;;;;;;;;GAoDlG"}
|
|
@@ -4,7 +4,6 @@ import path from 'path';
|
|
|
4
4
|
import { zipFunction, listFunction } from '@netlify/zip-it-and-ship-it';
|
|
5
5
|
import decache from 'decache';
|
|
6
6
|
import { readPackageUp } from 'read-package-up';
|
|
7
|
-
// @ts-expect-error TS(7016) FIXME: Could not find a declaration file for module 'sour... Remove this comment to see the full error message
|
|
8
7
|
import sourceMapSupport from 'source-map-support';
|
|
9
8
|
import { NETLIFYDEVERR } from '../../../../../utils/command-helpers.js';
|
|
10
9
|
import { SERVE_FUNCTIONS_FOLDER } from '../../../../../utils/functions/functions.js';
|
|
@@ -3,7 +3,6 @@ import process from 'process';
|
|
|
3
3
|
import { isMainThread, workerData, parentPort } from 'worker_threads';
|
|
4
4
|
import { isStream } from 'is-stream';
|
|
5
5
|
import lambdaLocal from 'lambda-local';
|
|
6
|
-
// @ts-expect-error TS(7016) FIXME: Could not find a declaration file for module 'sour... Remove this comment to see the full error message
|
|
7
6
|
import sourceMapSupport from 'source-map-support';
|
|
8
7
|
if (isMainThread) {
|
|
9
8
|
throw new Error(`Do not import "${import.meta.url}" in the main thread.`);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export declare const FILE_NAME = "netlify-development.mdc";
|
|
2
|
+
export declare const NETLIFY_PROVIDER = "netlify";
|
|
3
|
+
export declare const downloadFile: (cliVersion: string) => Promise<{
|
|
4
|
+
contents: string;
|
|
5
|
+
minimumCLIVersion: string | undefined;
|
|
6
|
+
} | null>;
|
|
7
|
+
interface ParsedContextFile {
|
|
8
|
+
contents: string;
|
|
9
|
+
innerContents?: string;
|
|
10
|
+
overrides?: {
|
|
11
|
+
contents?: string;
|
|
12
|
+
innerContents?: string;
|
|
13
|
+
};
|
|
14
|
+
provider?: string;
|
|
15
|
+
version?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Parses the `<ProviderContext>` and `<ProviderContextOverrides>` blocks in
|
|
19
|
+
* a context file.
|
|
20
|
+
*/
|
|
21
|
+
export declare const parseContextFile: (contents: string) => ParsedContextFile;
|
|
22
|
+
/**
|
|
23
|
+
* Takes a context file (a template) and injects a string in an overrides block
|
|
24
|
+
* if one is found. Returns the resulting context file.
|
|
25
|
+
*/
|
|
26
|
+
export declare const applyOverrides: (template: string, overrides?: string) => string;
|
|
27
|
+
/**
|
|
28
|
+
* Reads a file on disk and tries to parse it as a context file.
|
|
29
|
+
*/
|
|
30
|
+
export declare const getExistingContext: (path: string) => Promise<ParsedContextFile | null>;
|
|
31
|
+
export declare const writeFile: (path: string, contents: string) => Promise<void>;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/recipes/ai-context/context.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,SAAS,4BAA4B,CAAA;AAElD,eAAO,MAAM,gBAAgB,YAAY,CAAA;AAKzC,eAAO,MAAM,YAAY,eAAsB,MAAM;;;SAmBpD,CAAA;AAED,UAAU,iBAAiB;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,SAAS,CAAC,EAAE;QACV,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,aAAa,CAAC,EAAE,MAAM,CAAA;KACvB,CAAA;IACD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,aAAc,MAAM,sBA0ChD,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,aAAc,MAAM,cAAc,MAAM,WASlE,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,SAAgB,MAAM,sCAqBpD,CAAA;AAED,eAAO,MAAM,SAAS,SAAgB,MAAM,YAAY,MAAM,kBAK7D,CAAA"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
const ATTRIBUTES_REGEX = /(\S*)="([^\s"]*)"/gim;
|
|
4
|
+
const BASE_URL = 'https://docs.netlify.com/ai-context';
|
|
5
|
+
export const FILE_NAME = 'netlify-development.mdc';
|
|
6
|
+
const MINIMUM_CLI_VERSION_HEADER = 'x-cli-min-ver';
|
|
7
|
+
export const NETLIFY_PROVIDER = 'netlify';
|
|
8
|
+
const PROVIDER_CONTEXT_REGEX = /<providercontext ([^>]*)>(.*)<\/providercontext>/ims;
|
|
9
|
+
const PROVIDER_CONTEXT_OVERRIDES_REGEX = /<providercontextoverrides([^>]*)>(.*)<\/providercontextoverrides>/ims;
|
|
10
|
+
const PROVIDER_CONTEXT_OVERRIDES_TAG = 'ProviderContextOverrides';
|
|
11
|
+
export const downloadFile = async (cliVersion) => {
|
|
12
|
+
try {
|
|
13
|
+
const res = await fetch(`${BASE_URL}/${FILE_NAME}`, {
|
|
14
|
+
headers: {
|
|
15
|
+
'user-agent': `NetlifyCLI ${cliVersion}`,
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
const contents = await res.text();
|
|
19
|
+
const minimumCLIVersion = res.headers.get(MINIMUM_CLI_VERSION_HEADER) ?? undefined;
|
|
20
|
+
return {
|
|
21
|
+
contents,
|
|
22
|
+
minimumCLIVersion,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
// no-op
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Parses the `<ProviderContext>` and `<ProviderContextOverrides>` blocks in
|
|
32
|
+
* a context file.
|
|
33
|
+
*/
|
|
34
|
+
export const parseContextFile = (contents) => {
|
|
35
|
+
const result = {
|
|
36
|
+
contents,
|
|
37
|
+
};
|
|
38
|
+
const providerContext = contents.match(PROVIDER_CONTEXT_REGEX);
|
|
39
|
+
if (providerContext) {
|
|
40
|
+
const [, attributes, innerContents] = providerContext;
|
|
41
|
+
result.innerContents = innerContents;
|
|
42
|
+
for (const [, name, value] of attributes.matchAll(ATTRIBUTES_REGEX)) {
|
|
43
|
+
switch (name.toLowerCase()) {
|
|
44
|
+
case 'provider':
|
|
45
|
+
result.provider = value;
|
|
46
|
+
break;
|
|
47
|
+
case 'version':
|
|
48
|
+
result.version = value;
|
|
49
|
+
break;
|
|
50
|
+
default:
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const contextOverrides = contents.match(PROVIDER_CONTEXT_OVERRIDES_REGEX);
|
|
56
|
+
if (contextOverrides) {
|
|
57
|
+
const [overrideContents, , innerContents] = contextOverrides;
|
|
58
|
+
result.overrides = {
|
|
59
|
+
contents: overrideContents,
|
|
60
|
+
innerContents,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Takes a context file (a template) and injects a string in an overrides block
|
|
67
|
+
* if one is found. Returns the resulting context file.
|
|
68
|
+
*/
|
|
69
|
+
export const applyOverrides = (template, overrides) => {
|
|
70
|
+
if (!overrides) {
|
|
71
|
+
return template;
|
|
72
|
+
}
|
|
73
|
+
return template.replace(PROVIDER_CONTEXT_OVERRIDES_REGEX, `<${PROVIDER_CONTEXT_OVERRIDES_TAG}>${overrides}</${PROVIDER_CONTEXT_OVERRIDES_TAG}>`);
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Reads a file on disk and tries to parse it as a context file.
|
|
77
|
+
*/
|
|
78
|
+
export const getExistingContext = async (path) => {
|
|
79
|
+
try {
|
|
80
|
+
const stats = await fs.stat(path);
|
|
81
|
+
if (!stats.isFile()) {
|
|
82
|
+
throw new Error(`${path} already exists but is not a file. Please remove it or rename it and try again.`);
|
|
83
|
+
}
|
|
84
|
+
const file = await fs.readFile(path, 'utf8');
|
|
85
|
+
const parsedFile = parseContextFile(file);
|
|
86
|
+
return parsedFile;
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
const exception = error;
|
|
90
|
+
if (exception.code !== 'ENOENT') {
|
|
91
|
+
throw new Error(`Could not open context file at ${path}: ${exception.message}`);
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
export const writeFile = async (path, contents) => {
|
|
97
|
+
const directory = dirname(path);
|
|
98
|
+
await fs.mkdir(directory, { recursive: true });
|
|
99
|
+
await fs.writeFile(path, contents);
|
|
100
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/recipes/ai-context/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAA;AAazE,eAAO,MAAM,WAAW,sCAAsC,CAAA;AAuC9D,eAAO,MAAM,GAAG,sBAA6B,gBAAgB,kBAuE5D,CAAA"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import semver from 'semver';
|
|
4
|
+
import { chalk, error, log, version } from '../../utils/command-helpers.js';
|
|
5
|
+
import { applyOverrides, downloadFile, getExistingContext, parseContextFile, writeFile, FILE_NAME, NETLIFY_PROVIDER, } from './context.js';
|
|
6
|
+
export const description = 'Manage context files for AI tools';
|
|
7
|
+
const presets = [
|
|
8
|
+
{ name: 'Cursor rules (.cursor/rules/)', value: '.cursor/rules' },
|
|
9
|
+
{ name: 'Custom location', value: '' },
|
|
10
|
+
];
|
|
11
|
+
const promptForPath = async () => {
|
|
12
|
+
const { presetPath } = await inquirer.prompt([
|
|
13
|
+
{
|
|
14
|
+
name: 'presetPath',
|
|
15
|
+
message: 'Where should we put the context files?',
|
|
16
|
+
type: 'list',
|
|
17
|
+
choices: presets,
|
|
18
|
+
},
|
|
19
|
+
]);
|
|
20
|
+
if (presetPath) {
|
|
21
|
+
return presetPath;
|
|
22
|
+
}
|
|
23
|
+
const { customPath } = await inquirer.prompt([
|
|
24
|
+
{
|
|
25
|
+
type: 'input',
|
|
26
|
+
name: 'customPath',
|
|
27
|
+
message: 'Enter the path, relative to the project root, where the context files should be placed',
|
|
28
|
+
default: './ai-context',
|
|
29
|
+
},
|
|
30
|
+
]);
|
|
31
|
+
if (customPath) {
|
|
32
|
+
return customPath;
|
|
33
|
+
}
|
|
34
|
+
log('You must select a path.');
|
|
35
|
+
return promptForPath();
|
|
36
|
+
};
|
|
37
|
+
export const run = async ({ args, command }) => {
|
|
38
|
+
// Start the download in the background while we wait for the prompts.
|
|
39
|
+
// eslint-disable-next-line promise/prefer-await-to-then
|
|
40
|
+
const download = downloadFile(version).catch(() => null);
|
|
41
|
+
const filePath = args[0] || (await promptForPath());
|
|
42
|
+
const { contents: downloadedFile, minimumCLIVersion } = (await download) ?? {};
|
|
43
|
+
if (!downloadedFile) {
|
|
44
|
+
error('An error occurred when pulling the latest context files. Please try again.');
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (minimumCLIVersion && semver.lt(version, minimumCLIVersion)) {
|
|
48
|
+
error(`This command requires version ${minimumCLIVersion} or above of the Netlify CLI. Refer to ${chalk.underline('https://ntl.fyi/update-cli')} for information on how to update.`);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const absoluteFilePath = resolve(command?.workingDir ?? '', filePath, FILE_NAME);
|
|
52
|
+
const existing = await getExistingContext(absoluteFilePath);
|
|
53
|
+
const remote = parseContextFile(downloadedFile);
|
|
54
|
+
let { contents } = remote;
|
|
55
|
+
// Does a file already exist at this path?
|
|
56
|
+
if (existing) {
|
|
57
|
+
// If it's a file we've created, let's check the version and bail if we're
|
|
58
|
+
// already on the latest, otherwise rewrite it with the latest version.
|
|
59
|
+
if (existing.provider?.toLowerCase() === NETLIFY_PROVIDER) {
|
|
60
|
+
if (remote?.version === existing.version) {
|
|
61
|
+
log(`You're all up to date! ${chalk.underline(absoluteFilePath)} contains the latest version of the context files.`);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
// We must preserve any overrides found in the existing file.
|
|
65
|
+
contents = applyOverrides(remote.contents, existing.overrides?.innerContents);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
// If this is not a file we've created, we can offer to overwrite it and
|
|
69
|
+
// preserve the existing contents by moving it to the overrides slot.
|
|
70
|
+
const { confirm } = await inquirer.prompt({
|
|
71
|
+
type: 'confirm',
|
|
72
|
+
name: 'confirm',
|
|
73
|
+
message: `A context file already exists at ${chalk.underline(absoluteFilePath)}. It has not been created by the Netlify CLI, but we can update it while preserving its existing content. Can we proceed?`,
|
|
74
|
+
default: true,
|
|
75
|
+
});
|
|
76
|
+
if (!confirm) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
// Whatever exists in the file goes in the overrides block.
|
|
80
|
+
contents = applyOverrides(remote.contents, existing.contents);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
await writeFile(absoluteFilePath, contents);
|
|
84
|
+
log(`${existing ? 'Updated' : 'Created'} context files at ${chalk.underline(absoluteFilePath)}`);
|
|
85
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/recipes/vscode/settings.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAKrC,eAAO,MAAM,aAAa;;;;
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/recipes/vscode/settings.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAKrC,eAAO,MAAM,aAAa;;;;SA0BzB,CAAA;AAGD,eAAO,MAAM,WAAW;;;;;;EA0BvB,CAAA;AAGD,eAAO,MAAM,aAAa;;;mBAKzB,CAAA"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { mkdir, readFile, stat, writeFile } from 'fs/promises';
|
|
2
|
-
import { dirname, relative } from 'path';
|
|
2
|
+
import { dirname, posix, relative } from 'path';
|
|
3
3
|
import * as JSONC from 'comment-json';
|
|
4
|
-
|
|
5
|
-
import unixify from 'unixify';
|
|
4
|
+
const toUnixPath = (path) => path.replace(/\\/g, '/');
|
|
6
5
|
// @ts-expect-error TS(7006) FIXME: Parameter 'existingSettings' implicitly has an 'an... Remove this comment to see the full error message
|
|
7
6
|
export const applySettings = (existingSettings, { denoBinary, edgeFunctionsPath, repositoryRoot }) => {
|
|
8
|
-
|
|
7
|
+
// TODO(serhalp) I'm not convinced we want to convert to Unix paths on Windows? Does this even work? Was this a
|
|
8
|
+
// workaround for something, perhaps https://github.com/denoland/vscode_deno/pull/745?
|
|
9
|
+
const relativeEdgeFunctionsPath = toUnixPath(posix.normalize(relative(repositoryRoot, edgeFunctionsPath)));
|
|
9
10
|
const settings = JSONC.assign(existingSettings, {
|
|
10
11
|
'deno.enable': true,
|
|
11
12
|
'deno.enablePaths': existingSettings['deno.enablePaths'] || [],
|