netlify-cli 18.1.0 → 19.0.0-pre.4b63f12
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/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/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/npm-shrinkwrap.json +29926 -12308
- package/package.json +11 -15
- package/scripts/prepare-for-publish.js +48 -34
- 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/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "netlify-cli",
|
|
3
3
|
"description": "Netlify command line tool",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "19.0.0-pre.4b63f12",
|
|
5
5
|
"author": "Netlify Inc.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"engines": {
|
|
@@ -31,14 +31,13 @@
|
|
|
31
31
|
"url": "https://github.com/netlify/cli/issues"
|
|
32
32
|
},
|
|
33
33
|
"scripts": {
|
|
34
|
-
"prepublishOnly": "node ./scripts/prepare-for-publish.js"
|
|
35
|
-
"postinstall": "node ./scripts/postinstall.js"
|
|
34
|
+
"prepublishOnly": "node ./scripts/prepare-for-publish.js"
|
|
36
35
|
},
|
|
37
36
|
"dependencies": {
|
|
38
37
|
"@bugsnag/js": "8.2.0",
|
|
39
38
|
"@fastify/static": "7.0.4",
|
|
40
39
|
"@netlify/blobs": "8.1.1",
|
|
41
|
-
"@netlify/build": "29.58.
|
|
40
|
+
"@netlify/build": "29.58.10",
|
|
42
41
|
"@netlify/build-info": "8.0.0",
|
|
43
42
|
"@netlify/config": "20.21.7",
|
|
44
43
|
"@netlify/edge-bundler": "12.3.2",
|
|
@@ -47,23 +46,23 @@
|
|
|
47
46
|
"@netlify/local-functions-proxy": "1.1.1",
|
|
48
47
|
"@netlify/redirect-parser": "14.5.0",
|
|
49
48
|
"@netlify/zip-it-and-ship-it": "9.42.5",
|
|
50
|
-
"@octokit/rest": "21.1.
|
|
49
|
+
"@octokit/rest": "21.1.1",
|
|
51
50
|
"@opentelemetry/api": "1.8.0",
|
|
51
|
+
"@pnpm/tabtab": "0.5.4",
|
|
52
52
|
"ansi-escapes": "7.0.0",
|
|
53
53
|
"ansi-to-html": "0.7.2",
|
|
54
54
|
"ascii-table": "0.0.9",
|
|
55
55
|
"backoff": "2.5.0",
|
|
56
|
-
"better-opn": "3.0.2",
|
|
57
56
|
"boxen": "8.0.1",
|
|
58
57
|
"chalk": "5.4.1",
|
|
59
58
|
"chokidar": "3.6.0",
|
|
60
59
|
"ci-info": "4.1.0",
|
|
61
60
|
"clean-deep": "3.4.0",
|
|
62
|
-
"commander": "
|
|
61
|
+
"commander": "12.1.0",
|
|
63
62
|
"comment-json": "4.2.5",
|
|
64
63
|
"configstore": "7.0.0",
|
|
65
64
|
"content-type": "1.0.5",
|
|
66
|
-
"cookie": "0.
|
|
65
|
+
"cookie": "1.0.2",
|
|
67
66
|
"cron-parser": "4.9.0",
|
|
68
67
|
"debug": "4.4.0",
|
|
69
68
|
"decache": "4.6.2",
|
|
@@ -90,14 +89,13 @@
|
|
|
90
89
|
"http-proxy": "1.18.1",
|
|
91
90
|
"http-proxy-middleware": "2.0.7",
|
|
92
91
|
"https-proxy-agent": "7.0.6",
|
|
93
|
-
"inquirer": "8.
|
|
92
|
+
"inquirer": "8.2.6",
|
|
94
93
|
"inquirer-autocomplete-prompt": "1.4.0",
|
|
95
94
|
"ipx": "2.1.0",
|
|
96
95
|
"is-docker": "3.0.0",
|
|
97
96
|
"is-stream": "4.0.1",
|
|
98
97
|
"is-wsl": "3.1.0",
|
|
99
98
|
"isexe": "3.1.1",
|
|
100
|
-
"js-yaml": "4.1.0",
|
|
101
99
|
"jsonwebtoken": "9.0.2",
|
|
102
100
|
"jwt-decode": "4.0.0",
|
|
103
101
|
"lambda-local": "2.2.0",
|
|
@@ -111,6 +109,7 @@
|
|
|
111
109
|
"netlify": "13.3.3",
|
|
112
110
|
"netlify-redirector": "0.5.0",
|
|
113
111
|
"node-fetch": "3.3.2",
|
|
112
|
+
"open": "10.1.0",
|
|
114
113
|
"ora": "8.2.0",
|
|
115
114
|
"p-filter": "4.1.0",
|
|
116
115
|
"p-map": "7.0.3",
|
|
@@ -122,11 +121,10 @@
|
|
|
122
121
|
"pump": "3.0.2",
|
|
123
122
|
"raw-body": "3.0.0",
|
|
124
123
|
"read-package-up": "11.0.0",
|
|
125
|
-
"readdirp": "4.1.
|
|
124
|
+
"readdirp": "4.1.2",
|
|
126
125
|
"semver": "7.7.1",
|
|
127
126
|
"source-map-support": "0.5.21",
|
|
128
127
|
"strip-ansi-control-characters": "2.0.0",
|
|
129
|
-
"tabtab": "3.0.2",
|
|
130
128
|
"tempy": "3.1.0",
|
|
131
129
|
"terminal-link": "3.0.0",
|
|
132
130
|
"through2-filter": "4.0.0",
|
|
@@ -134,12 +132,10 @@
|
|
|
134
132
|
"toml": "3.0.0",
|
|
135
133
|
"tomlify-j0.4": "3.0.0",
|
|
136
134
|
"ulid": "2.3.0",
|
|
137
|
-
"unixify": "1.0.0",
|
|
138
135
|
"update-notifier": "7.3.1",
|
|
139
136
|
"uuid": "11.0.5",
|
|
140
137
|
"wait-port": "1.1.0",
|
|
141
138
|
"write-file-atomic": "5.0.1",
|
|
142
|
-
"ws": "8.18.
|
|
143
|
-
"zod": "3.24.1"
|
|
139
|
+
"ws": "8.18.1"
|
|
144
140
|
}
|
|
145
141
|
}
|
|
@@ -5,8 +5,29 @@ import { fileURLToPath } from 'url'
|
|
|
5
5
|
import execa from 'execa'
|
|
6
6
|
import ora from 'ora'
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
const insertUserPostinstall = (pkgJson) => {
|
|
9
|
+
pkgJson.scripts.postinstall = pkgJson.scripts['postinstall-pack']
|
|
10
|
+
delete pkgJson.scripts['postinstall-pack']
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const installDeps = async () => {
|
|
14
|
+
let spinner = ora('Running `npm install --no-audit`').start()
|
|
15
|
+
await execa('npm', ['install', '--no-audit'])
|
|
16
|
+
spinner.succeed()
|
|
17
|
+
|
|
18
|
+
spinner = ora('Running `npm shrinkwrap`').start()
|
|
19
|
+
await execa('npm', ['shrinkwrap'])
|
|
20
|
+
spinner.succeed()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// NOTE: this must run before `cleanPackageJson`, otherwise the `build` script has been deleted
|
|
24
|
+
const buildPackageForPublish = async () => {
|
|
25
|
+
const spinner = ora('Running `npm run build`').start()
|
|
26
|
+
await execa('npm', ['run', 'build'])
|
|
27
|
+
spinner.succeed()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const SCRIPTS_TO_KEEP_ON_PUBLISHED_PKG = new Set([
|
|
10
31
|
'postinstall-pack',
|
|
11
32
|
'postpack',
|
|
12
33
|
'preinstall',
|
|
@@ -15,42 +36,35 @@ const preserveScripts = new Set([
|
|
|
15
36
|
'prepublishOnly',
|
|
16
37
|
])
|
|
17
38
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
39
|
+
const cleanPackageJson = (pkgJson) => {
|
|
40
|
+
delete pkgJson.devDependencies
|
|
41
|
+
delete pkgJson.config
|
|
42
|
+
|
|
43
|
+
for (const scriptName in pkgJson.scripts) {
|
|
44
|
+
if (SCRIPTS_TO_KEEP_ON_PUBLISHED_PKG.has(scriptName)) continue
|
|
22
45
|
|
|
23
|
-
|
|
24
|
-
|
|
46
|
+
delete pkgJson.scripts[scriptName]
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const writeUpdatedPackageJson = async (pkgJson, packageJsonPath) => {
|
|
51
|
+
const spinner = ora('Patching package.json (removing devDependencies, scripts, etc').start()
|
|
52
|
+
await writeFile(packageJsonPath, JSON.stringify(pkgJson, null, 2))
|
|
53
|
+
spinner.succeed()
|
|
54
|
+
}
|
|
25
55
|
|
|
26
|
-
const
|
|
56
|
+
const main = async () => {
|
|
57
|
+
const dir = dirname(fileURLToPath(import.meta.url))
|
|
58
|
+
const pkgJsonPath = join(dir, '../package.json')
|
|
59
|
+
const pkgJson = JSON.parse(await readFile(pkgJsonPath))
|
|
27
60
|
|
|
28
|
-
|
|
29
|
-
delete pkgJson.ava
|
|
30
|
-
delete pkgJson.config
|
|
61
|
+
await installDeps()
|
|
31
62
|
|
|
32
|
-
|
|
33
|
-
if (preserveScripts.has(scriptName)) continue
|
|
63
|
+
await buildPackageForPublish()
|
|
34
64
|
|
|
35
|
-
|
|
65
|
+
insertUserPostinstall(pkgJson)
|
|
66
|
+
cleanPackageJson(pkgJson)
|
|
67
|
+
await writeUpdatedPackageJson(pkgJson, pkgJsonPath)
|
|
36
68
|
}
|
|
37
69
|
|
|
38
|
-
|
|
39
|
-
delete pkgJson.scripts['postinstall-pack']
|
|
40
|
-
|
|
41
|
-
await writeFile(packageJsonPath, JSON.stringify(pkgJson, null, 2))
|
|
42
|
-
spinner.succeed()
|
|
43
|
-
|
|
44
|
-
spinner = ora({
|
|
45
|
-
spinner: 'star',
|
|
46
|
-
text: 'Running `npm install --no-audit`',
|
|
47
|
-
}).start()
|
|
48
|
-
await execa('npm', ['install', '--no-audit'])
|
|
49
|
-
spinner.succeed()
|
|
50
|
-
|
|
51
|
-
spinner = ora({
|
|
52
|
-
spinner: 'star',
|
|
53
|
-
text: 'Running `npm shrinkwrap`',
|
|
54
|
-
}).start()
|
|
55
|
-
await execa('npm', ['shrinkwrap'])
|
|
56
|
-
spinner.succeed()
|
|
70
|
+
await main()
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { OptionValues } from 'commander';
|
|
2
|
-
import BaseCommand from '../base-command.js';
|
|
3
|
-
export declare function areScopesEqual(localScopes: any, remoteScopes: any): any;
|
|
4
|
-
export declare function registerIntegration(workingDir: any, siteId: any, accountId: any, localIntegrationConfig: any, token: any): Promise<void>;
|
|
5
|
-
export declare function updateIntegration(workingDir: any, options: any, siteId: any, accountId: any, localIntegrationConfig: any, token: any, registeredIntegration: any): Promise<void>;
|
|
6
|
-
export declare const getConfiguration: (workingDir: any) => any;
|
|
7
|
-
export declare const deploy: (options: OptionValues, command: BaseCommand) => Promise<void>;
|
|
8
|
-
//# sourceMappingURL=deploy.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../../src/commands/integration/deploy.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAUxC,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAS5C,wBAAgB,cAAc,CAAC,WAAW,KAAA,EAAE,YAAY,KAAA,OAOvD;AAuFD,wBAAsB,mBAAmB,CAAC,UAAU,KAAA,EAAE,MAAM,KAAA,EAAE,SAAS,KAAA,EAAE,sBAAsB,KAAA,EAAE,KAAK,KAAA,iBAyErG;AAED,wBAAsB,iBAAiB,CAErC,UAAU,KAAA,EAEV,OAAO,KAAA,EAEP,MAAM,KAAA,EAEN,SAAS,KAAA,EAET,sBAAsB,KAAA,EAEtB,KAAK,KAAA,EAEL,qBAAqB,KAAA,iBAsHtB;AA2BD,eAAO,MAAM,gBAAgB,0BA6B5B,CAAA;AAED,eAAO,MAAM,MAAM,YAAmB,YAAY,WAAW,WAAW,kBAgEvE,CAAA"}
|
|
@@ -1,353 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import process from 'process';
|
|
3
|
-
import { resolve } from 'path';
|
|
4
|
-
import { exit } from 'process';
|
|
5
|
-
import inquirer from 'inquirer';
|
|
6
|
-
// @ts-expect-error TS(7016) FIXME: Could not find a declaration file for module 'js-y... Remove this comment to see the full error message
|
|
7
|
-
import yaml from 'js-yaml';
|
|
8
|
-
import fetch from 'node-fetch';
|
|
9
|
-
import { z } from 'zod';
|
|
10
|
-
import { getBuildOptions } from '../../lib/build.js';
|
|
11
|
-
import { chalk, getToken, log } from '../../utils/command-helpers.js';
|
|
12
|
-
import { getSiteInformation } from '../../utils/dev.js';
|
|
13
|
-
import { checkOptions } from '../build/build.js';
|
|
14
|
-
import { deploy as siteDeploy } from '../deploy/deploy.js';
|
|
15
|
-
function getIntegrationAPIUrl() {
|
|
16
|
-
return process.env.INTEGRATION_URL || 'https://api.netlifysdk.com';
|
|
17
|
-
}
|
|
18
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'localScopes' implicitly has an 'any' ty... Remove this comment to see the full error message
|
|
19
|
-
export function areScopesEqual(localScopes, remoteScopes) {
|
|
20
|
-
if (localScopes.length !== remoteScopes.length) {
|
|
21
|
-
return false;
|
|
22
|
-
}
|
|
23
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'scope' implicitly has an 'any' type.
|
|
24
|
-
return localScopes.every((scope) => remoteScopes.includes(scope));
|
|
25
|
-
}
|
|
26
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'localScopes' implicitly has an 'any' ty... Remove this comment to see the full error message
|
|
27
|
-
function logScopeConfirmationMessage(localScopes, remoteScopes) {
|
|
28
|
-
log(chalk.yellow(`This integration is already registered. The current required scopes are:`));
|
|
29
|
-
for (const scope of remoteScopes) {
|
|
30
|
-
log(chalk.green(`- ${scope}`));
|
|
31
|
-
}
|
|
32
|
-
log(chalk.yellow('and will be updated to:'));
|
|
33
|
-
for (const scope of localScopes) {
|
|
34
|
-
log(chalk.green(`- ${scope}`));
|
|
35
|
-
}
|
|
36
|
-
log(chalk.yellow('if you continue. This will only affect future installations of the integration.'));
|
|
37
|
-
}
|
|
38
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'registeredIntegrationScopes' implicitly... Remove this comment to see the full error message
|
|
39
|
-
function formatScopesToWrite(registeredIntegrationScopes) {
|
|
40
|
-
let scopesToWrite = {};
|
|
41
|
-
for (const scope of registeredIntegrationScopes) {
|
|
42
|
-
const [resource, permission] = scope.split(':');
|
|
43
|
-
if (resource === 'all') {
|
|
44
|
-
scopesToWrite = { all: true };
|
|
45
|
-
break;
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
// @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
|
49
|
-
if (!scopesToWrite[resource]) {
|
|
50
|
-
// @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
|
51
|
-
scopesToWrite[resource] = [];
|
|
52
|
-
}
|
|
53
|
-
// @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
|
54
|
-
scopesToWrite[resource].push(permission);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return scopesToWrite;
|
|
58
|
-
}
|
|
59
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'scopes' implicitly has an 'any' type.
|
|
60
|
-
function formatScopesForRemote(scopes) {
|
|
61
|
-
const scopesToWrite = [];
|
|
62
|
-
if (scopes.all) {
|
|
63
|
-
scopesToWrite.push('all');
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
const scopeResources = Object.keys(scopes);
|
|
67
|
-
scopeResources.forEach((resource) => {
|
|
68
|
-
const permissionsRequested = scopes[resource];
|
|
69
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'permission' implicitly has an 'any' typ... Remove this comment to see the full error message
|
|
70
|
-
permissionsRequested.forEach((permission) => {
|
|
71
|
-
scopesToWrite.push(`${resource}:${permission}`);
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
return scopesToWrite.join(',');
|
|
76
|
-
}
|
|
77
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'name' implicitly has an 'any' type.
|
|
78
|
-
function verifyRequiredFieldsAreInConfig(name, description, scopes) {
|
|
79
|
-
const missingFields = [];
|
|
80
|
-
if (!name) {
|
|
81
|
-
missingFields.push('name');
|
|
82
|
-
}
|
|
83
|
-
if (!description) {
|
|
84
|
-
missingFields.push('description');
|
|
85
|
-
}
|
|
86
|
-
if (!scopes) {
|
|
87
|
-
missingFields.push('scopes');
|
|
88
|
-
}
|
|
89
|
-
if (missingFields.length !== 0) {
|
|
90
|
-
log(chalk.yellow(`You are missing the following fields for the integration to be deployed: ${missingFields.join(', ')}. Please add a these fields as an entry to the integration.yaml file and try again.`));
|
|
91
|
-
log(chalk.yellow('For more information on the required fields, please see the documentation: https://ntl.fyi/create-private-integration'));
|
|
92
|
-
return false;
|
|
93
|
-
}
|
|
94
|
-
return true;
|
|
95
|
-
}
|
|
96
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'workingDir' implicitly has an 'any' typ... Remove this comment to see the full error message
|
|
97
|
-
export async function registerIntegration(workingDir, siteId, accountId, localIntegrationConfig, token) {
|
|
98
|
-
const { description, name, scopes, slug } = localIntegrationConfig;
|
|
99
|
-
log(chalk.yellow(`An integration associated with the site ID ${siteId} is not registered.`));
|
|
100
|
-
const registerPrompt = await inquirer.prompt([
|
|
101
|
-
{
|
|
102
|
-
type: 'confirm',
|
|
103
|
-
name: 'registerIntegration',
|
|
104
|
-
message: `Would you like to register this site as a private integration now?`,
|
|
105
|
-
default: false,
|
|
106
|
-
},
|
|
107
|
-
]);
|
|
108
|
-
if (!registerPrompt.registerIntegration) {
|
|
109
|
-
log(chalk.white("Cancelling deployment. Please run 'netlify int deploy' again when you are ready to register the integration."));
|
|
110
|
-
log(chalk.white("You can also register the integration through the Netlify UI on the 'Integrations' > 'Create private integration' page"));
|
|
111
|
-
exit(1);
|
|
112
|
-
}
|
|
113
|
-
if (!verifyRequiredFieldsAreInConfig(name, description, scopes)) {
|
|
114
|
-
exit(1);
|
|
115
|
-
}
|
|
116
|
-
log(chalk.white('Registering the integration...'));
|
|
117
|
-
const { body, statusCode } = await fetch(`${getIntegrationAPIUrl()}/${accountId}/integrations`, {
|
|
118
|
-
method: 'POST',
|
|
119
|
-
headers: {
|
|
120
|
-
'netlify-token': token,
|
|
121
|
-
},
|
|
122
|
-
body: JSON.stringify({
|
|
123
|
-
name,
|
|
124
|
-
slug,
|
|
125
|
-
description,
|
|
126
|
-
hostSiteId: siteId,
|
|
127
|
-
scopes: formatScopesForRemote(scopes),
|
|
128
|
-
}),
|
|
129
|
-
}).then(async (res) => {
|
|
130
|
-
const response = await res.json();
|
|
131
|
-
return { body: response, statusCode: res.status };
|
|
132
|
-
});
|
|
133
|
-
if (statusCode !== 201) {
|
|
134
|
-
log(chalk.red(`There was an error registering the integration:`));
|
|
135
|
-
log();
|
|
136
|
-
log(chalk.red(`-----------------------------------------------`));
|
|
137
|
-
// @ts-expect-error TS(18046) - 'body' is of type 'unknown'
|
|
138
|
-
log(chalk.red(body.msg));
|
|
139
|
-
log(chalk.red(`-----------------------------------------------`));
|
|
140
|
-
log();
|
|
141
|
-
log(chalk.red(`Please try again. If the problem persists, please contact support.`));
|
|
142
|
-
exit(1);
|
|
143
|
-
}
|
|
144
|
-
// @ts-expect-error TS(18046) - 'body' is of type 'unknown'
|
|
145
|
-
log(chalk.green(`Successfully registered the integration with the slug: ${body.slug}`));
|
|
146
|
-
const updatedIntegrationConfig = yaml.dump({
|
|
147
|
-
// @ts-expect-error TS(18046) - 'body' is of type 'unknown'
|
|
148
|
-
config: { name, description, slug: body.slug, scopes },
|
|
149
|
-
});
|
|
150
|
-
const filePath = resolve(workingDir, 'integration.yaml');
|
|
151
|
-
await fs.promises.writeFile(filePath, updatedIntegrationConfig);
|
|
152
|
-
log(chalk.yellow('Your integration.yaml file has been updated. Please commit and push these changes.'));
|
|
153
|
-
}
|
|
154
|
-
export async function updateIntegration(
|
|
155
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'workingDir' implicitly has an 'any' typ... Remove this comment to see the full error message
|
|
156
|
-
workingDir,
|
|
157
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type.
|
|
158
|
-
options,
|
|
159
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'siteId' implicitly has an 'any' type.
|
|
160
|
-
siteId,
|
|
161
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'accountId' implicitly has an 'any' type... Remove this comment to see the full error message
|
|
162
|
-
accountId,
|
|
163
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'localIntegrationConfig' implicitly has ... Remove this comment to see the full error message
|
|
164
|
-
localIntegrationConfig,
|
|
165
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'token' implicitly has an 'any' type.
|
|
166
|
-
token,
|
|
167
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'registeredIntegration' implicitly has a... Remove this comment to see the full error message
|
|
168
|
-
registeredIntegration) {
|
|
169
|
-
let { description, name, scopes, slug } = localIntegrationConfig;
|
|
170
|
-
let integrationSlug = slug;
|
|
171
|
-
if (slug !== registeredIntegration.slug) {
|
|
172
|
-
// Update the project's integration.yaml file with the remote slug since that will
|
|
173
|
-
// be considered the source of truth and is a value that can't be edited by the user.
|
|
174
|
-
// Let the user know they need to commit and push the changes.
|
|
175
|
-
integrationSlug = registeredIntegration.slug;
|
|
176
|
-
}
|
|
177
|
-
if (!name) {
|
|
178
|
-
// Disabling this lint rule because the destructuring was not assigning the variable correct and leading to a bug
|
|
179
|
-
// eslint-disable-next-line prefer-destructuring
|
|
180
|
-
name = registeredIntegration.name;
|
|
181
|
-
}
|
|
182
|
-
if (!description) {
|
|
183
|
-
// eslint-disable-next-line prefer-destructuring
|
|
184
|
-
description = registeredIntegration.description;
|
|
185
|
-
}
|
|
186
|
-
// This is returned as a comma separated string and will be easier to manage here as an array
|
|
187
|
-
const registeredIntegrationScopes = registeredIntegration.scopes.split(',');
|
|
188
|
-
const scopeResources = Object.keys(scopes);
|
|
189
|
-
// @ts-expect-error TS(7034) FIXME: Variable 'localScopes' implicitly has type 'any[]'... Remove this comment to see the full error message
|
|
190
|
-
let localScopes = [];
|
|
191
|
-
if (scopeResources.includes('all')) {
|
|
192
|
-
localScopes = ['all'];
|
|
193
|
-
}
|
|
194
|
-
else {
|
|
195
|
-
scopeResources.forEach((resource) => {
|
|
196
|
-
const permissionsRequested = scopes[resource];
|
|
197
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'permission' implicitly has an 'any' typ... Remove this comment to see the full error message
|
|
198
|
-
permissionsRequested.forEach((permission) => {
|
|
199
|
-
localScopes.push(`${resource}:${permission}`);
|
|
200
|
-
});
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
// @ts-expect-error TS(7005) FIXME: Variable 'localScopes' implicitly has an 'any[]' t... Remove this comment to see the full error message
|
|
204
|
-
if (!areScopesEqual(localScopes, registeredIntegrationScopes)) {
|
|
205
|
-
// @ts-expect-error TS(7005) FIXME: Variable 'localScopes' implicitly has an 'any[]' t... Remove this comment to see the full error message
|
|
206
|
-
logScopeConfirmationMessage(localScopes, registeredIntegrationScopes);
|
|
207
|
-
const scopePrompt = await inquirer.prompt([
|
|
208
|
-
{
|
|
209
|
-
type: 'confirm',
|
|
210
|
-
name: 'updateScopes',
|
|
211
|
-
message: `Do you want to update the scopes?`,
|
|
212
|
-
default: false,
|
|
213
|
-
},
|
|
214
|
-
]);
|
|
215
|
-
let scopesToWrite;
|
|
216
|
-
if (scopePrompt.updateScopes) {
|
|
217
|
-
// Update the scopes in remote
|
|
218
|
-
scopesToWrite = scopes;
|
|
219
|
-
const { statusCode, updateResponse } = await fetch(`${getIntegrationAPIUrl()}/${accountId}/integrations/${integrationSlug}`, {
|
|
220
|
-
method: 'PUT',
|
|
221
|
-
headers: {
|
|
222
|
-
'netlify-token': token,
|
|
223
|
-
},
|
|
224
|
-
body: JSON.stringify({
|
|
225
|
-
name,
|
|
226
|
-
description,
|
|
227
|
-
hostSiteId: siteId,
|
|
228
|
-
// @ts-expect-error TS(7005) FIXME: Variable 'localScopes' implicitly has an 'any[]' t... Remove this comment to see the full error message
|
|
229
|
-
scopes: localScopes.join(','),
|
|
230
|
-
}),
|
|
231
|
-
}).then(async (res) => {
|
|
232
|
-
const response = await res.json();
|
|
233
|
-
return { updateResponse: response, statusCode: res.status };
|
|
234
|
-
});
|
|
235
|
-
if (statusCode !== 200) {
|
|
236
|
-
log(chalk.red(`There was an error updating the integration: ${updateResponse}`), chalk.red('Please try again. If the problem persists, please contact support.'));
|
|
237
|
-
exit(1);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
else {
|
|
241
|
-
const useRegisteredScopesPrompt = await inquirer.prompt([
|
|
242
|
-
{
|
|
243
|
-
type: 'confirm',
|
|
244
|
-
name: 'useRegisteredScopes',
|
|
245
|
-
message: `Do you want to save the scopes registered for your integration in your local configuration file?`,
|
|
246
|
-
default: false,
|
|
247
|
-
},
|
|
248
|
-
]);
|
|
249
|
-
if (useRegisteredScopesPrompt.useRegisteredScopes) {
|
|
250
|
-
// Use the scopes that are already registered
|
|
251
|
-
log(chalk.white('Saving the currently registered scopes to the integration.yaml file.'));
|
|
252
|
-
scopesToWrite = formatScopesToWrite(registeredIntegrationScopes);
|
|
253
|
-
}
|
|
254
|
-
if (!useRegisteredScopesPrompt.useRegisteredScopes && options.prod) {
|
|
255
|
-
log(chalk.red('Unable to deploy your integration to production without updating the registered scopes.'));
|
|
256
|
-
exit(1);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
const updatedIntegrationConfig = yaml.dump({
|
|
260
|
-
config: { name, description, slug: integrationSlug, scopes: scopesToWrite },
|
|
261
|
-
});
|
|
262
|
-
const filePath = resolve(workingDir, 'integration.yaml');
|
|
263
|
-
await fs.promises.writeFile(filePath, updatedIntegrationConfig);
|
|
264
|
-
log(chalk.yellow('Changes to the integration.yaml file are complete. Please commit and push these changes.'));
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
const possibleFiles = ['integration.yaml', 'integration.yml', 'integration.netlify.yaml', 'integration.netlify.yml'];
|
|
268
|
-
const IntegrationConfigurationSchema = z.object({
|
|
269
|
-
name: z.string().optional(),
|
|
270
|
-
description: z.string().optional(),
|
|
271
|
-
slug: z.string().regex(/^[a-z\d-]+$/, 'slug must be lowercase with dashes'),
|
|
272
|
-
scopes: z
|
|
273
|
-
.object({
|
|
274
|
-
all: z.boolean().optional(),
|
|
275
|
-
site: z.array(z.enum(['read', 'write'])).optional(),
|
|
276
|
-
env: z.array(z.enum(['read', 'write', 'delete'])).optional(),
|
|
277
|
-
user: z.array(z.enum(['read', 'write'])).optional(),
|
|
278
|
-
})
|
|
279
|
-
.optional(),
|
|
280
|
-
});
|
|
281
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'workingDir' implicitly has an 'any' typ... Remove this comment to see the full error message
|
|
282
|
-
const getConfigurationFile = (workingDir) => {
|
|
283
|
-
const pwd = workingDir;
|
|
284
|
-
const fileName = possibleFiles.find((configFileName) => fs.existsSync(resolve(pwd, configFileName)));
|
|
285
|
-
return fileName;
|
|
286
|
-
};
|
|
287
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'workingDir' implicitly has an 'any' typ... Remove this comment to see the full error message
|
|
288
|
-
export const getConfiguration = (workingDir) => {
|
|
289
|
-
const pwd = workingDir;
|
|
290
|
-
const fileName = getConfigurationFile(workingDir);
|
|
291
|
-
if (!fileName) {
|
|
292
|
-
throw new Error('No configuration file found');
|
|
293
|
-
}
|
|
294
|
-
try {
|
|
295
|
-
const { config } = yaml.load(fs.readFileSync(resolve(pwd, fileName), 'utf-8'));
|
|
296
|
-
if (!config) {
|
|
297
|
-
throw new Error('No configuration found');
|
|
298
|
-
}
|
|
299
|
-
const parseResult = IntegrationConfigurationSchema.safeParse(config);
|
|
300
|
-
if (!parseResult.success) {
|
|
301
|
-
console.error(parseResult.error.message);
|
|
302
|
-
throw new Error('Invalid Configuration');
|
|
303
|
-
}
|
|
304
|
-
return config;
|
|
305
|
-
}
|
|
306
|
-
catch (error) {
|
|
307
|
-
console.error(error);
|
|
308
|
-
console.error(`No configuration found in ${fileName} in ${pwd}`);
|
|
309
|
-
exit(1);
|
|
310
|
-
}
|
|
311
|
-
};
|
|
312
|
-
export const deploy = async (options, command) => {
|
|
313
|
-
const { api, cachedConfig, site, siteInfo } = command.netlify;
|
|
314
|
-
const { id: siteId } = site;
|
|
315
|
-
const [token] = await getToken();
|
|
316
|
-
const workingDir = resolve(command.workingDir);
|
|
317
|
-
const buildOptions = await getBuildOptions({
|
|
318
|
-
cachedConfig,
|
|
319
|
-
packagePath: command.workspacePackage,
|
|
320
|
-
currentDir: command.workingDir,
|
|
321
|
-
token,
|
|
322
|
-
// @ts-expect-error TS(2740)
|
|
323
|
-
options,
|
|
324
|
-
});
|
|
325
|
-
// Confirm that a site is linked and that the user is logged in
|
|
326
|
-
checkOptions(buildOptions);
|
|
327
|
-
const { description, name, scopes, slug } = await getConfiguration(command.workingDir);
|
|
328
|
-
const localIntegrationConfig = { name, description, scopes, slug };
|
|
329
|
-
const headers = token ? { 'netlify-token': token } : undefined;
|
|
330
|
-
// @ts-expect-error TS(2345) FIXME: Argument of type '{ api: any; site: any; siteInfo:... Remove this comment to see the full error message
|
|
331
|
-
const { accountId } = await getSiteInformation({
|
|
332
|
-
api,
|
|
333
|
-
site,
|
|
334
|
-
siteInfo,
|
|
335
|
-
});
|
|
336
|
-
const { body: registeredIntegration, statusCode } = await fetch(`${getIntegrationAPIUrl()}/${accountId}/integrations?site_id=${siteId}`, {
|
|
337
|
-
headers,
|
|
338
|
-
}).then(async (res) => {
|
|
339
|
-
const body = await res.json();
|
|
340
|
-
return { body, statusCode: res.status };
|
|
341
|
-
});
|
|
342
|
-
// The integration is registered on the remote
|
|
343
|
-
statusCode === 200
|
|
344
|
-
? await updateIntegration(workingDir, options, siteId, accountId, localIntegrationConfig, token, registeredIntegration)
|
|
345
|
-
: await registerIntegration(workingDir, siteId, accountId, localIntegrationConfig, token);
|
|
346
|
-
// Set the prod flag to true if the integration is being initially registered because we don't want the user
|
|
347
|
-
// to be in a weird state where the card is appearing in the integrations list but there's no production
|
|
348
|
-
// version of the integration deployed
|
|
349
|
-
options = statusCode === 200 ? options : { ...options, prod: true };
|
|
350
|
-
// Deploy the integration to that site
|
|
351
|
-
await siteDeploy(options, command);
|
|
352
|
-
log(`${chalk.cyanBright.bold(`Your integration has been deployed. Next step is to enable it for a team or site.`)} https://ntl.fyi/create-private-integration`);
|
|
353
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/integration/index.ts"],"names":[],"mappings":"AAIA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAM5C,eAAO,MAAM,8BAA8B,YAAa,WAAW,SAalE,CAAA;AAED,eAAO,MAAM,wBAAwB,YAAa,WAAW,gBAQ5D,CAAA"}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { env } from 'process';
|
|
2
|
-
const integrations = (options, command) => {
|
|
3
|
-
command.help();
|
|
4
|
-
};
|
|
5
|
-
export const createIntegrationDeployCommand = (program) => {
|
|
6
|
-
program
|
|
7
|
-
.command('integration:deploy')
|
|
8
|
-
.alias('int:deploy')
|
|
9
|
-
.description('Register, build, and deploy a private integration on Netlify')
|
|
10
|
-
.option('-p, --prod', 'Deploy to production', false)
|
|
11
|
-
.option('-b, --build', 'Build the integration', false)
|
|
12
|
-
.option('-a, --auth <token>', 'Netlify auth token to deploy with', env.NETLIFY_AUTH_TOKEN)
|
|
13
|
-
.option('-s, --site <name-or-id>', 'A site name or ID to deploy to', env.NETLIFY_SITE_ID)
|
|
14
|
-
.action(async (options, command) => {
|
|
15
|
-
const { deploy } = await import('./deploy.js');
|
|
16
|
-
await deploy(options, command);
|
|
17
|
-
});
|
|
18
|
-
};
|
|
19
|
-
export const createIntegrationCommand = (program) => {
|
|
20
|
-
createIntegrationDeployCommand(program);
|
|
21
|
-
return program
|
|
22
|
-
.command('integration')
|
|
23
|
-
.alias('int')
|
|
24
|
-
.description('Manage Netlify Integrations built with the Netlify SDK')
|
|
25
|
-
.action(integrations);
|
|
26
|
-
};
|