@commercetools-frontend/mc-scripts 25.0.0 → 25.2.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/application-runtime/dist/commercetools-frontend-mc-scripts-application-runtime.cjs.dev.js +1 -1
- package/application-runtime/dist/commercetools-frontend-mc-scripts-application-runtime.cjs.prod.js +1 -1
- package/application-runtime/dist/commercetools-frontend-mc-scripts-application-runtime.esm.js +1 -1
- package/cli/dist/commercetools-frontend-mc-scripts-cli.cjs.dev.js +28 -14
- package/cli/dist/commercetools-frontend-mc-scripts-cli.cjs.prod.js +28 -14
- package/cli/dist/commercetools-frontend-mc-scripts-cli.esm.js +28 -14
- package/dist/{build-50f29fb0.cjs.prod.js → build-182a099c.cjs.prod.js} +7 -7
- package/dist/{build-0b4c6b04.esm.js → build-220a1658.esm.js} +7 -7
- package/dist/{build-1baf8a00.cjs.dev.js → build-519d246d.cjs.dev.js} +7 -7
- package/dist/{build-vite-e26f6c9f.cjs.dev.js → build-vite-837e7c94.cjs.dev.js} +64 -43
- package/dist/{build-vite-85211835.esm.js → build-vite-8cae71a0.esm.js} +61 -24
- package/dist/{build-vite-4a6c90c2.cjs.prod.js → build-vite-b007241b.cjs.prod.js} +64 -43
- package/dist/commercetools-frontend-mc-scripts.cjs.dev.js +1 -1
- package/dist/commercetools-frontend-mc-scripts.cjs.prod.js +1 -1
- package/dist/commercetools-frontend-mc-scripts.esm.js +1 -1
- package/dist/{compile-html-adfef598.esm.js → compile-html-025cd493.esm.js} +2 -4
- package/dist/{compile-html-b80f9651.cjs.prod.js → compile-html-50fd05ec.cjs.prod.js} +2 -5
- package/dist/{compile-html-8679f721.cjs.dev.js → compile-html-f4ac88cc.cjs.dev.js} +2 -5
- package/dist/config-sync-0b96d430.esm.js +255 -0
- package/dist/config-sync-b3072939.cjs.prod.js +265 -0
- package/dist/config-sync-ci-4a09aa00.cjs.prod.js +305 -0
- package/dist/config-sync-ci-85e3fec2.esm.js +294 -0
- package/dist/config-sync-ci-eadb8bfc.cjs.dev.js +305 -0
- package/dist/config-sync-f8fca39f.cjs.dev.js +265 -0
- package/dist/{config-sync-87ba9f28.cjs.prod.js → config-sync-helpers-11fc328f.cjs.prod.js} +193 -326
- package/dist/{config-sync-27ca0c93.cjs.dev.js → config-sync-helpers-dab59ed9.cjs.dev.js} +195 -328
- package/dist/{config-sync-ff4b1e5b.esm.js → config-sync-helpers-fe6ea729.esm.js} +186 -323
- package/dist/{create-postcss-config-34bab342.cjs.prod.js → create-postcss-config-56b74a34.cjs.prod.js} +1 -1
- package/dist/{create-postcss-config-0e833724.cjs.dev.js → create-postcss-config-78879a12.cjs.dev.js} +1 -1
- package/dist/{create-postcss-config-e6dfba3f.esm.js → create-postcss-config-95f9bf62.esm.js} +1 -1
- package/dist/{create-webpack-config-for-development-fe0945ce.cjs.prod.js → create-webpack-config-for-development-3eb1b365.cjs.prod.js} +7 -7
- package/dist/{create-webpack-config-for-development-2ac1d86f.cjs.dev.js → create-webpack-config-for-development-62b89920.cjs.dev.js} +7 -7
- package/dist/{create-webpack-config-for-development-be2722d6.esm.js → create-webpack-config-for-development-a28736fa.esm.js} +7 -7
- package/dist/{create-webpack-config-for-production-66c77849.esm.js → create-webpack-config-for-production-21ea561f.esm.js} +8 -8
- package/dist/{create-webpack-config-for-production-2200e554.cjs.prod.js → create-webpack-config-for-production-3b6599db.cjs.prod.js} +8 -8
- package/dist/{create-webpack-config-for-production-d2c41a9d.cjs.dev.js → create-webpack-config-for-production-e5ed8805.cjs.dev.js} +8 -8
- package/dist/{credentials-storage-381abf27.cjs.prod.js → credentials-storage-6d592cd6.cjs.prod.js} +21 -3
- package/dist/{credentials-storage-de220814.cjs.dev.js → credentials-storage-c4c5980e.cjs.dev.js} +21 -3
- package/dist/{credentials-storage-7285d7b4.esm.js → credentials-storage-fcc77fb6.esm.js} +21 -3
- package/dist/declarations/src/types.d.ts +4 -0
- package/dist/{deployment-previews-set-7f9fbfe5.esm.js → deployment-previews-set-7d49e7df.esm.js} +22 -27
- package/dist/{deployment-previews-set-3697be5e.cjs.dev.js → deployment-previews-set-8d6a1e99.cjs.dev.js} +22 -28
- package/dist/{deployment-previews-set-e92403f7.cjs.prod.js → deployment-previews-set-f8ce3db7.cjs.prod.js} +22 -28
- package/dist/{graphql-requests-bab5fcc3.cjs.dev.js → graphql-requests-b57fca4c.cjs.prod.js} +5 -8
- package/dist/{graphql-requests-d8bc2292.esm.js → graphql-requests-d2fa2ca7.esm.js} +6 -9
- package/dist/{graphql-requests-8ef89149.cjs.prod.js → graphql-requests-da194989.cjs.dev.js} +5 -8
- package/dist/{i18n-message-complilation-8aec9d1b.esm.js → i18n-message-complilation-21d3b0aa.esm.js} +1 -1
- package/dist/{i18n-message-complilation-3f80e8d6.cjs.dev.js → i18n-message-complilation-7311cb29.cjs.dev.js} +1 -1
- package/dist/{i18n-message-complilation-393d344a.cjs.prod.js → i18n-message-complilation-7762da61.cjs.prod.js} +1 -1
- package/dist/{login-5fd67aac.cjs.prod.js → login-9774c9cc.cjs.prod.js} +154 -38
- package/dist/login-abb38213.esm.js +337 -0
- package/dist/{login-9fac9eee.cjs.dev.js → login-f4550251.cjs.dev.js} +154 -38
- package/dist/{optimizations-ea21b802.cjs.prod.js → optimizations-7789145e.cjs.dev.js} +5 -8
- package/dist/{optimizations-ea71a24a.esm.js → optimizations-bf991634.esm.js} +5 -7
- package/dist/{optimizations-ebbeaf88.cjs.dev.js → optimizations-fb93514f.cjs.prod.js} +5 -8
- package/dist/{package-ff04bcf7.cjs.dev.js → package-0eebca1b.cjs.dev.js} +21 -11
- package/dist/{package-4bdd2ccf.esm.js → package-9e6910b8.esm.js} +21 -11
- package/dist/{package-428d5001.cjs.prod.js → package-b9298ce3.cjs.prod.js} +21 -11
- package/dist/{paths-7bf7e88e.esm.js → paths-39f22b8b.esm.js} +4 -9
- package/dist/{paths-af1a725a.cjs.prod.js → paths-7768b440.cjs.prod.js} +4 -10
- package/dist/{paths-ec3e3a7d.cjs.dev.js → paths-b76fc753.cjs.dev.js} +4 -10
- package/dist/{serve-04a03d5f.cjs.dev.js → serve-38456e1b.cjs.dev.js} +7 -6
- package/dist/{serve-fb1a0f5a.esm.js → serve-be1f9439.esm.js} +6 -6
- package/dist/{serve-2a863026.cjs.prod.js → serve-cc4a766d.cjs.prod.js} +7 -6
- package/dist/{start-643a55bb.esm.js → start-109f9462.esm.js} +8 -9
- package/dist/{start-47ea5e04.cjs.dev.js → start-7765f44c.cjs.dev.js} +8 -9
- package/dist/{start-84cdf12b.cjs.prod.js → start-e014127c.cjs.prod.js} +8 -9
- package/dist/{start-vite-eea72ba9.cjs.dev.js → start-vite-068e9f73.cjs.dev.js} +3 -4
- package/dist/{start-vite-d548c121.cjs.prod.js → start-vite-29078b3a.cjs.prod.js} +3 -4
- package/dist/{start-vite-d649d1f3.esm.js → start-vite-7d1161e8.esm.js} +3 -4
- package/dist/{vite-plugin-svgr-53ef97c7.cjs.dev.js → vite-plugin-svgr-4034a834.cjs.prod.js} +4 -4
- package/dist/{vite-plugin-svgr-5de1cad9.cjs.prod.js → vite-plugin-svgr-7d06f400.cjs.dev.js} +4 -4
- package/dist/{vite-plugin-svgr-22c8d518.esm.js → vite-plugin-svgr-de6ee7da.esm.js} +4 -4
- package/package.json +21 -11
- package/postcss/dist/commercetools-frontend-mc-scripts-postcss.cjs.dev.js +2 -2
- package/postcss/dist/commercetools-frontend-mc-scripts-postcss.cjs.prod.js +2 -2
- package/postcss/dist/commercetools-frontend-mc-scripts-postcss.esm.js +2 -2
- package/webpack/dist/commercetools-frontend-mc-scripts-webpack.cjs.dev.js +6 -6
- package/webpack/dist/commercetools-frontend-mc-scripts-webpack.cjs.prod.js +6 -6
- package/webpack/dist/commercetools-frontend-mc-scripts-webpack.esm.js +6 -6
- package/webpack-loaders/i18n-message-compilation-loader/dist/commercetools-frontend-mc-scripts-webpack-loaders-i18n-message-compilation-loader.cjs.dev.js +1 -1
- package/webpack-loaders/i18n-message-compilation-loader/dist/commercetools-frontend-mc-scripts-webpack-loaders-i18n-message-compilation-loader.cjs.prod.js +1 -1
- package/webpack-loaders/i18n-message-compilation-loader/dist/commercetools-frontend-mc-scripts-webpack-loaders-i18n-message-compilation-loader.esm.js +1 -1
- package/dist/login-9ee43381.esm.js +0 -223
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
import _Promise from '@babel/runtime-corejs3/core-js-stable/promise';
|
|
2
|
+
import _mapInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/map';
|
|
3
|
+
import _startsWithInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/starts-with';
|
|
4
|
+
import _bindInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/bind';
|
|
5
|
+
import _trimInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/trim';
|
|
6
|
+
import _flatMapInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/flat-map';
|
|
7
|
+
import _setTimeout from '@babel/runtime-corejs3/core-js-stable/set-timeout';
|
|
8
|
+
import _Date$now from '@babel/runtime-corejs3/core-js-stable/date/now';
|
|
9
|
+
import _includesInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/includes';
|
|
10
|
+
import _forEachInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/for-each';
|
|
11
|
+
import _URL from '@babel/runtime-corejs3/core-js-stable/url';
|
|
12
|
+
import crypto from 'node:crypto';
|
|
13
|
+
import process, { exit } from 'node:process';
|
|
14
|
+
import chalk from 'chalk';
|
|
15
|
+
import { processConfig } from '@commercetools-frontend/application-config';
|
|
16
|
+
import { p as pkgJson } from './package-9e6910b8.esm.js';
|
|
17
|
+
import http from 'node:http';
|
|
18
|
+
import jwtDecode from 'jwt-decode';
|
|
19
|
+
import { C as CredentialsStorage } from './credentials-storage-fcc77fb6.esm.js';
|
|
20
|
+
import '@babel/runtime-corejs3/helpers/classCallCheck';
|
|
21
|
+
import '@babel/runtime-corejs3/helpers/createClass';
|
|
22
|
+
import '@babel/runtime-corejs3/core-js-stable/json/stringify';
|
|
23
|
+
import 'node:fs';
|
|
24
|
+
import 'node:os';
|
|
25
|
+
import 'node:path';
|
|
26
|
+
import './does-file-exist-32618334.esm.js';
|
|
27
|
+
|
|
28
|
+
function createAuthCallbackServer(options) {
|
|
29
|
+
const server = http.createServer(async (request, response) => {
|
|
30
|
+
try {
|
|
31
|
+
var _context, _context2;
|
|
32
|
+
if (((_context = request.url) == null ? void 0 : _bindInstanceProperty(_context2 = Function.call).call(_context2, _includesInstanceProperty(_context), _context))?.(`/${options.clientIdentifier}/oidc/callback`)) {
|
|
33
|
+
const incomingUrl = new _URL(request.url, 'http://localhost');
|
|
34
|
+
const sessionToken = incomingUrl.searchParams.get('sessionToken');
|
|
35
|
+
const requestedState = incomingUrl.searchParams.get('state');
|
|
36
|
+
if (!sessionToken) {
|
|
37
|
+
throw new Error('Invalid authentication flow (missing sessionToken)');
|
|
38
|
+
}
|
|
39
|
+
const decodedSessionToken = jwtDecode(sessionToken);
|
|
40
|
+
if (decodedSessionToken?.nonce !== options.nonce) {
|
|
41
|
+
throw new Error('Invalid authentication flow (nonce mismatch)');
|
|
42
|
+
}
|
|
43
|
+
if (requestedState !== options.state) {
|
|
44
|
+
throw new Error('Invalid authentication flow (state mismatch)');
|
|
45
|
+
}
|
|
46
|
+
options.onSuccess({
|
|
47
|
+
token: sessionToken,
|
|
48
|
+
expiresAt: decodedSessionToken.exp
|
|
49
|
+
});
|
|
50
|
+
response.setHeader('content-type', 'text/html');
|
|
51
|
+
response.end('Success!');
|
|
52
|
+
server.close(() => {
|
|
53
|
+
exit();
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
} catch (error) {
|
|
57
|
+
response.setHeader('content-type', 'text/html');
|
|
58
|
+
if (error instanceof Error) {
|
|
59
|
+
console.error(error.message);
|
|
60
|
+
response.end(error.message);
|
|
61
|
+
} else {
|
|
62
|
+
console.error(error);
|
|
63
|
+
response.end(`Invalid authentication flow.`);
|
|
64
|
+
}
|
|
65
|
+
server.close(() => {
|
|
66
|
+
exit();
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
return server;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const credentialsStorage = new CredentialsStorage();
|
|
74
|
+
const port = 3001;
|
|
75
|
+
const clientIdentifier = `mc-scripts-${pkgJson.version}`;
|
|
76
|
+
const isServerError = error => {
|
|
77
|
+
return error instanceof Error && 'code' in error;
|
|
78
|
+
};
|
|
79
|
+
const startServer = server => new _Promise((resolve, reject) => {
|
|
80
|
+
server.listen(port, 'localhost').on('listening', resolve).on('error', error => {
|
|
81
|
+
if (isServerError(error) && error.code === 'EADDRINUSE') {
|
|
82
|
+
return reject(new Error(`The address "localhost:${port}" is already in use. Are you running a Merchant Center application in other process? Please stop that and try again.`, {
|
|
83
|
+
cause: error
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
return reject(new Error('Problem starting server', {
|
|
87
|
+
cause: error
|
|
88
|
+
}));
|
|
89
|
+
}).on('close', () => {
|
|
90
|
+
process.exit();
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
const resolveMcApiUrl = async options => {
|
|
94
|
+
if (options.mcApiUrl) {
|
|
95
|
+
return options.mcApiUrl;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// We first check whether the user has set the MC_API_URL environment variable
|
|
99
|
+
if (process.env.MC_API_URL) {
|
|
100
|
+
return process.env.MC_API_URL;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// If not, we parse the configuration and check if it's defined over there
|
|
104
|
+
const applicationConfig = await processConfig();
|
|
105
|
+
const mcApiUrl = applicationConfig.env.mcApiUrl;
|
|
106
|
+
return mcApiUrl;
|
|
107
|
+
};
|
|
108
|
+
const resolveProjectKey = async options => {
|
|
109
|
+
if (options.projectKey) {
|
|
110
|
+
return options.projectKey;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// We first check whether the user has set the CTP_PROJECT_KEY environment variable
|
|
114
|
+
if (process.env.CTP_PROJECT_KEY) {
|
|
115
|
+
return process.env.CTP_PROJECT_KEY;
|
|
116
|
+
}
|
|
117
|
+
try {
|
|
118
|
+
const applicationConfig = await processConfig();
|
|
119
|
+
return applicationConfig.env.__DEVELOPMENT__?.oidc?.initialProjectKey;
|
|
120
|
+
} catch (error) {
|
|
121
|
+
// It's ok if there's not application config file or if it does not contain the initialProjectKey
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
const mapOAuthScopesToClaims = scopes => {
|
|
126
|
+
return _mapInstanceProperty(scopes).call(scopes, scope => {
|
|
127
|
+
if (_startsWithInstanceProperty(scope).call(scope, 'view_')) {
|
|
128
|
+
return `view:${scope}`;
|
|
129
|
+
}
|
|
130
|
+
if (_startsWithInstanceProperty(scope).call(scope, 'manage_')) {
|
|
131
|
+
return `manage:${scope}`;
|
|
132
|
+
}
|
|
133
|
+
return scope;
|
|
134
|
+
});
|
|
135
|
+
};
|
|
136
|
+
const mapAdditionalOAuthScopesToClaims = (name, scopes) => {
|
|
137
|
+
return _mapInstanceProperty(scopes).call(scopes, scope => {
|
|
138
|
+
if (_startsWithInstanceProperty(scope).call(scope, 'view_')) {
|
|
139
|
+
return `view/${name}:${scope}`;
|
|
140
|
+
}
|
|
141
|
+
if (_startsWithInstanceProperty(scope).call(scope, 'manage_')) {
|
|
142
|
+
return `manage/${name}:${scope}`;
|
|
143
|
+
}
|
|
144
|
+
return scope;
|
|
145
|
+
});
|
|
146
|
+
};
|
|
147
|
+
const resolveOAuthScopes = async options => {
|
|
148
|
+
if (options.oauthScope) {
|
|
149
|
+
return mapOAuthScopesToClaims(options.oauthScope);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// We first check whether the user has set the CTP_OAUTH_SCOPES environment variable
|
|
153
|
+
if (process.env.CTP_OAUTH_SCOPES) {
|
|
154
|
+
var _context, _context2;
|
|
155
|
+
return mapOAuthScopesToClaims(((_context = process.env.CTP_OAUTH_SCOPES?.split(',')) == null ? void 0 : _bindInstanceProperty(_context2 = Function.call).call(_context2, _mapInstanceProperty(_context), _context))?.(scope => _trimInstanceProperty(scope).call(scope)) ?? []);
|
|
156
|
+
}
|
|
157
|
+
try {
|
|
158
|
+
var _context3, _context4, _context5, _context6;
|
|
159
|
+
const applicationConfig = await processConfig();
|
|
160
|
+
const configuredOAuthScopes = applicationConfig.env.__DEVELOPMENT__?.oidc?.oAuthScopes;
|
|
161
|
+
const configuredAdditionalOAuthScopes = applicationConfig.env.__DEVELOPMENT__?.oidc?.additionalOAuthScopes;
|
|
162
|
+
return [...mapOAuthScopesToClaims(configuredOAuthScopes?.view ?? []), ...mapOAuthScopesToClaims(configuredOAuthScopes?.manage ?? []), ...(((_context3 = configuredAdditionalOAuthScopes) == null ? void 0 : _bindInstanceProperty(_context4 = Function.call).call(_context4, _flatMapInstanceProperty(_context3), _context3))?.(scope => mapAdditionalOAuthScopesToClaims(scope.name, scope.view)) ?? []), ...(((_context5 = configuredAdditionalOAuthScopes) == null ? void 0 : _bindInstanceProperty(_context6 = Function.call).call(_context6, _flatMapInstanceProperty(_context5), _context5))?.(scope => mapAdditionalOAuthScopesToClaims(scope.name, scope.manage)) ?? [])];
|
|
163
|
+
} catch (error) {
|
|
164
|
+
// It's ok if there's not application config file or if it does not contain the initialProjectKey
|
|
165
|
+
return [];
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
const generateRandomHash = function () {
|
|
169
|
+
let length = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 16;
|
|
170
|
+
return crypto.randomBytes(length).toString('hex');
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Performs headless login using Puppeteer.
|
|
175
|
+
* Requires IDENTITY_EMAIL and IDENTITY_PASSWORD environment variables.
|
|
176
|
+
*/
|
|
177
|
+
async function runHeadlessLogin(authUrl) {
|
|
178
|
+
const email = process.env.IDENTITY_EMAIL;
|
|
179
|
+
const password = process.env.IDENTITY_PASSWORD;
|
|
180
|
+
if (!email || !password) {
|
|
181
|
+
throw new Error('Headless login requires IDENTITY_EMAIL and IDENTITY_PASSWORD environment variables');
|
|
182
|
+
}
|
|
183
|
+
let puppeteer;
|
|
184
|
+
try {
|
|
185
|
+
puppeteer = await import('puppeteer');
|
|
186
|
+
} catch {
|
|
187
|
+
throw new Error('Puppeteer is required for headless login. Install it with: npm install puppeteer');
|
|
188
|
+
}
|
|
189
|
+
const browser = await puppeteer.default.launch({
|
|
190
|
+
headless: 'new',
|
|
191
|
+
args: ['--no-sandbox', '--disable-setuid-sandbox']
|
|
192
|
+
});
|
|
193
|
+
try {
|
|
194
|
+
const page = await browser.newPage();
|
|
195
|
+
await page.goto(authUrl.toString(), {
|
|
196
|
+
waitUntil: 'networkidle2'
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
// Wait for the login page to load
|
|
200
|
+
await page.waitForSelector('input[name="identifier"]', {
|
|
201
|
+
timeout: 30000
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// Dismiss cookie banner if present
|
|
205
|
+
// Note: Using string-based evaluate to avoid bundler transforming Array.from
|
|
206
|
+
try {
|
|
207
|
+
await page.evaluate(`
|
|
208
|
+
(function() {
|
|
209
|
+
var buttons = Array.from(document.querySelectorAll('button'));
|
|
210
|
+
var acceptBtn = buttons.find(function(btn) {
|
|
211
|
+
return btn.textContent && btn.textContent.includes('Accept all cookies');
|
|
212
|
+
});
|
|
213
|
+
if (acceptBtn) acceptBtn.click();
|
|
214
|
+
})()
|
|
215
|
+
`);
|
|
216
|
+
await new _Promise(resolve => _setTimeout(resolve, 500));
|
|
217
|
+
} catch {
|
|
218
|
+
// Cookie banner not found or already dismissed
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Fill in email
|
|
222
|
+
await page.type('input[name="identifier"]', email);
|
|
223
|
+
await new _Promise(resolve => _setTimeout(resolve, 500));
|
|
224
|
+
|
|
225
|
+
// Click "Next" button
|
|
226
|
+
await page.evaluate(`
|
|
227
|
+
(function() {
|
|
228
|
+
var buttons = Array.from(document.querySelectorAll('button'));
|
|
229
|
+
var nextBtn = buttons.find(function(btn) {
|
|
230
|
+
return btn.textContent && btn.textContent.toLowerCase().includes('next');
|
|
231
|
+
});
|
|
232
|
+
if (nextBtn) nextBtn.click();
|
|
233
|
+
})()
|
|
234
|
+
`);
|
|
235
|
+
|
|
236
|
+
// Wait for password field
|
|
237
|
+
await page.waitForSelector('input[name="password"]', {
|
|
238
|
+
visible: true,
|
|
239
|
+
timeout: 30000
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// Fill in password
|
|
243
|
+
await page.type('input[name="password"]', password);
|
|
244
|
+
await new _Promise(resolve => _setTimeout(resolve, 500));
|
|
245
|
+
|
|
246
|
+
// Click "Submit" button
|
|
247
|
+
await page.evaluate(`
|
|
248
|
+
(function() {
|
|
249
|
+
var buttons = Array.from(document.querySelectorAll('button'));
|
|
250
|
+
var submitBtn = buttons.find(function(btn) {
|
|
251
|
+
return btn.textContent && btn.textContent.toLowerCase().includes('submit');
|
|
252
|
+
});
|
|
253
|
+
if (submitBtn) submitBtn.click();
|
|
254
|
+
})()
|
|
255
|
+
`);
|
|
256
|
+
|
|
257
|
+
// Wait for the callback to be processed (the server will close and exit)
|
|
258
|
+
// We just need to keep the browser alive until the redirect happens
|
|
259
|
+
const startTime = _Date$now();
|
|
260
|
+
const timeout = 60000;
|
|
261
|
+
while (_Date$now() - startTime < timeout) {
|
|
262
|
+
await new _Promise(resolve => _setTimeout(resolve, 500));
|
|
263
|
+
const currentUrl = page.url();
|
|
264
|
+
if (_includesInstanceProperty(currentUrl).call(currentUrl, 'sessionToken=')) {
|
|
265
|
+
// Token was captured by the callback server, we can exit
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
const pageContent = await page.content();
|
|
269
|
+
if (_includesInstanceProperty(pageContent).call(pageContent, 'Invalid credentials') || _includesInstanceProperty(pageContent).call(pageContent, 'invalid_grant')) {
|
|
270
|
+
throw new Error('Invalid credentials');
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Check if page shows success (callback server response)
|
|
274
|
+
if (_includesInstanceProperty(pageContent).call(pageContent, 'Success!')) {
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
} finally {
|
|
279
|
+
await browser.close();
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
async function run(options) {
|
|
283
|
+
const mcApiUrl = await resolveMcApiUrl(options);
|
|
284
|
+
if (!mcApiUrl) {
|
|
285
|
+
throw new Error('No Merchant Center API URL found. Aborting.');
|
|
286
|
+
}
|
|
287
|
+
console.log(`Using Merchant Center environment "${chalk.green(mcApiUrl)}".`);
|
|
288
|
+
console.log();
|
|
289
|
+
if (!options.force && credentialsStorage.isSessionValid(mcApiUrl)) {
|
|
290
|
+
console.log(`You already have a valid session.`);
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
const projectKey = await resolveProjectKey(options);
|
|
294
|
+
const oauthScopes = await resolveOAuthScopes(options);
|
|
295
|
+
const scopes = ['openid'];
|
|
296
|
+
if (projectKey) {
|
|
297
|
+
scopes.push(`project_key:${projectKey}`);
|
|
298
|
+
_forEachInstanceProperty(oauthScopes).call(oauthScopes, scope => {
|
|
299
|
+
scopes.push(scope);
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
const state = generateRandomHash();
|
|
303
|
+
const nonce = generateRandomHash();
|
|
304
|
+
const authUrl = new _URL('/login/authorize', mcApiUrl);
|
|
305
|
+
authUrl.searchParams.set('response_type', 'id_token');
|
|
306
|
+
authUrl.searchParams.set('response_mode', 'query');
|
|
307
|
+
authUrl.searchParams.set('client_id', `__local:${clientIdentifier}`);
|
|
308
|
+
authUrl.searchParams.set('scope', scopes.join(' '));
|
|
309
|
+
authUrl.searchParams.set('state', state);
|
|
310
|
+
authUrl.searchParams.set('nonce', nonce);
|
|
311
|
+
const server = createAuthCallbackServer({
|
|
312
|
+
clientIdentifier,
|
|
313
|
+
state,
|
|
314
|
+
nonce,
|
|
315
|
+
onSuccess: tokenContext => {
|
|
316
|
+
credentialsStorage.setToken(mcApiUrl, tokenContext);
|
|
317
|
+
console.log();
|
|
318
|
+
console.log(chalk.green(`Login successful.`));
|
|
319
|
+
console.log();
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
await startServer(server);
|
|
323
|
+
if (options.headless) {
|
|
324
|
+
console.log(`Initiating headless authentication flow using Puppeteer...`);
|
|
325
|
+
console.log();
|
|
326
|
+
await runHeadlessLogin(authUrl);
|
|
327
|
+
} else {
|
|
328
|
+
console.log(`Initiating the OIDC authentication flow, opening the login page in your browser...`);
|
|
329
|
+
console.log(` ${authUrl}`);
|
|
330
|
+
console.log();
|
|
331
|
+
const open = await import('open');
|
|
332
|
+
await open.default(authUrl.toString());
|
|
333
|
+
console.log('Waiting for the OIDC authentication to complete...');
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
export { run as default };
|
|
@@ -3,24 +3,25 @@
|
|
|
3
3
|
var _Promise = require('@babel/runtime-corejs3/core-js-stable/promise');
|
|
4
4
|
var _mapInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/map');
|
|
5
5
|
var _startsWithInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/starts-with');
|
|
6
|
-
var
|
|
6
|
+
var _bindInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/bind');
|
|
7
7
|
var _trimInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/trim');
|
|
8
8
|
var _flatMapInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/flat-map');
|
|
9
|
+
var _setTimeout = require('@babel/runtime-corejs3/core-js-stable/set-timeout');
|
|
10
|
+
var _Date$now = require('@babel/runtime-corejs3/core-js-stable/date/now');
|
|
11
|
+
var _includesInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/includes');
|
|
9
12
|
var _forEachInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/for-each');
|
|
10
13
|
var _URL = require('@babel/runtime-corejs3/core-js-stable/url');
|
|
11
14
|
var crypto = require('node:crypto');
|
|
12
15
|
var process = require('node:process');
|
|
13
16
|
var chalk = require('chalk');
|
|
14
17
|
var applicationConfig = require('@commercetools-frontend/application-config');
|
|
15
|
-
var _package = require('./package-
|
|
16
|
-
var _includesInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/includes');
|
|
18
|
+
var _package = require('./package-0eebca1b.cjs.dev.js');
|
|
17
19
|
var http = require('node:http');
|
|
18
20
|
var jwtDecode = require('jwt-decode');
|
|
19
|
-
var credentialsStorage$1 = require('./credentials-storage-
|
|
21
|
+
var credentialsStorage$1 = require('./credentials-storage-c4c5980e.cjs.dev.js');
|
|
20
22
|
require('@babel/runtime-corejs3/helpers/classCallCheck');
|
|
21
23
|
require('@babel/runtime-corejs3/helpers/createClass');
|
|
22
24
|
require('@babel/runtime-corejs3/core-js-stable/json/stringify');
|
|
23
|
-
require('@babel/runtime-corejs3/core-js-stable/date/now');
|
|
24
25
|
require('node:fs');
|
|
25
26
|
require('node:os');
|
|
26
27
|
require('node:path');
|
|
@@ -49,23 +50,25 @@ function _interopNamespace(e) {
|
|
|
49
50
|
var _Promise__default = /*#__PURE__*/_interopDefault(_Promise);
|
|
50
51
|
var _mapInstanceProperty__default = /*#__PURE__*/_interopDefault(_mapInstanceProperty);
|
|
51
52
|
var _startsWithInstanceProperty__default = /*#__PURE__*/_interopDefault(_startsWithInstanceProperty);
|
|
52
|
-
var
|
|
53
|
+
var _bindInstanceProperty__default = /*#__PURE__*/_interopDefault(_bindInstanceProperty);
|
|
53
54
|
var _trimInstanceProperty__default = /*#__PURE__*/_interopDefault(_trimInstanceProperty);
|
|
54
55
|
var _flatMapInstanceProperty__default = /*#__PURE__*/_interopDefault(_flatMapInstanceProperty);
|
|
56
|
+
var _setTimeout__default = /*#__PURE__*/_interopDefault(_setTimeout);
|
|
57
|
+
var _Date$now__default = /*#__PURE__*/_interopDefault(_Date$now);
|
|
58
|
+
var _includesInstanceProperty__default = /*#__PURE__*/_interopDefault(_includesInstanceProperty);
|
|
55
59
|
var _forEachInstanceProperty__default = /*#__PURE__*/_interopDefault(_forEachInstanceProperty);
|
|
56
60
|
var _URL__default = /*#__PURE__*/_interopDefault(_URL);
|
|
57
61
|
var crypto__default = /*#__PURE__*/_interopDefault(crypto);
|
|
58
62
|
var process__default = /*#__PURE__*/_interopDefault(process);
|
|
59
63
|
var chalk__default = /*#__PURE__*/_interopDefault(chalk);
|
|
60
|
-
var _includesInstanceProperty__default = /*#__PURE__*/_interopDefault(_includesInstanceProperty);
|
|
61
64
|
var http__default = /*#__PURE__*/_interopDefault(http);
|
|
62
65
|
var jwtDecode__default = /*#__PURE__*/_interopDefault(jwtDecode);
|
|
63
66
|
|
|
64
67
|
function createAuthCallbackServer(options) {
|
|
65
68
|
const server = http__default["default"].createServer(async (request, response) => {
|
|
66
69
|
try {
|
|
67
|
-
var
|
|
68
|
-
if ((
|
|
70
|
+
var _context, _context2;
|
|
71
|
+
if (((_context = request.url) == null ? void 0 : _bindInstanceProperty__default["default"](_context2 = Function.call).call(_context2, _includesInstanceProperty__default["default"](_context), _context))?.(`/${options.clientIdentifier}/oidc/callback`)) {
|
|
69
72
|
const incomingUrl = new _URL__default["default"](request.url, 'http://localhost');
|
|
70
73
|
const sessionToken = incomingUrl.searchParams.get('sessionToken');
|
|
71
74
|
const requestedState = incomingUrl.searchParams.get('state');
|
|
@@ -73,7 +76,7 @@ function createAuthCallbackServer(options) {
|
|
|
73
76
|
throw new Error('Invalid authentication flow (missing sessionToken)');
|
|
74
77
|
}
|
|
75
78
|
const decodedSessionToken = jwtDecode__default["default"](sessionToken);
|
|
76
|
-
if (
|
|
79
|
+
if (decodedSessionToken?.nonce !== options.nonce) {
|
|
77
80
|
throw new Error('Invalid authentication flow (nonce mismatch)');
|
|
78
81
|
}
|
|
79
82
|
if (requestedState !== options.state) {
|
|
@@ -96,7 +99,7 @@ function createAuthCallbackServer(options) {
|
|
|
96
99
|
response.end(error.message);
|
|
97
100
|
} else {
|
|
98
101
|
console.error(error);
|
|
99
|
-
response.end(
|
|
102
|
+
response.end(`Invalid authentication flow.`);
|
|
100
103
|
}
|
|
101
104
|
server.close(() => {
|
|
102
105
|
process.exit();
|
|
@@ -108,14 +111,14 @@ function createAuthCallbackServer(options) {
|
|
|
108
111
|
|
|
109
112
|
const credentialsStorage = new credentialsStorage$1.CredentialsStorage();
|
|
110
113
|
const port = 3001;
|
|
111
|
-
const clientIdentifier =
|
|
114
|
+
const clientIdentifier = `mc-scripts-${_package.pkgJson.version}`;
|
|
112
115
|
const isServerError = error => {
|
|
113
116
|
return error instanceof Error && 'code' in error;
|
|
114
117
|
};
|
|
115
118
|
const startServer = server => new _Promise__default["default"]((resolve, reject) => {
|
|
116
119
|
server.listen(port, 'localhost').on('listening', resolve).on('error', error => {
|
|
117
120
|
if (isServerError(error) && error.code === 'EADDRINUSE') {
|
|
118
|
-
return reject(new Error(
|
|
121
|
+
return reject(new Error(`The address "localhost:${port}" is already in use. Are you running a Merchant Center application in other process? Please stop that and try again.`, {
|
|
119
122
|
cause: error
|
|
120
123
|
}));
|
|
121
124
|
}
|
|
@@ -151,9 +154,8 @@ const resolveProjectKey = async options => {
|
|
|
151
154
|
return process__default["default"].env.CTP_PROJECT_KEY;
|
|
152
155
|
}
|
|
153
156
|
try {
|
|
154
|
-
var _applicationConfig$en;
|
|
155
157
|
const applicationConfig$1 = await applicationConfig.processConfig();
|
|
156
|
-
return
|
|
158
|
+
return applicationConfig$1.env.__DEVELOPMENT__?.oidc?.initialProjectKey;
|
|
157
159
|
} catch (error) {
|
|
158
160
|
// It's ok if there's not application config file or if it does not contain the initialProjectKey
|
|
159
161
|
return;
|
|
@@ -162,10 +164,10 @@ const resolveProjectKey = async options => {
|
|
|
162
164
|
const mapOAuthScopesToClaims = scopes => {
|
|
163
165
|
return _mapInstanceProperty__default["default"](scopes).call(scopes, scope => {
|
|
164
166
|
if (_startsWithInstanceProperty__default["default"](scope).call(scope, 'view_')) {
|
|
165
|
-
return
|
|
167
|
+
return `view:${scope}`;
|
|
166
168
|
}
|
|
167
169
|
if (_startsWithInstanceProperty__default["default"](scope).call(scope, 'manage_')) {
|
|
168
|
-
return
|
|
170
|
+
return `manage:${scope}`;
|
|
169
171
|
}
|
|
170
172
|
return scope;
|
|
171
173
|
});
|
|
@@ -173,12 +175,10 @@ const mapOAuthScopesToClaims = scopes => {
|
|
|
173
175
|
const mapAdditionalOAuthScopesToClaims = (name, scopes) => {
|
|
174
176
|
return _mapInstanceProperty__default["default"](scopes).call(scopes, scope => {
|
|
175
177
|
if (_startsWithInstanceProperty__default["default"](scope).call(scope, 'view_')) {
|
|
176
|
-
|
|
177
|
-
return _concatInstanceProperty__default["default"](_context = "view/".concat(name, ":")).call(_context, scope);
|
|
178
|
+
return `view/${name}:${scope}`;
|
|
178
179
|
}
|
|
179
180
|
if (_startsWithInstanceProperty__default["default"](scope).call(scope, 'manage_')) {
|
|
180
|
-
|
|
181
|
-
return _concatInstanceProperty__default["default"](_context2 = "manage/".concat(name, ":")).call(_context2, scope);
|
|
181
|
+
return `manage/${name}:${scope}`;
|
|
182
182
|
}
|
|
183
183
|
return scope;
|
|
184
184
|
});
|
|
@@ -190,15 +190,15 @@ const resolveOAuthScopes = async options => {
|
|
|
190
190
|
|
|
191
191
|
// We first check whether the user has set the CTP_OAUTH_SCOPES environment variable
|
|
192
192
|
if (process__default["default"].env.CTP_OAUTH_SCOPES) {
|
|
193
|
-
var
|
|
194
|
-
return mapOAuthScopesToClaims((
|
|
193
|
+
var _context, _context2;
|
|
194
|
+
return mapOAuthScopesToClaims(((_context = process__default["default"].env.CTP_OAUTH_SCOPES?.split(',')) == null ? void 0 : _bindInstanceProperty__default["default"](_context2 = Function.call).call(_context2, _mapInstanceProperty__default["default"](_context), _context))?.(scope => _trimInstanceProperty__default["default"](scope).call(scope)) ?? []);
|
|
195
195
|
}
|
|
196
196
|
try {
|
|
197
|
-
var
|
|
197
|
+
var _context3, _context4, _context5, _context6;
|
|
198
198
|
const applicationConfig$1 = await applicationConfig.processConfig();
|
|
199
|
-
const configuredOAuthScopes =
|
|
200
|
-
const configuredAdditionalOAuthScopes =
|
|
201
|
-
return [...mapOAuthScopesToClaims(
|
|
199
|
+
const configuredOAuthScopes = applicationConfig$1.env.__DEVELOPMENT__?.oidc?.oAuthScopes;
|
|
200
|
+
const configuredAdditionalOAuthScopes = applicationConfig$1.env.__DEVELOPMENT__?.oidc?.additionalOAuthScopes;
|
|
201
|
+
return [...mapOAuthScopesToClaims(configuredOAuthScopes?.view ?? []), ...mapOAuthScopesToClaims(configuredOAuthScopes?.manage ?? []), ...(((_context3 = configuredAdditionalOAuthScopes) == null ? void 0 : _bindInstanceProperty__default["default"](_context4 = Function.call).call(_context4, _flatMapInstanceProperty__default["default"](_context3), _context3))?.(scope => mapAdditionalOAuthScopesToClaims(scope.name, scope.view)) ?? []), ...(((_context5 = configuredAdditionalOAuthScopes) == null ? void 0 : _bindInstanceProperty__default["default"](_context6 = Function.call).call(_context6, _flatMapInstanceProperty__default["default"](_context5), _context5))?.(scope => mapAdditionalOAuthScopesToClaims(scope.name, scope.manage)) ?? [])];
|
|
202
202
|
} catch (error) {
|
|
203
203
|
// It's ok if there's not application config file or if it does not contain the initialProjectKey
|
|
204
204
|
return [];
|
|
@@ -208,22 +208,132 @@ const generateRandomHash = function () {
|
|
|
208
208
|
let length = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 16;
|
|
209
209
|
return crypto__default["default"].randomBytes(length).toString('hex');
|
|
210
210
|
};
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Performs headless login using Puppeteer.
|
|
214
|
+
* Requires IDENTITY_EMAIL and IDENTITY_PASSWORD environment variables.
|
|
215
|
+
*/
|
|
216
|
+
async function runHeadlessLogin(authUrl) {
|
|
217
|
+
const email = process__default["default"].env.IDENTITY_EMAIL;
|
|
218
|
+
const password = process__default["default"].env.IDENTITY_PASSWORD;
|
|
219
|
+
if (!email || !password) {
|
|
220
|
+
throw new Error('Headless login requires IDENTITY_EMAIL and IDENTITY_PASSWORD environment variables');
|
|
221
|
+
}
|
|
222
|
+
let puppeteer;
|
|
223
|
+
try {
|
|
224
|
+
puppeteer = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('puppeteer')); });
|
|
225
|
+
} catch {
|
|
226
|
+
throw new Error('Puppeteer is required for headless login. Install it with: npm install puppeteer');
|
|
227
|
+
}
|
|
228
|
+
const browser = await puppeteer.default.launch({
|
|
229
|
+
headless: 'new',
|
|
230
|
+
args: ['--no-sandbox', '--disable-setuid-sandbox']
|
|
231
|
+
});
|
|
232
|
+
try {
|
|
233
|
+
const page = await browser.newPage();
|
|
234
|
+
await page.goto(authUrl.toString(), {
|
|
235
|
+
waitUntil: 'networkidle2'
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// Wait for the login page to load
|
|
239
|
+
await page.waitForSelector('input[name="identifier"]', {
|
|
240
|
+
timeout: 30000
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
// Dismiss cookie banner if present
|
|
244
|
+
// Note: Using string-based evaluate to avoid bundler transforming Array.from
|
|
245
|
+
try {
|
|
246
|
+
await page.evaluate(`
|
|
247
|
+
(function() {
|
|
248
|
+
var buttons = Array.from(document.querySelectorAll('button'));
|
|
249
|
+
var acceptBtn = buttons.find(function(btn) {
|
|
250
|
+
return btn.textContent && btn.textContent.includes('Accept all cookies');
|
|
251
|
+
});
|
|
252
|
+
if (acceptBtn) acceptBtn.click();
|
|
253
|
+
})()
|
|
254
|
+
`);
|
|
255
|
+
await new _Promise__default["default"](resolve => _setTimeout__default["default"](resolve, 500));
|
|
256
|
+
} catch {
|
|
257
|
+
// Cookie banner not found or already dismissed
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Fill in email
|
|
261
|
+
await page.type('input[name="identifier"]', email);
|
|
262
|
+
await new _Promise__default["default"](resolve => _setTimeout__default["default"](resolve, 500));
|
|
263
|
+
|
|
264
|
+
// Click "Next" button
|
|
265
|
+
await page.evaluate(`
|
|
266
|
+
(function() {
|
|
267
|
+
var buttons = Array.from(document.querySelectorAll('button'));
|
|
268
|
+
var nextBtn = buttons.find(function(btn) {
|
|
269
|
+
return btn.textContent && btn.textContent.toLowerCase().includes('next');
|
|
270
|
+
});
|
|
271
|
+
if (nextBtn) nextBtn.click();
|
|
272
|
+
})()
|
|
273
|
+
`);
|
|
274
|
+
|
|
275
|
+
// Wait for password field
|
|
276
|
+
await page.waitForSelector('input[name="password"]', {
|
|
277
|
+
visible: true,
|
|
278
|
+
timeout: 30000
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
// Fill in password
|
|
282
|
+
await page.type('input[name="password"]', password);
|
|
283
|
+
await new _Promise__default["default"](resolve => _setTimeout__default["default"](resolve, 500));
|
|
284
|
+
|
|
285
|
+
// Click "Submit" button
|
|
286
|
+
await page.evaluate(`
|
|
287
|
+
(function() {
|
|
288
|
+
var buttons = Array.from(document.querySelectorAll('button'));
|
|
289
|
+
var submitBtn = buttons.find(function(btn) {
|
|
290
|
+
return btn.textContent && btn.textContent.toLowerCase().includes('submit');
|
|
291
|
+
});
|
|
292
|
+
if (submitBtn) submitBtn.click();
|
|
293
|
+
})()
|
|
294
|
+
`);
|
|
295
|
+
|
|
296
|
+
// Wait for the callback to be processed (the server will close and exit)
|
|
297
|
+
// We just need to keep the browser alive until the redirect happens
|
|
298
|
+
const startTime = _Date$now__default["default"]();
|
|
299
|
+
const timeout = 60000;
|
|
300
|
+
while (_Date$now__default["default"]() - startTime < timeout) {
|
|
301
|
+
await new _Promise__default["default"](resolve => _setTimeout__default["default"](resolve, 500));
|
|
302
|
+
const currentUrl = page.url();
|
|
303
|
+
if (_includesInstanceProperty__default["default"](currentUrl).call(currentUrl, 'sessionToken=')) {
|
|
304
|
+
// Token was captured by the callback server, we can exit
|
|
305
|
+
break;
|
|
306
|
+
}
|
|
307
|
+
const pageContent = await page.content();
|
|
308
|
+
if (_includesInstanceProperty__default["default"](pageContent).call(pageContent, 'Invalid credentials') || _includesInstanceProperty__default["default"](pageContent).call(pageContent, 'invalid_grant')) {
|
|
309
|
+
throw new Error('Invalid credentials');
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Check if page shows success (callback server response)
|
|
313
|
+
if (_includesInstanceProperty__default["default"](pageContent).call(pageContent, 'Success!')) {
|
|
314
|
+
break;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
} finally {
|
|
318
|
+
await browser.close();
|
|
319
|
+
}
|
|
320
|
+
}
|
|
211
321
|
async function run(options) {
|
|
212
322
|
const mcApiUrl = await resolveMcApiUrl(options);
|
|
213
323
|
if (!mcApiUrl) {
|
|
214
324
|
throw new Error('No Merchant Center API URL found. Aborting.');
|
|
215
325
|
}
|
|
216
|
-
console.log(
|
|
326
|
+
console.log(`Using Merchant Center environment "${chalk__default["default"].green(mcApiUrl)}".`);
|
|
217
327
|
console.log();
|
|
218
328
|
if (!options.force && credentialsStorage.isSessionValid(mcApiUrl)) {
|
|
219
|
-
console.log(
|
|
329
|
+
console.log(`You already have a valid session.`);
|
|
220
330
|
return;
|
|
221
331
|
}
|
|
222
332
|
const projectKey = await resolveProjectKey(options);
|
|
223
333
|
const oauthScopes = await resolveOAuthScopes(options);
|
|
224
334
|
const scopes = ['openid'];
|
|
225
335
|
if (projectKey) {
|
|
226
|
-
scopes.push(
|
|
336
|
+
scopes.push(`project_key:${projectKey}`);
|
|
227
337
|
_forEachInstanceProperty__default["default"](oauthScopes).call(oauthScopes, scope => {
|
|
228
338
|
scopes.push(scope);
|
|
229
339
|
});
|
|
@@ -233,7 +343,7 @@ async function run(options) {
|
|
|
233
343
|
const authUrl = new _URL__default["default"]('/login/authorize', mcApiUrl);
|
|
234
344
|
authUrl.searchParams.set('response_type', 'id_token');
|
|
235
345
|
authUrl.searchParams.set('response_mode', 'query');
|
|
236
|
-
authUrl.searchParams.set('client_id',
|
|
346
|
+
authUrl.searchParams.set('client_id', `__local:${clientIdentifier}`);
|
|
237
347
|
authUrl.searchParams.set('scope', scopes.join(' '));
|
|
238
348
|
authUrl.searchParams.set('state', state);
|
|
239
349
|
authUrl.searchParams.set('nonce', nonce);
|
|
@@ -244,17 +354,23 @@ async function run(options) {
|
|
|
244
354
|
onSuccess: tokenContext => {
|
|
245
355
|
credentialsStorage.setToken(mcApiUrl, tokenContext);
|
|
246
356
|
console.log();
|
|
247
|
-
console.log(chalk__default["default"].green(
|
|
357
|
+
console.log(chalk__default["default"].green(`Login successful.`));
|
|
248
358
|
console.log();
|
|
249
359
|
}
|
|
250
360
|
});
|
|
251
361
|
await startServer(server);
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
362
|
+
if (options.headless) {
|
|
363
|
+
console.log(`Initiating headless authentication flow using Puppeteer...`);
|
|
364
|
+
console.log();
|
|
365
|
+
await runHeadlessLogin(authUrl);
|
|
366
|
+
} else {
|
|
367
|
+
console.log(`Initiating the OIDC authentication flow, opening the login page in your browser...`);
|
|
368
|
+
console.log(` ${authUrl}`);
|
|
369
|
+
console.log();
|
|
370
|
+
const open = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('open')); });
|
|
371
|
+
await open.default(authUrl.toString());
|
|
372
|
+
console.log('Waiting for the OIDC authentication to complete...');
|
|
373
|
+
}
|
|
258
374
|
}
|
|
259
375
|
|
|
260
376
|
exports["default"] = run;
|