@contentstack/cli-utilities 1.19.0-beta.0 → 1.19.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/lib/contentstack-management-sdk.js +7 -3
- package/lib/contentstack-marketplace-sdk.d.ts +2 -2
- package/lib/feature-status/build-auth-headers.d.ts +9 -0
- package/lib/feature-status/build-auth-headers.js +33 -0
- package/lib/feature-status/feature-status-handler.d.ts +3 -0
- package/lib/feature-status/feature-status-handler.js +37 -0
- package/lib/feature-status/feature-uids.d.ts +5 -0
- package/lib/feature-status/feature-uids.js +7 -0
- package/lib/feature-status/index.d.ts +5 -0
- package/lib/feature-status/index.js +13 -0
- package/lib/feature-status/resolve-auth-host.d.ts +8 -0
- package/lib/feature-status/resolve-auth-host.js +31 -0
- package/lib/feature-status/types.d.ts +21 -0
- package/lib/feature-status/types.js +2 -0
- package/lib/fs-utility/core.js +0 -3
- package/lib/helpers.d.ts +2 -0
- package/lib/helpers.js +11 -1
- package/lib/http-client/client.js +9 -6
- package/lib/http-client/http-response.d.ts +1 -1
- package/lib/http-client/http-response.js +1 -0
- package/lib/index.d.ts +4 -1
- package/lib/index.js +5 -1
- package/lib/interfaces/index.d.ts +1 -1
- package/lib/logger/cli-error-handler.js +1 -1
- package/lib/logger/log.js +1 -1
- package/lib/logger/session-path.js +1 -1
- package/lib/proxy-helper.d.ts +6 -6
- package/lib/proxy-helper.js +61 -51
- package/lib/region-endpoints.d.ts +25 -0
- package/lib/region-endpoints.js +39 -0
- package/lib/region-refresh.d.ts +9 -0
- package/lib/region-refresh.js +27 -0
- package/package.json +21 -20
|
@@ -19,12 +19,12 @@ class ManagementSDKInitiator {
|
|
|
19
19
|
const host = (0, proxy_helper_1.resolveRequestHost)(config);
|
|
20
20
|
// NO_PROXY has priority over HTTP_PROXY/HTTPS_PROXY and config-set proxy
|
|
21
21
|
const proxyConfig = (0, proxy_helper_1.getProxyConfigForHost)(host);
|
|
22
|
-
// When
|
|
23
|
-
if (
|
|
22
|
+
// When NO_PROXY matches, strip proxy env so SDK/axios cannot pick up HTTP_PROXY for this process.
|
|
23
|
+
if (host && (0, proxy_helper_1.shouldBypassProxy)(host)) {
|
|
24
24
|
(0, proxy_helper_1.clearProxyEnv)();
|
|
25
25
|
}
|
|
26
26
|
const option = {
|
|
27
|
-
host: config.host,
|
|
27
|
+
host: config.host || host || undefined,
|
|
28
28
|
maxContentLength: config.maxContentLength || 100000000,
|
|
29
29
|
maxBodyLength: config.maxBodyLength || 1000000000,
|
|
30
30
|
maxRequests: 10,
|
|
@@ -112,6 +112,10 @@ class ManagementSDKInitiator {
|
|
|
112
112
|
if (proxyConfig) {
|
|
113
113
|
option.proxy = proxyConfig;
|
|
114
114
|
}
|
|
115
|
+
else if (host && (0, proxy_helper_1.shouldBypassProxy)(host)) {
|
|
116
|
+
option.proxy = false;
|
|
117
|
+
}
|
|
118
|
+
// When host is in NO_PROXY, do not add proxy to option at all
|
|
115
119
|
if (config.endpoint) {
|
|
116
120
|
option.endpoint = config.endpoint;
|
|
117
121
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { App, AppData } from '@contentstack/marketplace-sdk/types/marketplace/app';
|
|
1
|
+
import type { App, AppData } from '@contentstack/marketplace-sdk/types/marketplace/app';
|
|
2
2
|
import { ContentstackConfig, ContentstackClient, ContentstackToken } from '@contentstack/marketplace-sdk';
|
|
3
|
-
import { Installation } from '@contentstack/marketplace-sdk/types/marketplace/installation';
|
|
3
|
+
import type { Installation } from '@contentstack/marketplace-sdk/types/marketplace/installation';
|
|
4
4
|
type ConfigType = Pick<ContentstackConfig, 'host' | 'endpoint' | 'retryDelay' | 'retryLimit'> & {
|
|
5
5
|
skipTokenValidity?: string;
|
|
6
6
|
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildAuthHeaders = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const config_handler_1 = tslib_1.__importDefault(require("../config-handler"));
|
|
6
|
+
function buildAuthHeaders(ctx) {
|
|
7
|
+
var _a, _b;
|
|
8
|
+
// 1. Management token takes priority (no 'Bearer' prefix — API contract)
|
|
9
|
+
if ((ctx === null || ctx === void 0 ? void 0 : ctx.managementToken) && (ctx === null || ctx === void 0 ? void 0 : ctx.apiKey)) {
|
|
10
|
+
return {
|
|
11
|
+
Authorization: ctx.managementToken,
|
|
12
|
+
api_key: ctx.apiKey,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
// 2. OAuth
|
|
16
|
+
const oauthToken = config_handler_1.default.get('oauthAccessToken');
|
|
17
|
+
if (oauthToken) {
|
|
18
|
+
return { Authorization: `Bearer ${oauthToken}` };
|
|
19
|
+
}
|
|
20
|
+
// 3. Authtoken + organization_uid
|
|
21
|
+
const authtoken = (_a = ctx === null || ctx === void 0 ? void 0 : ctx.authToken) !== null && _a !== void 0 ? _a : config_handler_1.default.get('authtoken');
|
|
22
|
+
const orgUid = (_b = ctx === null || ctx === void 0 ? void 0 : ctx.orgUid) !== null && _b !== void 0 ? _b : config_handler_1.default.get('oauthOrgUid');
|
|
23
|
+
if (authtoken && orgUid) {
|
|
24
|
+
return { authtoken, organization_uid: orgUid };
|
|
25
|
+
}
|
|
26
|
+
// 4. Authtoken + api_key
|
|
27
|
+
if (authtoken && (ctx === null || ctx === void 0 ? void 0 : ctx.apiKey)) {
|
|
28
|
+
return { authtoken, api_key: ctx.apiKey };
|
|
29
|
+
}
|
|
30
|
+
throw new Error('PLAN_CHECK: Cannot build auth headers — no valid credentials available. ' +
|
|
31
|
+
'Please log in or provide a management token alias.');
|
|
32
|
+
}
|
|
33
|
+
exports.buildAuthHeaders = buildAuthHeaders;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.assertFeatureEnabled = exports.isFeatureEnabled = void 0;
|
|
4
|
+
const http_client_1 = require("../http-client");
|
|
5
|
+
const resolve_auth_host_1 = require("./resolve-auth-host");
|
|
6
|
+
const build_auth_headers_1 = require("./build-auth-headers");
|
|
7
|
+
async function isFeatureEnabled(featureUid, ctx) {
|
|
8
|
+
const host = (0, resolve_auth_host_1.resolveAuthHost)(ctx);
|
|
9
|
+
const headers = (0, build_auth_headers_1.buildAuthHeaders)(ctx);
|
|
10
|
+
const client = new http_client_1.HttpClient();
|
|
11
|
+
client.baseUrl(host).headers(headers);
|
|
12
|
+
const res = await client.get(`/v1/feature-status?feature_uid=${encodeURIComponent(featureUid)}`);
|
|
13
|
+
if (res.status < 200 || res.status >= 300) {
|
|
14
|
+
throw new Error(`PLAN_CHECK: feature-status API returned ${res.status} for "${featureUid}".`);
|
|
15
|
+
}
|
|
16
|
+
return res.data;
|
|
17
|
+
}
|
|
18
|
+
exports.isFeatureEnabled = isFeatureEnabled;
|
|
19
|
+
async function assertFeatureEnabled(featureUid, ctx) {
|
|
20
|
+
let status;
|
|
21
|
+
try {
|
|
22
|
+
status = await isFeatureEnabled(featureUid, ctx);
|
|
23
|
+
}
|
|
24
|
+
catch (e) {
|
|
25
|
+
throw new Error(`Could not verify your plan for "${featureUid}". ` +
|
|
26
|
+
`This command requires a confirmed plan status to run. ` +
|
|
27
|
+
`Please retry; if the problem persists contact support. (${e.message})`);
|
|
28
|
+
}
|
|
29
|
+
if (!status.is_part_of_plan) {
|
|
30
|
+
throw new Error(`"${featureUid}" is not part of your current plan. Please upgrade your plan to use this feature.`);
|
|
31
|
+
}
|
|
32
|
+
if (status.status !== 'enabled') {
|
|
33
|
+
throw new Error(`"${featureUid}" is not enabled for your plan (status: ${status.status}).`);
|
|
34
|
+
}
|
|
35
|
+
return status;
|
|
36
|
+
}
|
|
37
|
+
exports.assertFeatureEnabled = assertFeatureEnabled;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.assertFeatureEnabled = exports.isFeatureEnabled = exports.buildAuthHeaders = exports.resolveAuthHost = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
tslib_1.__exportStar(require("./types"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./feature-uids"), exports);
|
|
7
|
+
var resolve_auth_host_1 = require("./resolve-auth-host");
|
|
8
|
+
Object.defineProperty(exports, "resolveAuthHost", { enumerable: true, get: function () { return resolve_auth_host_1.resolveAuthHost; } });
|
|
9
|
+
var build_auth_headers_1 = require("./build-auth-headers");
|
|
10
|
+
Object.defineProperty(exports, "buildAuthHeaders", { enumerable: true, get: function () { return build_auth_headers_1.buildAuthHeaders; } });
|
|
11
|
+
var feature_status_handler_1 = require("./feature-status-handler");
|
|
12
|
+
Object.defineProperty(exports, "isFeatureEnabled", { enumerable: true, get: function () { return feature_status_handler_1.isFeatureEnabled; } });
|
|
13
|
+
Object.defineProperty(exports, "assertFeatureEnabled", { enumerable: true, get: function () { return feature_status_handler_1.assertFeatureEnabled; } });
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveAuthHost = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const config_handler_1 = tslib_1.__importDefault(require("../config-handler"));
|
|
6
|
+
// Mirrors config:set:region's own custom-region fallback (region.ts's transformUrl) —
|
|
7
|
+
// same heuristic, applied retroactively for a custom region that predates auth-api.
|
|
8
|
+
// Computed fresh on each call, never persisted back to config.
|
|
9
|
+
function deriveAuthFromCma(cma) {
|
|
10
|
+
let transformed = cma.replace('api', 'auth-api');
|
|
11
|
+
if (transformed.startsWith('http')) {
|
|
12
|
+
transformed = transformed.split('//')[1];
|
|
13
|
+
}
|
|
14
|
+
transformed = transformed.replace(/^dev\d+/, 'dev');
|
|
15
|
+
transformed = transformed.endsWith('io') ? transformed.replace('io', 'com') : transformed;
|
|
16
|
+
return `https://${transformed}`;
|
|
17
|
+
}
|
|
18
|
+
function resolveAuthHost(ctx) {
|
|
19
|
+
var _a, _b;
|
|
20
|
+
const region = ((_a = ctx === null || ctx === void 0 ? void 0 : ctx.region) !== null && _a !== void 0 ? _a : config_handler_1.default.get('region'));
|
|
21
|
+
let authUrl = (_b = region === null || region === void 0 ? void 0 : region.endpoints) === null || _b === void 0 ? void 0 : _b.auth;
|
|
22
|
+
if (!authUrl && (region === null || region === void 0 ? void 0 : region.cma)) {
|
|
23
|
+
authUrl = deriveAuthFromCma(region.cma);
|
|
24
|
+
}
|
|
25
|
+
if (!authUrl) {
|
|
26
|
+
throw new Error('PLAN_CHECK: Auth host is not configured for the current region. ' +
|
|
27
|
+
"Re-run `csdx config:set:region` to refresh region endpoints.");
|
|
28
|
+
}
|
|
29
|
+
return String(authUrl).replace(/\/$/, '');
|
|
30
|
+
}
|
|
31
|
+
exports.resolveAuthHost = resolveAuthHost;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface FeatureStatus {
|
|
2
|
+
org_uid: string;
|
|
3
|
+
feature_key: string;
|
|
4
|
+
status: 'enabled' | 'disabled' | string;
|
|
5
|
+
limit: number;
|
|
6
|
+
max_limit: number;
|
|
7
|
+
is_part_of_plan: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface FeatureCtx {
|
|
10
|
+
apiKey?: string;
|
|
11
|
+
orgUid?: string;
|
|
12
|
+
managementToken?: string;
|
|
13
|
+
authToken?: string;
|
|
14
|
+
region?: {
|
|
15
|
+
name?: string;
|
|
16
|
+
cma?: string;
|
|
17
|
+
endpoints?: {
|
|
18
|
+
auth?: string;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
}
|
package/lib/fs-utility/core.js
CHANGED
|
@@ -337,11 +337,9 @@ class FsUtility {
|
|
|
337
337
|
this.pageInfo.after = index || 0;
|
|
338
338
|
this.pageInfo.before = 1;
|
|
339
339
|
}
|
|
340
|
-
/* eslint-disable unicorn/consistent-destructuring */
|
|
341
340
|
if (!(0, isEmpty_1.default)(this.readIndexer[this.pageInfo.after + 1])) {
|
|
342
341
|
this.pageInfo.hasNextPage = true;
|
|
343
342
|
}
|
|
344
|
-
/* eslint-disable unicorn/consistent-destructuring */
|
|
345
343
|
if (!(0, isEmpty_1.default)(this.readIndexer[this.pageInfo.after - 1])) {
|
|
346
344
|
this.pageInfo.hasPreviousPage = true;
|
|
347
345
|
}
|
|
@@ -367,7 +365,6 @@ async function getFileList(dirName, onlyName = true) {
|
|
|
367
365
|
const items = (0, node_fs_1.readdirSync)(dirName, { withFileTypes: true });
|
|
368
366
|
for (const item of items) {
|
|
369
367
|
if (item.isDirectory()) {
|
|
370
|
-
/* eslint-disable no-await-in-loop */
|
|
371
368
|
files = [...files, ...(await getFileList(`${dirName}/${item.name}`))];
|
|
372
369
|
}
|
|
373
370
|
else {
|
package/lib/helpers.d.ts
CHANGED
|
@@ -42,6 +42,8 @@ export declare function getAuthenticationMethod(): string;
|
|
|
42
42
|
* @param authenticationMethod - Optional authentication method
|
|
43
43
|
* @returns Context object with all session-level metadata
|
|
44
44
|
*/
|
|
45
|
+
export declare function generateUid(): string;
|
|
46
|
+
export declare function generateShortUid(): string;
|
|
45
47
|
export declare function createLogContext(commandId: string, apiKey: string, authenticationMethod?: string): {
|
|
46
48
|
command: string;
|
|
47
49
|
module: string;
|
package/lib/helpers.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createLogContext = exports.getAuthenticationMethod = exports.redactObject = exports.formatError = exports.validateRegex = exports.validateFileName = exports.validateUids = exports.sanitizePath = exports.escapeRegExp = exports.validatePath = exports.createDeveloperHubUrl = exports.isManagementTokenValid = exports.getBranchFromAlias = exports.doesBranchExist = exports.isAuthenticated = void 0;
|
|
3
|
+
exports.createLogContext = exports.generateShortUid = exports.generateUid = exports.getAuthenticationMethod = exports.redactObject = exports.formatError = exports.validateRegex = exports.validateFileName = exports.validateUids = exports.sanitizePath = exports.escapeRegExp = exports.validatePath = exports.createDeveloperHubUrl = exports.isManagementTokenValid = exports.getBranchFromAlias = exports.doesBranchExist = exports.isAuthenticated = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const recheck_1 = require("recheck");
|
|
6
6
|
const traverse_1 = tslib_1.__importDefault(require("traverse"));
|
|
7
|
+
const uuid_1 = require("uuid");
|
|
8
|
+
const short_uuid_1 = require("short-uuid");
|
|
7
9
|
const auth_handler_1 = tslib_1.__importDefault(require("./auth-handler"));
|
|
8
10
|
const _1 = require(".");
|
|
9
11
|
const proxy_helper_1 = require("./proxy-helper");
|
|
@@ -271,6 +273,14 @@ exports.getAuthenticationMethod = getAuthenticationMethod;
|
|
|
271
273
|
* @param authenticationMethod - Optional authentication method
|
|
272
274
|
* @returns Context object with all session-level metadata
|
|
273
275
|
*/
|
|
276
|
+
function generateUid() {
|
|
277
|
+
return (0, uuid_1.v4)();
|
|
278
|
+
}
|
|
279
|
+
exports.generateUid = generateUid;
|
|
280
|
+
function generateShortUid() {
|
|
281
|
+
return (0, short_uuid_1.generate)();
|
|
282
|
+
}
|
|
283
|
+
exports.generateShortUid = generateShortUid;
|
|
274
284
|
function createLogContext(commandId, apiKey, authenticationMethod) {
|
|
275
285
|
// Store apiKey in configHandler so it's available for session.json
|
|
276
286
|
if (apiKey) {
|
|
@@ -12,13 +12,13 @@ const proxy_helper_1 = require("../proxy-helper");
|
|
|
12
12
|
*/
|
|
13
13
|
function getRequestHost(baseURL, url) {
|
|
14
14
|
const toTry = [baseURL, url].filter(Boolean);
|
|
15
|
-
for (const
|
|
15
|
+
for (const u of toTry) {
|
|
16
16
|
try {
|
|
17
|
-
const parsed = new URL(
|
|
17
|
+
const parsed = new URL(u.startsWith('http') ? u : `https://${u}`);
|
|
18
18
|
return parsed.hostname || undefined;
|
|
19
19
|
}
|
|
20
20
|
catch (_a) {
|
|
21
|
-
//
|
|
21
|
+
// ignore
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
return undefined;
|
|
@@ -356,13 +356,16 @@ class HttpClient {
|
|
|
356
356
|
this.headers({ 'x-header-ea': Object.values(earlyAccessHeaders).join(',') });
|
|
357
357
|
}
|
|
358
358
|
}
|
|
359
|
-
// Configure proxy if available. NO_PROXY has priority
|
|
359
|
+
// Configure proxy if available. NO_PROXY has priority; fall back to region CMA for host resolution.
|
|
360
360
|
if (!this.request.proxy) {
|
|
361
|
-
const host = getRequestHost(this.request.baseURL, url);
|
|
362
|
-
const proxyConfig =
|
|
361
|
+
const host = getRequestHost(this.request.baseURL, url) || (0, proxy_helper_1.resolveRequestHost)({});
|
|
362
|
+
const proxyConfig = (0, proxy_helper_1.getProxyConfigForHost)(host);
|
|
363
363
|
if (proxyConfig) {
|
|
364
364
|
this.request.proxy = proxyConfig;
|
|
365
365
|
}
|
|
366
|
+
else if (host && (0, proxy_helper_1.shouldBypassProxy)(host)) {
|
|
367
|
+
this.request.proxy = false;
|
|
368
|
+
}
|
|
366
369
|
}
|
|
367
370
|
return await this.axiosInstance(Object.assign(Object.assign({ url,
|
|
368
371
|
method, withCredentials: true }, this.request), { data: this.prepareRequestPayload() }));
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.HttpResponse = void 0;
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
4
5
|
class HttpResponse {
|
|
5
6
|
/**
|
|
6
7
|
* Wrap the given Axios `response` into a new response instance.
|
package/lib/index.d.ts
CHANGED
|
@@ -22,8 +22,11 @@ export * from './path-validator';
|
|
|
22
22
|
export { default as CLITable, TableFlags, TableHeader, TableOptions, TableData } from './cli-table';
|
|
23
23
|
export { App, AppData, Installation, marketplaceSDKClient, MarketplaceSDKInitiator, marketplaceSDKInitiator, ContentstackMarketplaceClient, ContentstackMarketplaceConfig, };
|
|
24
24
|
export { Args, CommandHelp, Config, Errors, Flags, loadHelpClass, Help, HelpBase, HelpSection, HelpSectionRenderer, HelpSectionKeyValueTable, Hook, Interfaces, Parser, Plugin, run, toStandardizedId, toConfiguredId, settings, Settings, flush, ux, execute, } from '@oclif/core';
|
|
25
|
-
export { FlagInput, ArgInput, FlagDefinition } from '@oclif/core/lib/interfaces/parser';
|
|
25
|
+
export type { FlagInput, ArgInput, FlagDefinition } from '@oclif/core/lib/interfaces/parser';
|
|
26
26
|
export { default as TablePrompt } from './inquirer-table-prompt';
|
|
27
27
|
export { Logger };
|
|
28
28
|
export { default as authenticationHandler } from './authentication-handler';
|
|
29
29
|
export { v2Logger as log, cliErrorHandler, handleAndLogError, getLogPath } from './logger/log';
|
|
30
|
+
export * from './feature-status';
|
|
31
|
+
export * from './region-endpoints';
|
|
32
|
+
export { refreshRegionEndpoints } from './region-refresh';
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getLogPath = exports.handleAndLogError = exports.cliErrorHandler = exports.log = exports.authenticationHandler = exports.Logger = exports.TablePrompt = exports.execute = exports.ux = exports.flush = exports.settings = exports.toConfiguredId = exports.toStandardizedId = exports.run = exports.Plugin = exports.Parser = exports.Interfaces = exports.HelpBase = exports.Help = exports.loadHelpClass = exports.Flags = exports.Errors = exports.Config = exports.CommandHelp = exports.Args = exports.marketplaceSDKInitiator = exports.MarketplaceSDKInitiator = exports.marketplaceSDKClient = exports.CLITable = exports.createLogContext = exports.Command = exports.flags = exports.args = exports.NodeCrypto = exports.printFlagDeprecation = exports.managementSDKInitiator = exports.managementSDKClient = exports.configHandler = exports.authHandler = exports.messageHandler = exports.CLIError = exports.cliux = exports.LoggerService = void 0;
|
|
3
|
+
exports.refreshRegionEndpoints = exports.getLogPath = exports.handleAndLogError = exports.cliErrorHandler = exports.log = exports.authenticationHandler = exports.Logger = exports.TablePrompt = exports.execute = exports.ux = exports.flush = exports.settings = exports.toConfiguredId = exports.toStandardizedId = exports.run = exports.Plugin = exports.Parser = exports.Interfaces = exports.HelpBase = exports.Help = exports.loadHelpClass = exports.Flags = exports.Errors = exports.Config = exports.CommandHelp = exports.Args = exports.marketplaceSDKInitiator = exports.MarketplaceSDKInitiator = exports.marketplaceSDKClient = exports.CLITable = exports.createLogContext = exports.Command = exports.flags = exports.args = exports.NodeCrypto = exports.printFlagDeprecation = exports.managementSDKInitiator = exports.managementSDKClient = exports.configHandler = exports.authHandler = exports.messageHandler = exports.CLIError = exports.cliux = exports.LoggerService = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const logger_1 = tslib_1.__importDefault(require("./logger"));
|
|
6
6
|
exports.Logger = logger_1.default;
|
|
@@ -72,3 +72,7 @@ Object.defineProperty(exports, "log", { enumerable: true, get: function () { ret
|
|
|
72
72
|
Object.defineProperty(exports, "cliErrorHandler", { enumerable: true, get: function () { return log_1.cliErrorHandler; } });
|
|
73
73
|
Object.defineProperty(exports, "handleAndLogError", { enumerable: true, get: function () { return log_1.handleAndLogError; } });
|
|
74
74
|
Object.defineProperty(exports, "getLogPath", { enumerable: true, get: function () { return log_1.getLogPath; } });
|
|
75
|
+
tslib_1.__exportStar(require("./feature-status"), exports);
|
|
76
|
+
tslib_1.__exportStar(require("./region-endpoints"), exports);
|
|
77
|
+
var region_refresh_1 = require("./region-refresh");
|
|
78
|
+
Object.defineProperty(exports, "refreshRegionEndpoints", { enumerable: true, get: function () { return region_refresh_1.refreshRegionEndpoints; } });
|
|
@@ -16,7 +16,7 @@ export interface InquirePayload {
|
|
|
16
16
|
default?: any;
|
|
17
17
|
message: string;
|
|
18
18
|
choices?: Array<any>;
|
|
19
|
-
transformer?:
|
|
19
|
+
transformer?: (value: any) => any;
|
|
20
20
|
validate?(input: any, answers?: any): boolean | string | Promise<boolean | string>;
|
|
21
21
|
selectAll?: boolean;
|
|
22
22
|
pageSize?: number;
|
|
@@ -175,7 +175,7 @@ class CLIErrorHandler {
|
|
|
175
175
|
*/
|
|
176
176
|
extractErrorPayload(error) {
|
|
177
177
|
var _a, _b, _c, _d;
|
|
178
|
-
const { name,
|
|
178
|
+
const { name, code, status, response, request, config, statusText } = error;
|
|
179
179
|
const payload = {
|
|
180
180
|
name,
|
|
181
181
|
message: this.extractClearMessage(error),
|
package/lib/logger/log.js
CHANGED
|
@@ -43,7 +43,7 @@ function createSessionMetadataFile(sessionPath, metadata) {
|
|
|
43
43
|
try {
|
|
44
44
|
fs.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2), 'utf8');
|
|
45
45
|
}
|
|
46
|
-
catch (
|
|
46
|
+
catch (_a) {
|
|
47
47
|
// Silently fail if metadata file cannot be created
|
|
48
48
|
// Logging here would cause circular dependency
|
|
49
49
|
// The session folder and logs will still be created
|
package/lib/proxy-helper.d.ts
CHANGED
|
@@ -23,8 +23,9 @@ export declare function getNoProxyList(): string[];
|
|
|
23
23
|
*/
|
|
24
24
|
export declare function shouldBypassProxy(host: string): boolean;
|
|
25
25
|
/**
|
|
26
|
-
* Get proxy configuration.
|
|
27
|
-
* from `csdx config:set:proxy --host <host> --port <port> --protocol <protocol
|
|
26
|
+
* Get proxy configuration. Priority order (per spec):
|
|
27
|
+
* 1. Global CLI config from `csdx config:set:proxy --host <host> --port <port> --protocol <protocol>`
|
|
28
|
+
* 2. Environment variables (HTTPS_PROXY or HTTP_PROXY)
|
|
28
29
|
* For per-request use, prefer getProxyConfigForHost(host) so NO_PROXY overrides both sources.
|
|
29
30
|
* @returns ProxyConfig object or undefined if no proxy is configured
|
|
30
31
|
*/
|
|
@@ -39,10 +40,9 @@ export declare function getProxyConfig(): ProxyConfig | undefined;
|
|
|
39
40
|
*/
|
|
40
41
|
export declare function getProxyConfigForHost(host: string): ProxyConfig | undefined;
|
|
41
42
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* @returns Host string (hostname or empty)
|
|
43
|
+
* Hostname for NO_PROXY / proxy. Prefer `region.cma` when set so callers that pass a
|
|
44
|
+
* default SDK host (e.g. bulk-entries -> api.contentstack.io) still match rules like
|
|
45
|
+
* `.csnonprod.com` against the real API host (e.g. dev11-api.csnonprod.com).
|
|
46
46
|
*/
|
|
47
47
|
export declare function resolveRequestHost(config: {
|
|
48
48
|
host?: string;
|
package/lib/proxy-helper.js
CHANGED
|
@@ -82,40 +82,14 @@ function shouldBypassProxy(host) {
|
|
|
82
82
|
}
|
|
83
83
|
exports.shouldBypassProxy = shouldBypassProxy;
|
|
84
84
|
/**
|
|
85
|
-
* Get proxy configuration.
|
|
86
|
-
* from `csdx config:set:proxy --host <host> --port <port> --protocol <protocol
|
|
85
|
+
* Get proxy configuration. Priority order (per spec):
|
|
86
|
+
* 1. Global CLI config from `csdx config:set:proxy --host <host> --port <port> --protocol <protocol>`
|
|
87
|
+
* 2. Environment variables (HTTPS_PROXY or HTTP_PROXY)
|
|
87
88
|
* For per-request use, prefer getProxyConfigForHost(host) so NO_PROXY overrides both sources.
|
|
88
89
|
* @returns ProxyConfig object or undefined if no proxy is configured
|
|
89
90
|
*/
|
|
90
91
|
function getProxyConfig() {
|
|
91
|
-
// Priority 1:
|
|
92
|
-
const proxyUrl = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
|
|
93
|
-
if (proxyUrl) {
|
|
94
|
-
try {
|
|
95
|
-
const url = new URL(proxyUrl);
|
|
96
|
-
const defaultPort = url.protocol === 'https:' ? 443 : 80;
|
|
97
|
-
const port = url.port ? Number.parseInt(url.port, 10) : defaultPort;
|
|
98
|
-
if (!Number.isNaN(port) && port >= 1 && port <= 65535) {
|
|
99
|
-
const protocol = url.protocol.replace(':', '');
|
|
100
|
-
const proxyConfig = {
|
|
101
|
-
protocol: protocol,
|
|
102
|
-
host: url.hostname,
|
|
103
|
-
port: port,
|
|
104
|
-
};
|
|
105
|
-
if (url.username || url.password) {
|
|
106
|
-
proxyConfig.auth = {
|
|
107
|
-
username: url.username,
|
|
108
|
-
password: url.password,
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
return proxyConfig;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
catch (_a) {
|
|
115
|
-
// Invalid URL, continue to check global config
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
// Priority 2: Global config (csdx config:set:proxy)
|
|
92
|
+
// Priority 1: Global config (csdx config:set:proxy)
|
|
119
93
|
const globalProxyConfig = config_handler_1.default.get('proxy');
|
|
120
94
|
if (globalProxyConfig) {
|
|
121
95
|
if (typeof globalProxyConfig === 'object') {
|
|
@@ -145,11 +119,38 @@ function getProxyConfig() {
|
|
|
145
119
|
return proxyConfig;
|
|
146
120
|
}
|
|
147
121
|
}
|
|
148
|
-
catch (
|
|
149
|
-
// Invalid URL,
|
|
122
|
+
catch (_a) {
|
|
123
|
+
// Invalid URL, continue to check environment
|
|
150
124
|
}
|
|
151
125
|
}
|
|
152
126
|
}
|
|
127
|
+
// Priority 2: Environment variables (HTTPS_PROXY or HTTP_PROXY)
|
|
128
|
+
const proxyUrl = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
|
|
129
|
+
if (proxyUrl) {
|
|
130
|
+
try {
|
|
131
|
+
const url = new URL(proxyUrl);
|
|
132
|
+
const defaultPort = url.protocol === 'https:' ? 443 : 80;
|
|
133
|
+
const port = url.port ? Number.parseInt(url.port, 10) : defaultPort;
|
|
134
|
+
if (!Number.isNaN(port) && port >= 1 && port <= 65535) {
|
|
135
|
+
const protocol = url.protocol.replace(':', '');
|
|
136
|
+
const proxyConfig = {
|
|
137
|
+
protocol: protocol,
|
|
138
|
+
host: url.hostname,
|
|
139
|
+
port: port,
|
|
140
|
+
};
|
|
141
|
+
if (url.username || url.password) {
|
|
142
|
+
proxyConfig.auth = {
|
|
143
|
+
username: url.username,
|
|
144
|
+
password: url.password,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
return proxyConfig;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
catch (_b) {
|
|
151
|
+
// Invalid URL, return undefined
|
|
152
|
+
}
|
|
153
|
+
}
|
|
153
154
|
return undefined;
|
|
154
155
|
}
|
|
155
156
|
exports.getProxyConfig = getProxyConfig;
|
|
@@ -167,30 +168,39 @@ function getProxyConfigForHost(host) {
|
|
|
167
168
|
return getProxyConfig();
|
|
168
169
|
}
|
|
169
170
|
exports.getProxyConfigForHost = getProxyConfigForHost;
|
|
171
|
+
function regionCmaHostname() {
|
|
172
|
+
var _a;
|
|
173
|
+
const cma = (_a = config_handler_1.default.get('region')) === null || _a === void 0 ? void 0 : _a.cma;
|
|
174
|
+
if (!cma || typeof cma !== 'string') {
|
|
175
|
+
return '';
|
|
176
|
+
}
|
|
177
|
+
if (cma.startsWith('http')) {
|
|
178
|
+
try {
|
|
179
|
+
const u = new URL(cma);
|
|
180
|
+
return u.hostname || cma;
|
|
181
|
+
}
|
|
182
|
+
catch (_b) {
|
|
183
|
+
return cma;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return cma;
|
|
187
|
+
}
|
|
170
188
|
/**
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
* @returns Host string (hostname or empty)
|
|
189
|
+
* Hostname for NO_PROXY / proxy. Prefer `region.cma` when set so callers that pass a
|
|
190
|
+
* default SDK host (e.g. bulk-entries -> api.contentstack.io) still match rules like
|
|
191
|
+
* `.csnonprod.com` against the real API host (e.g. dev11-api.csnonprod.com).
|
|
175
192
|
*/
|
|
176
193
|
function resolveRequestHost(config) {
|
|
177
194
|
var _a;
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
return u.hostname || cma;
|
|
186
|
-
}
|
|
187
|
-
catch (_b) {
|
|
188
|
-
return cma;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
return cma;
|
|
195
|
+
const fromRegion = regionCmaHostname();
|
|
196
|
+
if (fromRegion) {
|
|
197
|
+
return normalizeHost(fromRegion) || fromRegion;
|
|
198
|
+
}
|
|
199
|
+
const raw = ((_a = config.host) === null || _a === void 0 ? void 0 : _a.trim()) || '';
|
|
200
|
+
if (!raw) {
|
|
201
|
+
return '';
|
|
192
202
|
}
|
|
193
|
-
return
|
|
203
|
+
return normalizeHost(raw) || raw;
|
|
194
204
|
}
|
|
195
205
|
exports.resolveRequestHost = resolveRequestHost;
|
|
196
206
|
/**
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface RegionEndpoints {
|
|
2
|
+
[key: string]: string;
|
|
3
|
+
}
|
|
4
|
+
export interface CanonicalRegion {
|
|
5
|
+
name: string;
|
|
6
|
+
cma: string;
|
|
7
|
+
cda: string;
|
|
8
|
+
uiHost: string;
|
|
9
|
+
developerHubUrl: string;
|
|
10
|
+
launchHubUrl: string;
|
|
11
|
+
personalizeUrl: string;
|
|
12
|
+
composableStudioUrl: string;
|
|
13
|
+
endpoints: RegionEndpoints;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Resolve the canonical endpoint set for a region name/alias via @contentstack/utils.
|
|
17
|
+
* Returns null when the name isn't a recognized region (e.g. a custom region name).
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveCanonicalEndpoints(name: string): RegionEndpoints | null;
|
|
20
|
+
/**
|
|
21
|
+
* Build a region object from a raw endpoints map, keeping the existing named
|
|
22
|
+
* fields (cma/cda/uiHost/...) plus a full raw `endpoints` passthrough so any
|
|
23
|
+
* future endpoint Contentstack adds is available without further code changes.
|
|
24
|
+
*/
|
|
25
|
+
export declare function buildRegionFromEndpoints(name: string, endpoints: RegionEndpoints): CanonicalRegion;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildRegionFromEndpoints = exports.resolveCanonicalEndpoints = void 0;
|
|
4
|
+
const utils_1 = require("@contentstack/utils");
|
|
5
|
+
/**
|
|
6
|
+
* Resolve the canonical endpoint set for a region name/alias via @contentstack/utils.
|
|
7
|
+
* Returns null when the name isn't a recognized region (e.g. a custom region name).
|
|
8
|
+
*/
|
|
9
|
+
function resolveCanonicalEndpoints(name) {
|
|
10
|
+
try {
|
|
11
|
+
const endpoints = (0, utils_1.getContentstackEndpoint)(name);
|
|
12
|
+
if (!endpoints || typeof endpoints === 'string')
|
|
13
|
+
return null;
|
|
14
|
+
return endpoints;
|
|
15
|
+
}
|
|
16
|
+
catch (_a) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.resolveCanonicalEndpoints = resolveCanonicalEndpoints;
|
|
21
|
+
/**
|
|
22
|
+
* Build a region object from a raw endpoints map, keeping the existing named
|
|
23
|
+
* fields (cma/cda/uiHost/...) plus a full raw `endpoints` passthrough so any
|
|
24
|
+
* future endpoint Contentstack adds is available without further code changes.
|
|
25
|
+
*/
|
|
26
|
+
function buildRegionFromEndpoints(name, endpoints) {
|
|
27
|
+
return {
|
|
28
|
+
name,
|
|
29
|
+
cma: endpoints.contentManagement,
|
|
30
|
+
cda: endpoints.contentDelivery,
|
|
31
|
+
uiHost: endpoints.application,
|
|
32
|
+
developerHubUrl: endpoints.developerHub,
|
|
33
|
+
launchHubUrl: endpoints.launch,
|
|
34
|
+
personalizeUrl: endpoints.personalizeManagement,
|
|
35
|
+
composableStudioUrl: endpoints.composableStudio,
|
|
36
|
+
endpoints,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
exports.buildRegionFromEndpoints = buildRegionFromEndpoints;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-heals the persisted region config on every CLI invocation so that
|
|
3
|
+
* customers who set their region on an older CLI version (before a field
|
|
4
|
+
* like authUrl existed) get it backfilled without re-running
|
|
5
|
+
* `csdx config:set:region`. Only named/built-in regions are touched — a
|
|
6
|
+
* custom region's name won't resolve via resolveCanonicalEndpoints, so it's
|
|
7
|
+
* left untouched. Never throws.
|
|
8
|
+
*/
|
|
9
|
+
export declare function refreshRegionEndpoints(): void;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.refreshRegionEndpoints = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const config_handler_1 = tslib_1.__importDefault(require("./config-handler"));
|
|
6
|
+
const region_endpoints_1 = require("./region-endpoints");
|
|
7
|
+
/**
|
|
8
|
+
* Self-heals the persisted region config on every CLI invocation so that
|
|
9
|
+
* customers who set their region on an older CLI version (before a field
|
|
10
|
+
* like authUrl existed) get it backfilled without re-running
|
|
11
|
+
* `csdx config:set:region`. Only named/built-in regions are touched — a
|
|
12
|
+
* custom region's name won't resolve via resolveCanonicalEndpoints, so it's
|
|
13
|
+
* left untouched. Never throws.
|
|
14
|
+
*/
|
|
15
|
+
function refreshRegionEndpoints() {
|
|
16
|
+
const stored = config_handler_1.default.get('region');
|
|
17
|
+
if (!(stored === null || stored === void 0 ? void 0 : stored.name))
|
|
18
|
+
return;
|
|
19
|
+
const endpoints = (0, region_endpoints_1.resolveCanonicalEndpoints)(stored.name);
|
|
20
|
+
if (!endpoints)
|
|
21
|
+
return;
|
|
22
|
+
const merged = Object.assign(Object.assign({}, stored), (0, region_endpoints_1.buildRegionFromEndpoints)(stored.name, endpoints));
|
|
23
|
+
if (JSON.stringify(merged) !== JSON.stringify(stored)) {
|
|
24
|
+
config_handler_1.default.set('region', merged);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.refreshRegionEndpoints = refreshRegionEndpoints;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentstack/cli-utilities",
|
|
3
|
-
"version": "1.19.0
|
|
3
|
+
"version": "1.19.0",
|
|
4
4
|
"description": "Utilities for contentstack projects",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -9,14 +9,8 @@
|
|
|
9
9
|
"build": "pnpm compile",
|
|
10
10
|
"clean": "rm -rf ./lib ./node_modules tsconfig.tsbuildinfo",
|
|
11
11
|
"compile": "tsc -b tsconfig.json",
|
|
12
|
-
"test
|
|
13
|
-
"
|
|
14
|
-
"test": "nyc --extension .ts mocha --forbid-only \"test/**/*.test.ts\"",
|
|
15
|
-
"posttest": "npm run lint",
|
|
16
|
-
"lint": "eslint src/**/*.ts",
|
|
17
|
-
"format": "eslint src/**/*.ts --fix",
|
|
18
|
-
"test:unit": "mocha --forbid-only \"test/unit/**/*.test.ts\"",
|
|
19
|
-
"test:unit:report": "nyc --extension .ts mocha --forbid-only \"test/unit/**/*.test.ts\""
|
|
12
|
+
"test": "mocha \"test/unit/**/*.test.ts\"",
|
|
13
|
+
"lint": "eslint src/**/*.ts"
|
|
20
14
|
},
|
|
21
15
|
"repository": {
|
|
22
16
|
"type": "git",
|
|
@@ -33,10 +27,11 @@
|
|
|
33
27
|
"author": "contentstack",
|
|
34
28
|
"license": "MIT",
|
|
35
29
|
"dependencies": {
|
|
36
|
-
"@contentstack/management": "~1.
|
|
37
|
-
"@contentstack/marketplace-sdk": "^1.5.
|
|
38
|
-
"@
|
|
39
|
-
"
|
|
30
|
+
"@contentstack/management": "~1.30.1",
|
|
31
|
+
"@contentstack/marketplace-sdk": "^1.5.1",
|
|
32
|
+
"@contentstack/utils": "~1.9.1",
|
|
33
|
+
"@oclif/core": "^4.11.4",
|
|
34
|
+
"axios": "^1.16.1",
|
|
40
35
|
"chalk": "^4.1.2",
|
|
41
36
|
"cli-cursor": "^3.1.0",
|
|
42
37
|
"cli-progress": "^3.12.0",
|
|
@@ -47,9 +42,9 @@
|
|
|
47
42
|
"inquirer": "8.2.7",
|
|
48
43
|
"inquirer-search-checkbox": "^1.0.0",
|
|
49
44
|
"inquirer-search-list": "^1.2.6",
|
|
50
|
-
"js-yaml": "^4.
|
|
45
|
+
"js-yaml": "^4.2.0",
|
|
51
46
|
"klona": "^2.0.6",
|
|
52
|
-
"lodash": "^4.
|
|
47
|
+
"lodash": "^4.18.1",
|
|
53
48
|
"mkdirp": "^1.0.4",
|
|
54
49
|
"open": "^8.4.2",
|
|
55
50
|
"ora": "^5.4.1",
|
|
@@ -59,26 +54,32 @@
|
|
|
59
54
|
"traverse": "^0.6.11",
|
|
60
55
|
"tty-table": "^4.2.3",
|
|
61
56
|
"unique-string": "^2.0.0",
|
|
62
|
-
"uuid": "^
|
|
63
|
-
"
|
|
57
|
+
"short-uuid": "^6.0.0",
|
|
58
|
+
"uuid": "^14.0.0",
|
|
59
|
+
"winston": "^3.19.0",
|
|
64
60
|
"xdg-basedir": "^4.0.0"
|
|
65
61
|
},
|
|
62
|
+
"overrides": {
|
|
63
|
+
"@oclif/core": {
|
|
64
|
+
"picomatch": "^4.0.4"
|
|
65
|
+
}
|
|
66
|
+
},
|
|
66
67
|
"devDependencies": {
|
|
67
68
|
"@types/chai": "^4.3.20",
|
|
68
|
-
"@types/inquirer": "^9.0.
|
|
69
|
+
"@types/inquirer": "^9.0.9",
|
|
69
70
|
"@types/mkdirp": "^1.0.2",
|
|
70
71
|
"@types/mocha": "^10.0.10",
|
|
71
72
|
"@types/node": "^14.18.63",
|
|
72
73
|
"@types/sinon": "^21.0.0",
|
|
73
74
|
"@types/traverse": "^0.6.37",
|
|
74
75
|
"chai": "^4.5.0",
|
|
75
|
-
"eslint": "^
|
|
76
|
+
"eslint": "^10.5.0",
|
|
76
77
|
"eslint-config-oclif": "^6.0.62",
|
|
77
78
|
"eslint-config-oclif-typescript": "^3.1.14",
|
|
78
79
|
"fancy-test": "^2.0.42",
|
|
79
80
|
"mocha": "10.8.2",
|
|
80
81
|
"nyc": "^15.1.0",
|
|
81
|
-
"sinon": "^21.
|
|
82
|
+
"sinon": "^21.1.2",
|
|
82
83
|
"ts-node": "^10.9.2",
|
|
83
84
|
"typescript": "^4.9.5"
|
|
84
85
|
}
|