netlify-cli 17.3.1 → 17.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -139
- package/npm-shrinkwrap.json +82 -82
- package/package.json +16 -15
- package/src/commands/addons/addons-auth.mjs +27 -30
- package/src/commands/addons/addons-config.mjs +145 -154
- package/src/commands/addons/addons-create.mjs +94 -108
- package/src/commands/addons/addons-delete.mjs +36 -41
- package/src/commands/addons/addons-list.mjs +38 -42
- package/src/commands/addons/addons.mjs +26 -28
- package/src/commands/addons/index.mjs +1 -1
- package/src/commands/api/api.mjs +45 -53
- package/src/commands/api/index.mjs +1 -1
- package/src/commands/base-command.mjs +597 -684
- package/src/commands/blobs/blobs-delete.mjs +35 -0
- package/src/commands/blobs/blobs-get.mjs +44 -0
- package/src/commands/blobs/blobs-list.mjs +48 -0
- package/src/commands/blobs/blobs-set.mjs +54 -0
- package/src/commands/blobs/blobs.mjs +32 -0
- package/src/commands/blobs/index.mjs +1 -0
- package/src/commands/build/build.mjs +55 -67
- package/src/commands/build/index.mjs +1 -1
- package/src/commands/completion/completion.mjs +41 -46
- package/src/commands/completion/index.mjs +1 -1
- package/src/commands/deploy/deploy.mjs +675 -710
- package/src/commands/deploy/index.mjs +1 -1
- package/src/commands/dev/dev-exec.mjs +20 -32
- package/src/commands/dev/dev.mjs +217 -302
- package/src/commands/dev/index.mjs +1 -1
- package/src/commands/dev/types.d.ts +30 -0
- package/src/commands/env/env-clone.mjs +157 -184
- package/src/commands/env/env-get.mjs +49 -68
- package/src/commands/env/env-import.mjs +100 -119
- package/src/commands/env/env-list.mjs +104 -129
- package/src/commands/env/env-set.mjs +160 -185
- package/src/commands/env/env-unset.mjs +104 -122
- package/src/commands/env/env.mjs +28 -30
- package/src/commands/env/index.mjs +1 -1
- package/src/commands/functions/functions-build.mjs +29 -41
- package/src/commands/functions/functions-create.mjs +533 -601
- package/src/commands/functions/functions-invoke.mjs +193 -216
- package/src/commands/functions/functions-list.mjs +45 -55
- package/src/commands/functions/functions-serve.mjs +51 -61
- package/src/commands/functions/functions.mjs +26 -32
- package/src/commands/functions/index.mjs +1 -1
- package/src/commands/index.mjs +2 -2
- package/src/commands/init/index.mjs +1 -1
- package/src/commands/init/init.mjs +138 -167
- package/src/commands/integration/deploy.mjs +337 -399
- package/src/commands/integration/index.mjs +12 -13
- package/src/commands/link/index.mjs +1 -1
- package/src/commands/link/link.mjs +298 -317
- package/src/commands/lm/index.mjs +1 -1
- package/src/commands/lm/lm-info.mjs +23 -31
- package/src/commands/lm/lm-install.mjs +13 -17
- package/src/commands/lm/lm-setup.mjs +80 -84
- package/src/commands/lm/lm-uninstall.mjs +7 -12
- package/src/commands/lm/lm.mjs +18 -22
- package/src/commands/login/index.mjs +1 -1
- package/src/commands/login/login.mjs +35 -41
- package/src/commands/logout/index.mjs +1 -1
- package/src/commands/logout/logout.mjs +25 -31
- package/src/commands/main.mjs +166 -201
- package/src/commands/open/index.mjs +1 -1
- package/src/commands/open/open-admin.mjs +15 -18
- package/src/commands/open/open-site.mjs +16 -19
- package/src/commands/open/open.mjs +24 -27
- package/src/commands/recipes/common.mjs +23 -34
- package/src/commands/recipes/index.mjs +1 -1
- package/src/commands/recipes/recipes-list.mjs +13 -20
- package/src/commands/recipes/recipes.mjs +59 -72
- package/src/commands/serve/index.mjs +1 -1
- package/src/commands/serve/serve.mjs +142 -189
- package/src/commands/sites/index.mjs +2 -2
- package/src/commands/sites/sites-create-template.mjs +214 -236
- package/src/commands/sites/sites-create.mjs +145 -157
- package/src/commands/sites/sites-delete.mjs +75 -81
- package/src/commands/sites/sites-list.mjs +63 -66
- package/src/commands/sites/sites.mjs +18 -20
- package/src/commands/status/index.mjs +1 -1
- package/src/commands/status/status-hooks.mjs +32 -34
- package/src/commands/status/status.mjs +99 -106
- package/src/commands/switch/index.mjs +1 -1
- package/src/commands/switch/switch.mjs +32 -37
- package/src/commands/types.d.ts +31 -0
- package/src/commands/unlink/index.mjs +1 -1
- package/src/commands/unlink/unlink.mjs +23 -29
- package/src/commands/watch/index.mjs +1 -1
- package/src/commands/watch/watch.mjs +91 -105
- package/src/functions-templates/javascript/hello/{{name}}.js +2 -3
- package/src/lib/account.mjs +4 -5
- package/src/lib/api.mjs +22 -20
- package/src/lib/blobs/blobs.mjs +36 -45
- package/src/lib/build.mjs +82 -85
- package/src/lib/completion/constants.mjs +2 -4
- package/src/lib/completion/generate-autocompletion.mjs +33 -36
- package/src/lib/completion/get-autocompletion.mjs +31 -35
- package/src/lib/completion/index.mjs +1 -1
- package/src/lib/completion/script.mjs +12 -19
- package/src/lib/edge-functions/bootstrap.mjs +3 -5
- package/src/lib/edge-functions/consts.mjs +9 -10
- package/src/lib/edge-functions/deploy.mjs +28 -34
- package/src/lib/edge-functions/editor-helper.mjs +29 -42
- package/src/lib/edge-functions/headers.mjs +24 -26
- package/src/lib/edge-functions/internal.mjs +38 -44
- package/src/lib/edge-functions/proxy.mjs +229 -228
- package/src/lib/edge-functions/registry.mjs +473 -574
- package/src/lib/exec-fetcher.mjs +115 -122
- package/src/lib/fs.mjs +28 -27
- package/src/lib/functions/background.mjs +16 -20
- package/src/lib/functions/config.mjs +12 -9
- package/src/lib/functions/form-submissions-handler.mjs +143 -149
- package/src/lib/functions/local-proxy.mjs +40 -44
- package/src/lib/functions/memoized-build.mjs +19 -21
- package/src/lib/functions/netlify-function.mjs +269 -249
- package/src/lib/functions/registry.mjs +509 -568
- package/src/lib/functions/runtimes/go/index.mjs +62 -71
- package/src/lib/functions/runtimes/index.mjs +8 -15
- package/src/lib/functions/runtimes/js/builders/netlify-lambda.mjs +55 -64
- package/src/lib/functions/runtimes/js/builders/zisi.mjs +135 -154
- package/src/lib/functions/runtimes/js/constants.mjs +1 -1
- package/src/lib/functions/runtimes/js/index.mjs +92 -109
- package/src/lib/functions/runtimes/js/worker.mjs +43 -45
- package/src/lib/functions/runtimes/rust/index.mjs +64 -73
- package/src/lib/functions/scheduled.mjs +70 -88
- package/src/lib/functions/server.mjs +269 -327
- package/src/lib/functions/synchronous.mjs +118 -147
- package/src/lib/functions/utils.mjs +38 -46
- package/src/lib/geo-location.mjs +69 -81
- package/src/lib/http-agent.mjs +87 -90
- package/src/lib/images/proxy.mjs +97 -89
- package/src/lib/log.mjs +6 -9
- package/src/lib/path.mjs +2 -1
- package/src/lib/render-error-template.mjs +19 -20
- package/src/lib/settings.mjs +17 -19
- package/src/lib/spinner.mjs +21 -23
- package/src/lib/string.mjs +4 -2
- package/src/recipes/vscode/index.mjs +69 -85
- package/src/recipes/vscode/settings.mjs +53 -58
- package/src/utils/addons/compare.mjs +31 -32
- package/src/utils/addons/diffs/index.mjs +16 -17
- package/src/utils/addons/diffs/options.mjs +99 -101
- package/src/utils/addons/prepare.mjs +100 -97
- package/src/utils/addons/prompts.mjs +73 -76
- package/src/utils/addons/render.mjs +33 -36
- package/src/utils/addons/validation.mjs +19 -15
- package/src/utils/banner.mjs +11 -16
- package/src/utils/build-info.mjs +65 -66
- package/src/utils/command-helpers.mjs +185 -199
- package/src/utils/create-deferred.mjs +9 -12
- package/src/utils/create-stream-promise.mjs +54 -47
- package/src/utils/deploy/constants.mjs +9 -11
- package/src/utils/deploy/deploy-site.mjs +162 -182
- package/src/utils/deploy/hash-config.mjs +21 -21
- package/src/utils/deploy/hash-files.mjs +34 -38
- package/src/utils/deploy/hash-fns.mjs +149 -154
- package/src/utils/deploy/hasher-segments.mjs +58 -52
- package/src/utils/deploy/upload-files.mjs +99 -113
- package/src/utils/deploy/util.mjs +85 -91
- package/src/utils/detect-server-settings.mjs +236 -268
- package/src/utils/dev.mjs +163 -178
- package/src/utils/dot-env.mjs +37 -42
- package/src/utils/env/index.mjs +148 -148
- package/src/utils/execa.mjs +9 -13
- package/src/utils/feature-flags.mjs +6 -5
- package/src/utils/framework-server.mjs +43 -52
- package/src/utils/functions/constants.mjs +1 -1
- package/src/utils/functions/functions.mjs +30 -40
- package/src/utils/functions/get-functions.mjs +28 -29
- package/src/utils/functions/index.mjs +3 -3
- package/src/utils/get-global-config.mjs +33 -36
- package/src/utils/get-package-json.mjs +14 -15
- package/src/utils/get-repo-data.mjs +54 -64
- package/src/utils/get-site.mjs +14 -14
- package/src/utils/gh-auth.mjs +79 -100
- package/src/utils/gitignore.mjs +37 -40
- package/src/utils/headers.mjs +33 -35
- package/src/utils/hooks/requires-site-info.mjs +26 -22
- package/src/utils/init/config-github.mjs +207 -219
- package/src/utils/init/config-manual.mjs +83 -100
- package/src/utils/init/config.mjs +25 -26
- package/src/utils/init/node-version.mjs +23 -30
- package/src/utils/init/plugins.mjs +12 -8
- package/src/utils/init/utils.mjs +152 -172
- package/src/utils/live-tunnel.mjs +118 -141
- package/src/utils/lm/install.mjs +220 -259
- package/src/utils/lm/requirements.mjs +54 -63
- package/src/utils/lm/steps.mjs +31 -31
- package/src/utils/lm/ui.mjs +13 -20
- package/src/utils/open-browser.mjs +31 -32
- package/src/utils/parse-raw-flags.mjs +39 -35
- package/src/utils/proxy-server.mjs +84 -71
- package/src/utils/proxy.mjs +696 -750
- package/src/utils/read-repo-url.mjs +48 -47
- package/src/utils/redirects.mjs +49 -49
- package/src/utils/request-id.mjs +2 -4
- package/src/utils/rules-proxy.mjs +96 -100
- package/src/utils/run-build.mjs +109 -132
- package/src/utils/shell.mjs +99 -106
- package/src/utils/sign-redirect.mjs +14 -14
- package/src/utils/sites/utils.mjs +48 -55
- package/src/utils/state-config.mjs +101 -101
- package/src/utils/static-server.mjs +28 -34
- package/src/utils/telemetry/index.mjs +2 -2
- package/src/utils/telemetry/report-error.mjs +45 -49
- package/src/utils/telemetry/request.mjs +36 -43
- package/src/utils/telemetry/telemetry.mjs +90 -105
- package/src/utils/telemetry/utils.mjs +5 -6
- package/src/utils/telemetry/validation.mjs +55 -53
- package/src/utils/types.d.ts +46 -0
- package/src/utils/validation.mjs +10 -13
|
@@ -1,443 +1,381 @@
|
|
|
1
|
-
import fs from 'fs'
|
|
2
|
-
import { resolve } from 'path'
|
|
3
|
-
import { exit, env } from 'process'
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import yaml from 'js-yaml'
|
|
7
|
-
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
import { getBuildOptions } from '../../lib/build.mjs'
|
|
11
|
-
import { getToken, chalk, log } from '../../utils/command-helpers.mjs'
|
|
12
|
-
import { getSiteInformation } from '../../utils/dev.mjs'
|
|
13
|
-
import { checkOptions } from '../build/build.mjs'
|
|
14
|
-
import { deploy as siteDeploy } from '../deploy/deploy.mjs'
|
|
15
|
-
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { resolve } from 'path';
|
|
3
|
+
import { exit, env } from 'process';
|
|
4
|
+
import inquirer from 'inquirer';
|
|
5
|
+
// @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
|
|
6
|
+
import yaml from 'js-yaml';
|
|
7
|
+
// @ts-expect-error TS(7016) FIXME: Could not find a declaration file for module 'node... Remove this comment to see the full error message
|
|
8
|
+
import fetch from 'node-fetch';
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { getBuildOptions } from '../../lib/build.mjs';
|
|
11
|
+
import { getToken, chalk, log } from '../../utils/command-helpers.mjs';
|
|
12
|
+
import { getSiteInformation } from '../../utils/dev.mjs';
|
|
13
|
+
import { checkOptions } from '../build/build.mjs';
|
|
14
|
+
import { deploy as siteDeploy } from '../deploy/deploy.mjs';
|
|
16
15
|
function getIntegrationAPIUrl() {
|
|
17
|
-
|
|
16
|
+
return env.INTEGRATION_URL || 'https://api.netlifysdk.com';
|
|
18
17
|
}
|
|
19
|
-
|
|
18
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'localScopes' implicitly has an 'any' ty... Remove this comment to see the full error message
|
|
20
19
|
export function areScopesEqual(localScopes, remoteScopes) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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));
|
|
26
25
|
}
|
|
27
|
-
|
|
26
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'localScopes' implicitly has an 'any' ty... Remove this comment to see the full error message
|
|
28
27
|
function logScopeConfirmationMessage(localScopes, remoteScopes) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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.'));
|
|
38
37
|
}
|
|
39
|
-
|
|
38
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'registeredIntegrationScopes' implicitly... Remove this comment to see the full error message
|
|
40
39
|
function formatScopesToWrite(registeredIntegrationScopes) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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
|
+
}
|
|
53
56
|
}
|
|
54
|
-
|
|
55
|
-
return scopesToWrite
|
|
57
|
+
return scopesToWrite;
|
|
56
58
|
}
|
|
57
|
-
|
|
59
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'scopes' implicitly has an 'any' type.
|
|
58
60
|
function formatScopesForRemote(scopes) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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(',');
|
|
72
76
|
}
|
|
73
|
-
|
|
77
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'name' implicitly has an 'any' type.
|
|
74
78
|
function verifyRequiredFieldsAreInConfig(name, description, scopes, integrationLevel) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
)}. Please add a these fields as an entry to the integration.yaml file and try again.`,
|
|
95
|
-
),
|
|
96
|
-
)
|
|
97
|
-
log(
|
|
98
|
-
chalk.yellow(
|
|
99
|
-
'For more information on the required fields, please see the documentation: https://ntl.fyi/create-private-integration',
|
|
100
|
-
),
|
|
101
|
-
)
|
|
102
|
-
return false
|
|
103
|
-
}
|
|
104
|
-
return true
|
|
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 (!integrationLevel) {
|
|
90
|
+
missingFields.push('integrationLevel');
|
|
91
|
+
}
|
|
92
|
+
if (missingFields.length !== 0) {
|
|
93
|
+
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.`));
|
|
94
|
+
log(chalk.yellow('For more information on the required fields, please see the documentation: https://ntl.fyi/create-private-integration'));
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
return true;
|
|
105
98
|
}
|
|
106
|
-
|
|
99
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'workingDir' implicitly has an 'any' typ... Remove this comment to see the full error message
|
|
107
100
|
// eslint-disable-next-line max-params
|
|
108
101
|
export async function registerIntegration(workingDir, siteId, accountId, localIntegrationConfig, token) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
{
|
|
113
|
-
type: 'confirm',
|
|
114
|
-
name: 'registerIntegration',
|
|
115
|
-
message: `Would you like to register this site as a private integration now?`,
|
|
116
|
-
default: false,
|
|
117
|
-
},
|
|
118
|
-
])
|
|
119
|
-
|
|
120
|
-
if (!registerPrompt.registerIntegration) {
|
|
121
|
-
log(
|
|
122
|
-
chalk.white(
|
|
123
|
-
"Cancelling deployment. Please run 'netlify int deploy' again when you are ready to register the integration.",
|
|
124
|
-
),
|
|
125
|
-
)
|
|
126
|
-
log(
|
|
127
|
-
chalk.white(
|
|
128
|
-
"You can also register the integration through the Netlify UI on the 'Integrations' > 'Create private integration' page",
|
|
129
|
-
),
|
|
130
|
-
)
|
|
131
|
-
exit(1)
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
if (!verifyRequiredFieldsAreInConfig(name, description, scopes, integrationLevel)) {
|
|
135
|
-
exit(1)
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
log(chalk.white('Registering the integration...'))
|
|
139
|
-
|
|
140
|
-
const { body, statusCode } = await fetch(`${getIntegrationAPIUrl()}/${accountId}/integrations`, {
|
|
141
|
-
method: 'POST',
|
|
142
|
-
headers: {
|
|
143
|
-
'netlify-token': token,
|
|
144
|
-
},
|
|
145
|
-
body: JSON.stringify({
|
|
146
|
-
name,
|
|
147
|
-
slug,
|
|
148
|
-
description,
|
|
149
|
-
hostSiteId: siteId,
|
|
150
|
-
scopes: formatScopesForRemote(scopes),
|
|
151
|
-
integrationLevel,
|
|
152
|
-
}),
|
|
153
|
-
}).then(async (res) => {
|
|
154
|
-
const response = await res.json()
|
|
155
|
-
return { body: response, statusCode: res.status }
|
|
156
|
-
})
|
|
157
|
-
|
|
158
|
-
if (statusCode !== 201) {
|
|
159
|
-
log(chalk.red(`There was an error registering the integration:`))
|
|
160
|
-
log()
|
|
161
|
-
log(chalk.red(`-----------------------------------------------`))
|
|
162
|
-
log(chalk.red(body.msg))
|
|
163
|
-
log(chalk.red(`-----------------------------------------------`))
|
|
164
|
-
log()
|
|
165
|
-
log(chalk.red(`Please try again. If the problem persists, please contact support.`))
|
|
166
|
-
exit(1)
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
log(chalk.green(`Successfully registered the integration with the slug: ${body.slug}`))
|
|
170
|
-
|
|
171
|
-
const updatedIntegrationConfig = yaml.dump({
|
|
172
|
-
config: { name, description, slug: body.slug, scopes, integrationLevel },
|
|
173
|
-
})
|
|
174
|
-
|
|
175
|
-
const filePath = resolve(workingDir, 'integration.yaml')
|
|
176
|
-
await fs.promises.writeFile(filePath, updatedIntegrationConfig)
|
|
177
|
-
|
|
178
|
-
log(chalk.yellow('Your integration.yaml file has been updated. Please commit and push these changes.'))
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// eslint-disable-next-line max-params
|
|
182
|
-
export async function updateIntegration(
|
|
183
|
-
workingDir,
|
|
184
|
-
options,
|
|
185
|
-
siteId,
|
|
186
|
-
accountId,
|
|
187
|
-
localIntegrationConfig,
|
|
188
|
-
token,
|
|
189
|
-
registeredIntegration,
|
|
190
|
-
) {
|
|
191
|
-
let { description, integrationLevel, name, scopes, slug } = localIntegrationConfig
|
|
192
|
-
|
|
193
|
-
let integrationSlug = slug
|
|
194
|
-
if (slug !== registeredIntegration.slug) {
|
|
195
|
-
// Update the project's integration.yaml file with the remote slug since that will
|
|
196
|
-
// be considered the source of truth and is a value that can't be edited by the user.
|
|
197
|
-
// Let the user know they need to commit and push the changes.
|
|
198
|
-
integrationSlug = registeredIntegration.slug
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
if (!name) {
|
|
202
|
-
// Disabling this lint rule because the destructuring was not assigning the variable correct and leading to a bug
|
|
203
|
-
// eslint-disable-next-line prefer-destructuring
|
|
204
|
-
name = registeredIntegration.name
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
if (!description) {
|
|
208
|
-
// eslint-disable-next-line prefer-destructuring
|
|
209
|
-
description = registeredIntegration.description
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
if (!integrationLevel) {
|
|
213
|
-
// eslint-disable-next-line prefer-destructuring
|
|
214
|
-
integrationLevel = registeredIntegration.integrationLevel
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// This is returned as a comma separated string and will be easier to manage here as an array
|
|
218
|
-
const registeredIntegrationScopes = registeredIntegration.scopes.split(',')
|
|
219
|
-
|
|
220
|
-
const scopeResources = Object.keys(scopes)
|
|
221
|
-
let localScopes = []
|
|
222
|
-
|
|
223
|
-
if (scopeResources.includes('all')) {
|
|
224
|
-
localScopes = ['all']
|
|
225
|
-
} else {
|
|
226
|
-
scopeResources.forEach((resource) => {
|
|
227
|
-
const permissionsRequested = scopes[resource]
|
|
228
|
-
permissionsRequested.forEach((permission) => {
|
|
229
|
-
localScopes.push(`${resource}:${permission}`)
|
|
230
|
-
})
|
|
231
|
-
})
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
if (!areScopesEqual(localScopes, registeredIntegrationScopes)) {
|
|
235
|
-
logScopeConfirmationMessage(localScopes, registeredIntegrationScopes)
|
|
236
|
-
|
|
237
|
-
const scopePrompt = await inquirer.prompt([
|
|
238
|
-
{
|
|
239
|
-
type: 'confirm',
|
|
240
|
-
name: 'updateScopes',
|
|
241
|
-
message: `Do you want to update the scopes?`,
|
|
242
|
-
default: false,
|
|
243
|
-
},
|
|
244
|
-
])
|
|
245
|
-
|
|
246
|
-
let scopesToWrite
|
|
247
|
-
if (scopePrompt.updateScopes) {
|
|
248
|
-
// Update the scopes in remote
|
|
249
|
-
scopesToWrite = scopes
|
|
250
|
-
const { statusCode, updateResponse } = await fetch(
|
|
251
|
-
`${getIntegrationAPIUrl()}/${accountId}/integrations/${integrationSlug}`,
|
|
102
|
+
const { description, integrationLevel, name, scopes, slug } = localIntegrationConfig;
|
|
103
|
+
log(chalk.yellow(`An integration associated with the site ID ${siteId} is not registered.`));
|
|
104
|
+
const registerPrompt = await inquirer.prompt([
|
|
252
105
|
{
|
|
253
|
-
|
|
254
|
-
|
|
106
|
+
type: 'confirm',
|
|
107
|
+
name: 'registerIntegration',
|
|
108
|
+
message: `Would you like to register this site as a private integration now?`,
|
|
109
|
+
default: false,
|
|
110
|
+
},
|
|
111
|
+
]);
|
|
112
|
+
if (!registerPrompt.registerIntegration) {
|
|
113
|
+
log(chalk.white("Cancelling deployment. Please run 'netlify int deploy' again when you are ready to register the integration."));
|
|
114
|
+
log(chalk.white("You can also register the integration through the Netlify UI on the 'Integrations' > 'Create private integration' page"));
|
|
115
|
+
exit(1);
|
|
116
|
+
}
|
|
117
|
+
if (!verifyRequiredFieldsAreInConfig(name, description, scopes, integrationLevel)) {
|
|
118
|
+
exit(1);
|
|
119
|
+
}
|
|
120
|
+
log(chalk.white('Registering the integration...'));
|
|
121
|
+
const { body, statusCode } = await fetch(`${getIntegrationAPIUrl()}/${accountId}/integrations`, {
|
|
122
|
+
method: 'POST',
|
|
123
|
+
headers: {
|
|
255
124
|
'netlify-token': token,
|
|
256
|
-
|
|
257
|
-
|
|
125
|
+
},
|
|
126
|
+
body: JSON.stringify({
|
|
258
127
|
name,
|
|
128
|
+
slug,
|
|
259
129
|
description,
|
|
260
130
|
hostSiteId: siteId,
|
|
261
|
-
scopes:
|
|
131
|
+
scopes: formatScopesForRemote(scopes),
|
|
262
132
|
integrationLevel,
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
const response = await res.json()
|
|
267
|
-
return {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
log(
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
)
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
const useRegisteredScopesPrompt = await inquirer.prompt([
|
|
279
|
-
{
|
|
280
|
-
type: 'confirm',
|
|
281
|
-
name: 'useRegisteredScopes',
|
|
282
|
-
message: `Do you want to save the scopes registered for your integration in your local configuration file?`,
|
|
283
|
-
default: false,
|
|
284
|
-
},
|
|
285
|
-
])
|
|
286
|
-
|
|
287
|
-
if (useRegisteredScopesPrompt.useRegisteredScopes) {
|
|
288
|
-
// Use the scopes that are already registered
|
|
289
|
-
log(chalk.white('Saving the currently registered scopes to the integration.yaml file.'))
|
|
290
|
-
scopesToWrite = formatScopesToWrite(registeredIntegrationScopes)
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
if (!useRegisteredScopesPrompt.useRegisteredScopes && options.prod) {
|
|
294
|
-
log(chalk.red('Unable to deploy your integration to production without updating the registered scopes.'))
|
|
295
|
-
exit(1)
|
|
296
|
-
}
|
|
133
|
+
}),
|
|
134
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'res' implicitly has an 'any' type.
|
|
135
|
+
}).then(async (res) => {
|
|
136
|
+
const response = await res.json();
|
|
137
|
+
return { body: response, statusCode: res.status };
|
|
138
|
+
});
|
|
139
|
+
if (statusCode !== 201) {
|
|
140
|
+
log(chalk.red(`There was an error registering the integration:`));
|
|
141
|
+
log();
|
|
142
|
+
log(chalk.red(`-----------------------------------------------`));
|
|
143
|
+
log(chalk.red(body.msg));
|
|
144
|
+
log(chalk.red(`-----------------------------------------------`));
|
|
145
|
+
log();
|
|
146
|
+
log(chalk.red(`Please try again. If the problem persists, please contact support.`));
|
|
147
|
+
exit(1);
|
|
297
148
|
}
|
|
298
|
-
|
|
149
|
+
log(chalk.green(`Successfully registered the integration with the slug: ${body.slug}`));
|
|
299
150
|
const updatedIntegrationConfig = yaml.dump({
|
|
300
|
-
|
|
301
|
-
})
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
151
|
+
config: { name, description, slug: body.slug, scopes, integrationLevel },
|
|
152
|
+
});
|
|
153
|
+
const filePath = resolve(workingDir, 'integration.yaml');
|
|
154
|
+
await fs.promises.writeFile(filePath, updatedIntegrationConfig);
|
|
155
|
+
log(chalk.yellow('Your integration.yaml file has been updated. Please commit and push these changes.'));
|
|
156
|
+
}
|
|
157
|
+
// eslint-disable-next-line max-params
|
|
158
|
+
export async function updateIntegration(
|
|
159
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'workingDir' implicitly has an 'any' typ... Remove this comment to see the full error message
|
|
160
|
+
workingDir,
|
|
161
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type.
|
|
162
|
+
options,
|
|
163
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'siteId' implicitly has an 'any' type.
|
|
164
|
+
siteId,
|
|
165
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'accountId' implicitly has an 'any' type... Remove this comment to see the full error message
|
|
166
|
+
accountId,
|
|
167
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'localIntegrationConfig' implicitly has ... Remove this comment to see the full error message
|
|
168
|
+
localIntegrationConfig,
|
|
169
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'token' implicitly has an 'any' type.
|
|
170
|
+
token,
|
|
171
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'registeredIntegration' implicitly has a... Remove this comment to see the full error message
|
|
172
|
+
registeredIntegration) {
|
|
173
|
+
let { description, integrationLevel, name, scopes, slug } = localIntegrationConfig;
|
|
174
|
+
let integrationSlug = slug;
|
|
175
|
+
if (slug !== registeredIntegration.slug) {
|
|
176
|
+
// Update the project's integration.yaml file with the remote slug since that will
|
|
177
|
+
// be considered the source of truth and is a value that can't be edited by the user.
|
|
178
|
+
// Let the user know they need to commit and push the changes.
|
|
179
|
+
integrationSlug = registeredIntegration.slug;
|
|
180
|
+
}
|
|
181
|
+
if (!name) {
|
|
182
|
+
// Disabling this lint rule because the destructuring was not assigning the variable correct and leading to a bug
|
|
183
|
+
// eslint-disable-next-line prefer-destructuring
|
|
184
|
+
name = registeredIntegration.name;
|
|
185
|
+
}
|
|
186
|
+
if (!description) {
|
|
187
|
+
// eslint-disable-next-line prefer-destructuring
|
|
188
|
+
description = registeredIntegration.description;
|
|
189
|
+
}
|
|
190
|
+
if (!integrationLevel) {
|
|
191
|
+
// eslint-disable-next-line prefer-destructuring
|
|
192
|
+
integrationLevel = registeredIntegration.integrationLevel;
|
|
193
|
+
}
|
|
194
|
+
// This is returned as a comma separated string and will be easier to manage here as an array
|
|
195
|
+
const registeredIntegrationScopes = registeredIntegration.scopes.split(',');
|
|
196
|
+
const scopeResources = Object.keys(scopes);
|
|
197
|
+
// @ts-expect-error TS(7034) FIXME: Variable 'localScopes' implicitly has type 'any[]'... Remove this comment to see the full error message
|
|
198
|
+
let localScopes = [];
|
|
199
|
+
if (scopeResources.includes('all')) {
|
|
200
|
+
localScopes = ['all'];
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
scopeResources.forEach((resource) => {
|
|
204
|
+
const permissionsRequested = scopes[resource];
|
|
205
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'permission' implicitly has an 'any' typ... Remove this comment to see the full error message
|
|
206
|
+
permissionsRequested.forEach((permission) => {
|
|
207
|
+
localScopes.push(`${resource}:${permission}`);
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
// @ts-expect-error TS(7005) FIXME: Variable 'localScopes' implicitly has an 'any[]' t... Remove this comment to see the full error message
|
|
212
|
+
if (!areScopesEqual(localScopes, registeredIntegrationScopes)) {
|
|
213
|
+
// @ts-expect-error TS(7005) FIXME: Variable 'localScopes' implicitly has an 'any[]' t... Remove this comment to see the full error message
|
|
214
|
+
logScopeConfirmationMessage(localScopes, registeredIntegrationScopes);
|
|
215
|
+
const scopePrompt = await inquirer.prompt([
|
|
216
|
+
{
|
|
217
|
+
type: 'confirm',
|
|
218
|
+
name: 'updateScopes',
|
|
219
|
+
message: `Do you want to update the scopes?`,
|
|
220
|
+
default: false,
|
|
221
|
+
},
|
|
222
|
+
]);
|
|
223
|
+
let scopesToWrite;
|
|
224
|
+
if (scopePrompt.updateScopes) {
|
|
225
|
+
// Update the scopes in remote
|
|
226
|
+
scopesToWrite = scopes;
|
|
227
|
+
const { statusCode, updateResponse } = await fetch(`${getIntegrationAPIUrl()}/${accountId}/integrations/${integrationSlug}`, {
|
|
228
|
+
method: 'PUT',
|
|
229
|
+
headers: {
|
|
230
|
+
'netlify-token': token,
|
|
231
|
+
},
|
|
232
|
+
body: JSON.stringify({
|
|
233
|
+
name,
|
|
234
|
+
description,
|
|
235
|
+
hostSiteId: siteId,
|
|
236
|
+
// @ts-expect-error TS(7005) FIXME: Variable 'localScopes' implicitly has an 'any[]' t... Remove this comment to see the full error message
|
|
237
|
+
scopes: localScopes.join(','),
|
|
238
|
+
integrationLevel,
|
|
239
|
+
}),
|
|
240
|
+
}).then(async (res) => {
|
|
241
|
+
const response = await res.json();
|
|
242
|
+
return { updateResponse: response, statusCode: res.status };
|
|
243
|
+
});
|
|
244
|
+
if (statusCode !== 200) {
|
|
245
|
+
log(chalk.red(`There was an error updating the integration: ${updateResponse}`), chalk.red('Please try again. If the problem persists, please contact support.'));
|
|
246
|
+
exit(1);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
const useRegisteredScopesPrompt = await inquirer.prompt([
|
|
251
|
+
{
|
|
252
|
+
type: 'confirm',
|
|
253
|
+
name: 'useRegisteredScopes',
|
|
254
|
+
message: `Do you want to save the scopes registered for your integration in your local configuration file?`,
|
|
255
|
+
default: false,
|
|
256
|
+
},
|
|
257
|
+
]);
|
|
258
|
+
if (useRegisteredScopesPrompt.useRegisteredScopes) {
|
|
259
|
+
// Use the scopes that are already registered
|
|
260
|
+
log(chalk.white('Saving the currently registered scopes to the integration.yaml file.'));
|
|
261
|
+
scopesToWrite = formatScopesToWrite(registeredIntegrationScopes);
|
|
262
|
+
}
|
|
263
|
+
if (!useRegisteredScopesPrompt.useRegisteredScopes && options.prod) {
|
|
264
|
+
log(chalk.red('Unable to deploy your integration to production without updating the registered scopes.'));
|
|
265
|
+
exit(1);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
const updatedIntegrationConfig = yaml.dump({
|
|
269
|
+
config: { name, description, slug: integrationSlug, scopes: scopesToWrite, integrationLevel },
|
|
270
|
+
});
|
|
271
|
+
const filePath = resolve(workingDir, 'integration.yaml');
|
|
272
|
+
await fs.promises.writeFile(filePath, updatedIntegrationConfig);
|
|
273
|
+
log(chalk.yellow('Changes to the integration.yaml file are complete. Please commit and push these changes.'));
|
|
274
|
+
}
|
|
308
275
|
}
|
|
309
|
-
|
|
310
|
-
const possibleFiles = ['integration.yaml', 'integration.yml', 'integration.netlify.yaml', 'integration.netlify.yml']
|
|
276
|
+
const possibleFiles = ['integration.yaml', 'integration.yml', 'integration.netlify.yaml', 'integration.netlify.yml'];
|
|
311
277
|
const IntegrationConfigurationSchema = z.object({
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
278
|
+
name: z.string().optional(),
|
|
279
|
+
description: z.string().optional(),
|
|
280
|
+
slug: z.string().regex(/^[a-z\d-]+$/, 'slug must be lowercase with dashes'),
|
|
281
|
+
scopes: z
|
|
282
|
+
.object({
|
|
283
|
+
all: z.boolean().optional(),
|
|
284
|
+
site: z.array(z.enum(['read', 'write'])).optional(),
|
|
285
|
+
env: z.array(z.enum(['read', 'write', 'delete'])).optional(),
|
|
286
|
+
user: z.array(z.enum(['read', 'write'])).optional(),
|
|
321
287
|
})
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
})
|
|
325
|
-
|
|
288
|
+
.optional(),
|
|
289
|
+
integrationLevel: z.enum(['site', 'team', 'team-and-site']).optional(),
|
|
290
|
+
});
|
|
291
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'workingDir' implicitly has an 'any' typ... Remove this comment to see the full error message
|
|
326
292
|
const getConfigurationFile = (workingDir) => {
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
}
|
|
333
|
-
|
|
293
|
+
const pwd = workingDir;
|
|
294
|
+
const fileName = possibleFiles.find((configFileName) => fs.existsSync(resolve(pwd, configFileName)));
|
|
295
|
+
return fileName;
|
|
296
|
+
};
|
|
297
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'workingDir' implicitly has an 'any' typ... Remove this comment to see the full error message
|
|
334
298
|
export const getConfiguration = (workingDir) => {
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
if (!fileName) {
|
|
340
|
-
throw new Error('No configuration file found')
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
try {
|
|
344
|
-
const { config } = yaml.load(fs.readFileSync(resolve(pwd, fileName), 'utf-8'))
|
|
345
|
-
|
|
346
|
-
if (!config) {
|
|
347
|
-
throw new Error('No configuration found')
|
|
299
|
+
const pwd = workingDir;
|
|
300
|
+
const fileName = getConfigurationFile(workingDir);
|
|
301
|
+
if (!fileName) {
|
|
302
|
+
throw new Error('No configuration file found');
|
|
348
303
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
304
|
+
try {
|
|
305
|
+
const { config } = yaml.load(fs.readFileSync(resolve(pwd, fileName), 'utf-8'));
|
|
306
|
+
if (!config) {
|
|
307
|
+
throw new Error('No configuration found');
|
|
308
|
+
}
|
|
309
|
+
const parseResult = IntegrationConfigurationSchema.safeParse(config);
|
|
310
|
+
if (!parseResult.success) {
|
|
311
|
+
console.error(parseResult.error.message);
|
|
312
|
+
throw new Error('Invalid Configuration');
|
|
313
|
+
}
|
|
314
|
+
return config;
|
|
355
315
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
}
|
|
363
|
-
}
|
|
316
|
+
catch (error) {
|
|
317
|
+
console.error(error);
|
|
318
|
+
console.error(`No configuration found in ${fileName} in ${pwd}`);
|
|
319
|
+
exit(1);
|
|
320
|
+
}
|
|
321
|
+
};
|
|
364
322
|
/**
|
|
365
323
|
* The deploy command for Netlify Integrations
|
|
366
324
|
* @param {import('commander').OptionValues} options
|
|
367
325
|
* * @param {import('../base-command.mjs').default} command
|
|
368
326
|
*/
|
|
327
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type.
|
|
369
328
|
const deploy = async (options, command) => {
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
cachedConfig
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
})
|
|
381
|
-
|
|
382
|
-
// Confirm that a site is linked and that the user is logged in
|
|
383
|
-
checkOptions(buildOptions)
|
|
384
|
-
|
|
385
|
-
const { description, integrationLevel, name, scopes, slug } = await getConfiguration(command.workingDir)
|
|
386
|
-
const localIntegrationConfig = { name, description, scopes, slug, integrationLevel }
|
|
387
|
-
|
|
388
|
-
const { accountId } = await getSiteInformation({
|
|
389
|
-
api,
|
|
390
|
-
site,
|
|
391
|
-
siteInfo,
|
|
392
|
-
})
|
|
393
|
-
|
|
394
|
-
const { body: registeredIntegration, statusCode } = await fetch(
|
|
395
|
-
`${getIntegrationAPIUrl()}/${accountId}/integrations?site_id=${siteId}`,
|
|
396
|
-
{
|
|
397
|
-
headers: {
|
|
398
|
-
'netlify-token': token,
|
|
399
|
-
},
|
|
400
|
-
},
|
|
401
|
-
).then(async (res) => {
|
|
402
|
-
const body = await res.json()
|
|
403
|
-
return { body, statusCode: res.status }
|
|
404
|
-
})
|
|
405
|
-
|
|
406
|
-
// The integration is registered on the remote
|
|
407
|
-
statusCode === 200
|
|
408
|
-
? await updateIntegration(
|
|
409
|
-
workingDir,
|
|
410
|
-
options,
|
|
411
|
-
siteId,
|
|
412
|
-
accountId,
|
|
413
|
-
localIntegrationConfig,
|
|
329
|
+
const { api, cachedConfig, site, siteInfo } = command.netlify;
|
|
330
|
+
const { id: siteId } = site;
|
|
331
|
+
// @ts-expect-error TS(2554) FIXME: Expected 1 arguments, but got 0.
|
|
332
|
+
const [token] = await getToken();
|
|
333
|
+
const workingDir = resolve(command.workingDir);
|
|
334
|
+
// @ts-expect-error TS(2345) FIXME: Argument of type '{ cachedConfig: any; packagePath... Remove this comment to see the full error message
|
|
335
|
+
const buildOptions = await getBuildOptions({
|
|
336
|
+
cachedConfig,
|
|
337
|
+
packagePath: command.workspacePackage,
|
|
338
|
+
currentDir: command.workingDir,
|
|
414
339
|
token,
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
340
|
+
options,
|
|
341
|
+
});
|
|
342
|
+
// Confirm that a site is linked and that the user is logged in
|
|
343
|
+
checkOptions(buildOptions);
|
|
344
|
+
const { description, integrationLevel, name, scopes, slug } = await getConfiguration(command.workingDir);
|
|
345
|
+
const localIntegrationConfig = { name, description, scopes, slug, integrationLevel };
|
|
346
|
+
// @ts-expect-error TS(2345) FIXME: Argument of type '{ api: any; site: any; siteInfo:... Remove this comment to see the full error message
|
|
347
|
+
const { accountId } = await getSiteInformation({
|
|
348
|
+
api,
|
|
349
|
+
site,
|
|
350
|
+
siteInfo,
|
|
351
|
+
});
|
|
352
|
+
const { body: registeredIntegration, statusCode } = await fetch(`${getIntegrationAPIUrl()}/${accountId}/integrations?site_id=${siteId}`, {
|
|
353
|
+
headers: {
|
|
354
|
+
'netlify-token': token,
|
|
355
|
+
},
|
|
356
|
+
}).then(async (res) => {
|
|
357
|
+
const body = await res.json();
|
|
358
|
+
return { body, statusCode: res.status };
|
|
359
|
+
});
|
|
360
|
+
// The integration is registered on the remote
|
|
361
|
+
statusCode === 200
|
|
362
|
+
? await updateIntegration(workingDir, options, siteId, accountId, localIntegrationConfig, token, registeredIntegration)
|
|
363
|
+
: await registerIntegration(workingDir, siteId, accountId, localIntegrationConfig, token);
|
|
364
|
+
// Set the prod flag to true if the integration is being initially registered because we don't want the user
|
|
365
|
+
// to be in a weird state where the card is appearing in the integrations list but there's no production
|
|
366
|
+
// version of the integration deployed
|
|
367
|
+
options = statusCode === 200 ? options : { ...options, prod: true };
|
|
368
|
+
// Deploy the integration to that site
|
|
369
|
+
await siteDeploy(options, command);
|
|
370
|
+
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`);
|
|
371
|
+
};
|
|
434
372
|
/**
|
|
435
373
|
* Creates the `netlify int deploy` command
|
|
436
374
|
* @param {import('../base-command.mjs').default} program
|
|
437
375
|
* @returns
|
|
438
376
|
*/
|
|
439
|
-
|
|
440
|
-
|
|
377
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type.
|
|
378
|
+
export const createDeployCommand = (program) => program
|
|
441
379
|
.command('integration:deploy')
|
|
442
380
|
.alias('int:deploy')
|
|
443
381
|
.description('Register, build, and deploy a private integration on Netlify')
|
|
@@ -445,4 +383,4 @@ export const createDeployCommand = (program) =>
|
|
|
445
383
|
.option('-b, --build', 'Build the integration', false)
|
|
446
384
|
.option('-a, --auth <token>', 'Netlify auth token to deploy with', env.NETLIFY_AUTH_TOKEN)
|
|
447
385
|
.option('-s, --site <name-or-id>', 'A site name or ID to deploy to', env.NETLIFY_SITE_ID)
|
|
448
|
-
.action(deploy)
|
|
386
|
+
.action(deploy);
|