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.
Files changed (93) hide show
  1. package/dist/commands/base-command.d.ts.map +1 -1
  2. package/dist/commands/base-command.js +2 -13
  3. package/dist/commands/blobs/blobs.js +2 -2
  4. package/dist/commands/build/build.d.ts +4 -11
  5. package/dist/commands/build/build.d.ts.map +1 -1
  6. package/dist/commands/build/build.js +1 -7
  7. package/dist/commands/build/index.js +1 -1
  8. package/dist/commands/completion/completion.d.ts +4 -4
  9. package/dist/commands/completion/completion.d.ts.map +1 -1
  10. package/dist/commands/completion/completion.js +4 -5
  11. package/dist/commands/deploy/index.d.ts.map +1 -1
  12. package/dist/commands/deploy/index.js +5 -6
  13. package/dist/commands/dev/dev.d.ts.map +1 -1
  14. package/dist/commands/dev/dev.js +1 -15
  15. package/dist/commands/env/env-list.d.ts +2 -2
  16. package/dist/commands/env/env-list.d.ts.map +1 -1
  17. package/dist/commands/env/env.d.ts.map +1 -1
  18. package/dist/commands/env/env.js +5 -4
  19. package/dist/commands/functions/functions.d.ts +1 -1
  20. package/dist/commands/functions/functions.d.ts.map +1 -1
  21. package/dist/commands/functions/functions.js +4 -2
  22. package/dist/commands/init/index.d.ts.map +1 -1
  23. package/dist/commands/init/index.js +0 -2
  24. package/dist/commands/link/index.d.ts.map +1 -1
  25. package/dist/commands/link/index.js +0 -2
  26. package/dist/commands/main.d.ts.map +1 -1
  27. package/dist/commands/main.js +0 -3
  28. package/dist/commands/recipes/recipes.d.ts +1 -2
  29. package/dist/commands/recipes/recipes.d.ts.map +1 -1
  30. package/dist/commands/serve/index.d.ts.map +1 -1
  31. package/dist/commands/serve/index.js +1 -4
  32. package/dist/commands/status/index.d.ts +1 -1
  33. package/dist/commands/status/index.d.ts.map +1 -1
  34. package/dist/commands/status/index.js +2 -1
  35. package/dist/lib/build.d.ts +36 -67
  36. package/dist/lib/build.d.ts.map +1 -1
  37. package/dist/lib/build.js +6 -41
  38. package/dist/lib/completion/script.js +3 -13
  39. package/dist/lib/functions/form-submissions-handler.d.ts.map +1 -1
  40. package/dist/lib/functions/form-submissions-handler.js +0 -2
  41. package/dist/lib/functions/runtimes/js/builders/netlify-lambda.d.ts.map +1 -1
  42. package/dist/lib/functions/runtimes/js/builders/netlify-lambda.js +8 -7
  43. package/dist/lib/functions/runtimes/js/builders/zisi.d.ts.map +1 -1
  44. package/dist/lib/functions/runtimes/js/builders/zisi.js +0 -1
  45. package/dist/lib/functions/runtimes/js/worker.js +0 -1
  46. package/dist/recipes/ai-context/context.d.ts +33 -0
  47. package/dist/recipes/ai-context/context.d.ts.map +1 -0
  48. package/dist/recipes/ai-context/context.js +100 -0
  49. package/dist/recipes/ai-context/index.d.ts +4 -0
  50. package/dist/recipes/ai-context/index.d.ts.map +1 -0
  51. package/dist/recipes/ai-context/index.js +85 -0
  52. package/dist/recipes/vscode/settings.d.ts.map +1 -1
  53. package/dist/recipes/vscode/settings.js +5 -4
  54. package/dist/tsconfig.tsbuildinfo +1 -1
  55. package/dist/utils/command-helpers.d.ts +2 -2
  56. package/dist/utils/command-helpers.js +1 -1
  57. package/dist/utils/deploy/hash-files.js +3 -3
  58. package/dist/utils/deploy/hash-fns.d.ts.map +1 -1
  59. package/dist/utils/deploy/hash-fns.js +3 -2
  60. package/dist/utils/deploy/hasher-segments.d.ts +3 -3
  61. package/dist/utils/deploy/hasher-segments.d.ts.map +1 -1
  62. package/dist/utils/deploy/hasher-segments.js +2 -9
  63. package/dist/utils/get-global-config.d.ts.map +1 -1
  64. package/dist/utils/get-global-config.js +2 -2
  65. package/dist/utils/get-repo-data.d.ts +4 -4
  66. package/dist/utils/get-repo-data.d.ts.map +1 -1
  67. package/dist/utils/get-repo-data.js +7 -6
  68. package/dist/utils/open-browser.d.ts.map +1 -1
  69. package/dist/utils/open-browser.js +1 -2
  70. package/dist/utils/proxy.d.ts.map +1 -1
  71. package/dist/utils/proxy.js +3 -5
  72. package/dist/utils/rules-proxy.d.ts.map +1 -1
  73. package/dist/utils/rules-proxy.js +0 -1
  74. package/dist/utils/run-build.d.ts.map +1 -1
  75. package/dist/utils/run-build.js +7 -2
  76. package/dist/utils/sites/create-template.d.ts.map +1 -1
  77. package/dist/utils/sites/create-template.js +2 -3
  78. package/dist/utils/state-config.d.ts.map +1 -1
  79. package/dist/utils/state-config.js +0 -1
  80. package/dist/utils/types.d.ts +7 -0
  81. package/dist/utils/types.d.ts.map +1 -1
  82. package/functions-templates/javascript/scheduled-function/package.json +1 -1
  83. package/functions-templates/typescript/hello-world/package-lock.json +15 -46
  84. package/functions-templates/typescript/hello-world/package.json +1 -1
  85. package/functions-templates/typescript/scheduled-function/package.json +1 -1
  86. package/npm-shrinkwrap.json +650 -742
  87. package/package.json +16 -18
  88. package/dist/commands/integration/deploy.d.ts +0 -8
  89. package/dist/commands/integration/deploy.d.ts.map +0 -1
  90. package/dist/commands/integration/deploy.js +0 -353
  91. package/dist/commands/integration/index.d.ts +0 -4
  92. package/dist/commands/integration/index.d.ts.map +0 -1
  93. package/dist/commands/integration/index.js +0 -26
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/lib/build.ts"],"names":[],"mappings":"AAYA;;;;GAIG;AAKH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiE3B,CAAA;AAED;;;;GAIG;AAEH,eAAO,MAAM,QAAQ;;;;EAcpB,CAAA"}
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
- // @ts-expect-error TS(7016) FIXME: Could not find a declaration file for module 'tabt... Remove this comment to see the full error message
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":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAU7C,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
+ {"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;;;;;;;;EAqD/B,CAAA;AAED,wBAA8B,OAAO;;;;;;;;GASpC"}
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 { program } from 'commander';
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":"AAgHA;;;;;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"}
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,4 @@
1
+ import type { RunRecipeOptions } from '../../commands/recipes/recipes.js';
2
+ export declare const description = "Manage context files for AI tools";
3
+ export declare const run: ({ args, command }: RunRecipeOptions) => Promise<void>;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -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;;;;SAwBzB,CAAA;AAGD,eAAO,MAAM,WAAW;;;;;;EA0BvB,CAAA;AAGD,eAAO,MAAM,aAAa;;;mBAKzB,CAAA"}
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
- // @ts-expect-error TS(7016) FIXME: Could not find a declaration file for module 'unix... Remove this comment to see the full error message
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
- const relativeEdgeFunctionsPath = unixify(relative(repositoryRoot, edgeFunctionsPath));
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'] || [],