mirror of
https://github.com/strapi/strapi.git
synced 2026-05-03 16:22:30 +00:00
security: package upgrades to remove deprecated versions of boolean, tar, and glob (#25776)
* chore: upgrade tar, global-agent, dedupe yarn.lock This removes the deprecated packages: boolean, tar<7, node-gyp<12, and others * chore: upgrade inquirer, file-type, jscodeshift, supertest * chore: update better-sqlite3 * chore: upgrade pg and mysql2 * fix: use dynamic imports for inquirer esm only * test(cli): add create-strapi-app test * test(cli): add scaffold cases * chore: upgrade to rimraf 6.1.3 * chore: dedupe yarn.lock * security: update jwk-to-pem * chore: dedupe yarn.lock * chore: align inquirer version * chore: yarn.lock * test: fix inquirer imports * test(cli): support zero apps * test: fix back-end * test(cli): fix inquirer and fs * chore: remove accidental file * chore: dedupe and upgrade pinned deps
This commit is contained in:
+420
-2297
File diff suppressed because it is too large
Load Diff
@@ -28,7 +28,7 @@
|
||||
"dependencies": {
|
||||
"@strapi/plugin-users-permissions": "workspace:*",
|
||||
"@strapi/strapi": "workspace:*",
|
||||
"mysql2": "3.9.8",
|
||||
"mysql2": "3.20.0",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"react-router-dom": "6.30.3",
|
||||
|
||||
@@ -77,8 +77,8 @@ const packageJson = {
|
||||
'@strapi/plugin-users-permissions': '4.26.0',
|
||||
'@strapi/strapi': '4.26.0',
|
||||
entities: '2.2.0',
|
||||
mysql2: '^3.6.0',
|
||||
pg: '^8.11.0',
|
||||
mysql2: '3.20.0',
|
||||
pg: '8.20.0',
|
||||
react: '^18.0.0',
|
||||
'react-dom': '^18.0.0',
|
||||
'react-is': '^18.0.0',
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"dependencies": {
|
||||
"@strapi/plugin-users-permissions": "workspace:*",
|
||||
"@strapi/strapi": "workspace:*",
|
||||
"better-sqlite3": "12.6.2",
|
||||
"better-sqlite3": "12.8.0",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"react-router-dom": "6.30.3",
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"dependencies": {
|
||||
"@strapi/plugin-users-permissions": "workspace:*",
|
||||
"@strapi/strapi": "workspace:*",
|
||||
"better-sqlite3": "12.6.2",
|
||||
"better-sqlite3": "12.8.0",
|
||||
"react": "rc",
|
||||
"react-dom": "rc",
|
||||
"react-router-dom": "6.30.3",
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
"@strapi/provider-upload-aws-s3": "workspace:*",
|
||||
"@strapi/provider-upload-cloudinary": "workspace:*",
|
||||
"@strapi/strapi": "workspace:*",
|
||||
"better-sqlite3": "12.6.2",
|
||||
"better-sqlite3": "12.8.0",
|
||||
"lodash": "4.17.23",
|
||||
"mysql2": "3.9.8",
|
||||
"mysql2": "3.20.0",
|
||||
"passport-google-oauth2": "0.2.0",
|
||||
"pg": "8.11.1",
|
||||
"pg": "8.20.0",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"react-intl": "6.6.2",
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"dependencies": {
|
||||
"@strapi/plugin-users-permissions": "workspace:*",
|
||||
"@strapi/strapi": "workspace:*",
|
||||
"better-sqlite3": "12.6.2",
|
||||
"better-sqlite3": "12.8.0",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"react-router-dom": "6.30.3",
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
"@strapi/provider-upload-aws-s3": "workspace:*",
|
||||
"@strapi/provider-upload-cloudinary": "workspace:*",
|
||||
"@strapi/strapi": "workspace:*",
|
||||
"better-sqlite3": "12.6.2",
|
||||
"better-sqlite3": "12.8.0",
|
||||
"lodash": "4.17.23",
|
||||
"mysql2": "3.9.8",
|
||||
"mysql2": "3.20.0",
|
||||
"passport-google-oauth2": "0.2.0",
|
||||
"pg": "8.11.1",
|
||||
"pg": "8.20.0",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"react-router-dom": "6.30.3",
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
"styled-components": "^6.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@strapi/sdk-plugin": "^5.2.0",
|
||||
"@strapi/sdk-plugin": "^6.0.1",
|
||||
"@strapi/strapi": "workspace:*"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
+6
-6
@@ -152,9 +152,9 @@
|
||||
"find-up": "5.0.0",
|
||||
"fs-extra": "11.2.0",
|
||||
"get-port": "5.1.1",
|
||||
"glob": "13.0.0",
|
||||
"glob": "13.0.6",
|
||||
"husky": "9.1.7",
|
||||
"inquirer": "8.2.5",
|
||||
"inquirer": "9.3.8",
|
||||
"jest": "29.6.0",
|
||||
"jest-circus": "29.6.0",
|
||||
"jest-cli": "29.6.0",
|
||||
@@ -165,19 +165,19 @@
|
||||
"minimatch": "10.2.4",
|
||||
"npm-run-all": "4.1.5",
|
||||
"nx": "20.4.6",
|
||||
"plop": "4.0.1",
|
||||
"plop": "4.0.5",
|
||||
"prettier": "3.3.3",
|
||||
"prettier-2": "npm:prettier@^2",
|
||||
"qs": "6.15.0",
|
||||
"rimraf": "5.0.5",
|
||||
"rimraf": "6.1.3",
|
||||
"rollup": "4.59.0",
|
||||
"rollup-plugin-html": "0.2.1",
|
||||
"semver": "7.5.4",
|
||||
"stream-chain": "2.2.5",
|
||||
"stream-json": "1.8.0",
|
||||
"supertest": "6.3.3",
|
||||
"supertest": "7.2.2",
|
||||
"syncpack": "13.0.4",
|
||||
"tar": "7.5.10",
|
||||
"tar": "7.5.11",
|
||||
"ts-jest": "29.1.0",
|
||||
"typescript": "5.4.4",
|
||||
"vitest": "catalog:",
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
"eventsource": "2.0.2",
|
||||
"fast-safe-stringify": "2.1.1",
|
||||
"fs-extra": "11.2.0",
|
||||
"inquirer": "8.2.5",
|
||||
"inquirer": "9.3.8",
|
||||
"jsonwebtoken": "9.0.0",
|
||||
"jwks-rsa": "3.1.0",
|
||||
"lodash": "4.17.23",
|
||||
@@ -65,7 +65,7 @@
|
||||
"open": "8.4.0",
|
||||
"ora": "5.4.1",
|
||||
"pkg-up": "3.1.0",
|
||||
"tar": "7.5.10",
|
||||
"tar": "7.5.11",
|
||||
"xdg-app-paths": "8.3.0",
|
||||
"yup": "0.32.9"
|
||||
},
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import inquirer from 'inquirer';
|
||||
import { AxiosError } from 'axios';
|
||||
import { defaults } from 'lodash/fp';
|
||||
import {
|
||||
@@ -134,6 +133,7 @@ export default async (ctx: CLIContext) => {
|
||||
};
|
||||
|
||||
const projectAnswersDefaulted = defaults(defaultValues);
|
||||
const { default: inquirer } = await import('inquirer');
|
||||
const projectAnswers = await inquirer.prompt<ProjectAnswers>(questions);
|
||||
|
||||
const projectInput: ProjectInput = projectAnswersDefaulted(projectAnswers);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { DistinctQuestion } from 'inquirer';
|
||||
import type { DistinctQuestion } from 'inquirer';
|
||||
import type { ProjectAnswers } from '../../types';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import fse from 'fs-extra';
|
||||
import inquirer from 'inquirer';
|
||||
import boxen from 'boxen';
|
||||
import path from 'path';
|
||||
import chalk from 'chalk';
|
||||
@@ -51,6 +50,7 @@ const boxenOptions: boxen.Options = {
|
||||
const QUIT_OPTION = 'Quit';
|
||||
|
||||
async function promptForEnvironment(environments: string[]): Promise<string> {
|
||||
const { default: inquirer } = await import('inquirer');
|
||||
const choices = environments.map((env) => ({ name: env, value: env }));
|
||||
const { selectedEnvironment } = await inquirer.prompt([
|
||||
{
|
||||
@@ -348,6 +348,7 @@ export default async (ctx: CLIContext, opts: CmdOptions) => {
|
||||
);
|
||||
if (shouldDisplayWarning) {
|
||||
ctx.logger.log(boxen(cliConfig.projectDeployment.confirmationText, boxenOptions));
|
||||
const { default: inquirer } = await import('inquirer');
|
||||
const { confirm } = await inquirer.prompt([
|
||||
{
|
||||
type: 'confirm',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import chalk from 'chalk';
|
||||
import inquirer, { type Answers } from 'inquirer';
|
||||
import type { Answers } from 'inquirer';
|
||||
import { EnvironmentDetails, ProjectInput } from '../../services/cli-api';
|
||||
import type { CLIContext, CloudApiService } from '../../types';
|
||||
import { cloudApiFactory, tokenServiceFactory, local } from '../../services';
|
||||
@@ -91,6 +91,7 @@ async function promptUserForEnvironment(
|
||||
const { logger } = ctx;
|
||||
|
||||
try {
|
||||
const { default: inquirer } = await import('inquirer');
|
||||
const answer: LinkEnvironmentInput = await inquirer.prompt([
|
||||
{
|
||||
type: 'list',
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import inquirer from 'inquirer';
|
||||
import chalk from 'chalk';
|
||||
|
||||
import type { Answers } from 'inquirer';
|
||||
@@ -46,6 +45,7 @@ async function promptForRelink(
|
||||
existingConfig: LocalSave | null
|
||||
) {
|
||||
if (existingConfig && existingConfig.project) {
|
||||
const { default: inquirer } = await import('inquirer');
|
||||
const { shouldRelink } = await inquirer.prompt([
|
||||
{
|
||||
type: 'confirm',
|
||||
@@ -116,6 +116,7 @@ async function getUserSelection(
|
||||
): Promise<LinkProjectAnswer | null> {
|
||||
const { logger } = ctx;
|
||||
try {
|
||||
const { default: inquirer } = await import('inquirer');
|
||||
const answer: LinkProjectInput = await inquirer.prompt([
|
||||
{
|
||||
type: 'list',
|
||||
@@ -173,6 +174,7 @@ export default async (ctx: CLIContext) => {
|
||||
}
|
||||
|
||||
try {
|
||||
const { default: inquirer } = await import('inquirer');
|
||||
const { confirmAction } = await inquirer.prompt([
|
||||
{
|
||||
type: 'confirm',
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import axios, { AxiosResponse, AxiosError } from 'axios';
|
||||
import chalk from 'chalk';
|
||||
import inquirer from 'inquirer';
|
||||
import { tokenServiceFactory, cloudApiFactory } from '../services';
|
||||
import type { CloudCliConfig, CLIContext } from '../types';
|
||||
import { apiConfig } from '../config/api';
|
||||
@@ -10,6 +9,7 @@ import { setContext } from '../services/context';
|
||||
const openModule = import('open');
|
||||
|
||||
export async function promptLogin(ctx: CLIContext) {
|
||||
const { default: inquirer } = await import('inquirer');
|
||||
const response = await inquirer.prompt([
|
||||
{
|
||||
type: 'confirm',
|
||||
|
||||
@@ -57,19 +57,19 @@
|
||||
"commander": "8.3.0",
|
||||
"execa": "5.1.1",
|
||||
"fs-extra": "11.2.0",
|
||||
"inquirer": "8.2.5",
|
||||
"inquirer": "9.3.8",
|
||||
"lodash": "4.17.23",
|
||||
"node-machine-id": "^1.1.10",
|
||||
"ora": "^5.4.1",
|
||||
"rollup": "4.59.0",
|
||||
"semver": "7.5.4",
|
||||
"sort-package-json": "2.10.0",
|
||||
"tar": "7.5.10"
|
||||
"tar": "7.5.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/async-retry": "^1",
|
||||
"@types/fs-extra": "11.0.4",
|
||||
"@types/inquirer": "8.2.5",
|
||||
"@types/inquirer": "9.0.9",
|
||||
"eslint-config-custom": "5.40.0",
|
||||
"tsconfig": "5.40.0"
|
||||
},
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import inquirer from 'inquirer';
|
||||
import { cli as cloudCli, services as cloudServices } from '@strapi/cloud-cli';
|
||||
import parseToChalk from './utils/parse-to-chalk';
|
||||
|
||||
@@ -40,6 +39,7 @@ export async function handleCloudLogin(): Promise<boolean> {
|
||||
logger.error(defaultErrorMessage);
|
||||
return false;
|
||||
}
|
||||
const { default: inquirer } = await import('inquirer');
|
||||
const { userChoice } = await inquirer.prompt<{ userChoice: string }>(
|
||||
cloudApiConfig.projectCreation?.userChoice || [
|
||||
{
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import inquirer from 'inquirer';
|
||||
|
||||
async function directory() {
|
||||
const { default: inquirer } = await import('inquirer');
|
||||
const { directory } = await inquirer.prompt<{
|
||||
directory: string;
|
||||
}>([
|
||||
@@ -16,6 +15,7 @@ async function directory() {
|
||||
}
|
||||
|
||||
async function typescript() {
|
||||
const { default: inquirer } = await import('inquirer');
|
||||
const { useTypescript } = await inquirer.prompt<{
|
||||
useTypescript: boolean;
|
||||
}>([
|
||||
@@ -31,6 +31,7 @@ async function typescript() {
|
||||
}
|
||||
|
||||
async function example() {
|
||||
const { default: inquirer } = await import('inquirer');
|
||||
const { useExample } = await inquirer.prompt<{
|
||||
useExample: boolean;
|
||||
}>([
|
||||
@@ -46,6 +47,7 @@ async function example() {
|
||||
}
|
||||
|
||||
async function gitInit() {
|
||||
const { default: inquirer } = await import('inquirer');
|
||||
const { gitInit } = await inquirer.prompt<{
|
||||
gitInit: boolean;
|
||||
}>([
|
||||
@@ -61,6 +63,7 @@ async function gitInit() {
|
||||
}
|
||||
|
||||
async function installDependencies(packageManager: string) {
|
||||
const { default: inquirer } = await import('inquirer');
|
||||
const { installDependencies } = await inquirer.prompt<{
|
||||
installDependencies: boolean;
|
||||
}>([
|
||||
@@ -76,6 +79,7 @@ async function installDependencies(packageManager: string) {
|
||||
}
|
||||
|
||||
async function enableABTests() {
|
||||
const { default: inquirer } = await import('inquirer');
|
||||
const { enableABTests } = await inquirer.prompt<{
|
||||
enableABTests: boolean;
|
||||
}>([
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import inquirer from 'inquirer';
|
||||
import type { Question } from 'inquirer';
|
||||
|
||||
import type { Scope, Options, DBClient, DBConfig } from '../types';
|
||||
@@ -16,6 +15,7 @@ const DEFAULT_CONFIG: DBConfig = {
|
||||
};
|
||||
|
||||
async function dbPrompt() {
|
||||
const { default: inquirer } = await import('inquirer');
|
||||
const { useDefault } = await inquirer.prompt<{ useDefault: boolean }>([
|
||||
{
|
||||
type: 'confirm',
|
||||
@@ -105,9 +105,9 @@ export async function getDatabaseInfos(options: Options): Promise<DBConfig> {
|
||||
}
|
||||
|
||||
const sqlClientModule = {
|
||||
mysql: { mysql2: '3.9.8' },
|
||||
postgres: { pg: '8.8.0' },
|
||||
sqlite: { 'better-sqlite3': '12.6.2' },
|
||||
mysql: { mysql2: '3.20.0' },
|
||||
postgres: { pg: '8.20.0' },
|
||||
sqlite: { 'better-sqlite3': '12.8.0' },
|
||||
};
|
||||
|
||||
export function addDatabaseDependencies(scope: Scope) {
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
"fs-extra": "11.2.0",
|
||||
"highlight.js": "^10.4.1",
|
||||
"immer": "9.0.21",
|
||||
"inquirer": "8.2.5",
|
||||
"inquirer": "9.3.8",
|
||||
"invariant": "^2.2.4",
|
||||
"is-localhost-ip": "2.0.0",
|
||||
"json-logic-js": "2.0.5",
|
||||
@@ -138,7 +138,7 @@
|
||||
"react-redux": "8.1.3",
|
||||
"react-select": "5.8.0",
|
||||
"react-window": "1.8.10",
|
||||
"rimraf": "5.0.5",
|
||||
"rimraf": "6.1.3",
|
||||
"sanitize-html": "2.13.0",
|
||||
"scheduler": "0.23.0",
|
||||
"semver": "7.5.4",
|
||||
|
||||
@@ -75,16 +75,15 @@
|
||||
"cli-table3": "0.6.5",
|
||||
"commander": "8.3.0",
|
||||
"configstore": "5.0.1",
|
||||
"copyfiles": "2.4.1",
|
||||
"debug": "4.3.4",
|
||||
"delegates": "1.0.0",
|
||||
"dotenv": "16.4.5",
|
||||
"execa": "5.1.1",
|
||||
"fs-extra": "11.2.0",
|
||||
"glob": "13.0.0",
|
||||
"global-agent": "3.0.0",
|
||||
"glob": "13.0.6",
|
||||
"global-agent": "4.1.3",
|
||||
"http-errors": "2.0.0",
|
||||
"inquirer": "8.2.5",
|
||||
"inquirer": "9.3.8",
|
||||
"is-docker": "2.2.1",
|
||||
"json-logic-js": "2.0.5",
|
||||
"jsonwebtoken": "9.0.0",
|
||||
@@ -120,7 +119,7 @@
|
||||
"@types/configstore": "5.0.1",
|
||||
"@types/delegates": "1.0.0",
|
||||
"@types/fs-extra": "11.0.4",
|
||||
"@types/global-agent": "2.1.3",
|
||||
"@types/global-agent": "3.0.0",
|
||||
"@types/http-errors": "2.0.4",
|
||||
"@types/jest": "29.5.2",
|
||||
"@types/json-logic-js": "2.0.8",
|
||||
@@ -135,7 +134,7 @@
|
||||
"@types/node-schedule": "2.1.7",
|
||||
"@types/statuses": "2.0.1",
|
||||
"eslint-config-custom": "5.40.0",
|
||||
"supertest": "6.3.3",
|
||||
"supertest": "7.2.2",
|
||||
"tsconfig": "5.40.0",
|
||||
"vitest": "catalog:",
|
||||
"vitest-config": "5.40.0"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as globalAgent from 'global-agent';
|
||||
import { bootstrap as bootstrapGlobalAgent } from 'global-agent';
|
||||
import path from 'path';
|
||||
import _ from 'lodash';
|
||||
import { isFunction } from 'lodash/fp';
|
||||
@@ -515,7 +515,7 @@ class Strapi extends Container implements Core.Strapi {
|
||||
return;
|
||||
}
|
||||
|
||||
globalAgent.bootstrap();
|
||||
bootstrapGlobalAgent();
|
||||
|
||||
if (httpProxy) {
|
||||
this.log.info(`Using HTTP proxy: ${httpProxy}`);
|
||||
|
||||
@@ -58,14 +58,14 @@
|
||||
"cli-table3": "0.6.5",
|
||||
"commander": "8.3.0",
|
||||
"fs-extra": "11.2.0",
|
||||
"inquirer": "8.2.5",
|
||||
"inquirer": "9.3.8",
|
||||
"lodash": "4.17.23",
|
||||
"ora": "5.4.1",
|
||||
"resolve-cwd": "3.0.0",
|
||||
"semver": "7.5.4",
|
||||
"stream-chain": "2.2.5",
|
||||
"stream-json": "1.8.0",
|
||||
"tar": "7.5.10",
|
||||
"tar": "7.5.11",
|
||||
"tar-stream": "2.2.0",
|
||||
"ws": "8.17.1"
|
||||
},
|
||||
@@ -79,12 +79,11 @@
|
||||
"@types/semver": "7.5.0",
|
||||
"@types/stream-chain": "2.0.1",
|
||||
"@types/stream-json": "1.7.3",
|
||||
"@types/tar": "6.1.4",
|
||||
"@types/tar-stream": "2.2.2",
|
||||
"@types/ws": "^8.5.4",
|
||||
"knex": "3.0.1",
|
||||
"koa": "2.16.4",
|
||||
"rimraf": "5.0.5",
|
||||
"rimraf": "6.1.3",
|
||||
"typescript": "5.4.4"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
node_modules/
|
||||
.eslintrc.js
|
||||
jest.config.js
|
||||
coverage/
|
||||
dist/
|
||||
index.d.ts
|
||||
index.js
|
||||
|
||||
@@ -7,4 +7,7 @@ module.exports = {
|
||||
},
|
||||
testMatch: ['<rootDir>/**/*.test.ts'],
|
||||
displayName: 'Strapi',
|
||||
moduleNameMapper: {
|
||||
'^inquirer$': '<rootDir>/src/test/mocks/inquirer.ts',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -140,7 +140,6 @@
|
||||
"cli-table3": "0.6.5",
|
||||
"commander": "8.3.0",
|
||||
"concurrently": "8.2.2",
|
||||
"copyfiles": "2.4.1",
|
||||
"css-loader": "^6.10.0",
|
||||
"dotenv": "16.4.5",
|
||||
"esbuild-loader": "4.3.0",
|
||||
@@ -151,7 +150,7 @@
|
||||
"get-latest-version": "5.1.0",
|
||||
"git-url-parse": "14.0.0",
|
||||
"html-webpack-plugin": "5.6.0",
|
||||
"inquirer": "8.2.5",
|
||||
"inquirer": "9.3.8",
|
||||
"lodash": "4.17.23",
|
||||
"mini-css-extract-plugin": "2.7.7",
|
||||
"nodemon": "3.0.2",
|
||||
@@ -170,12 +169,12 @@
|
||||
"webpack-bundle-analyzer": "^4.10.1",
|
||||
"webpack-dev-middleware": "6.1.2",
|
||||
"webpack-hot-middleware": "2.26.1",
|
||||
"yalc": "1.0.0-pre.53",
|
||||
"yup": "0.32.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@strapi/ts-zen": "^0.2.0",
|
||||
"@types/fs-extra": "11.0.4",
|
||||
"@types/inquirer": "9.0.9",
|
||||
"@types/jest": "29.5.2",
|
||||
"@types/lodash": "^4.14.191",
|
||||
"@types/node": "24.10.0",
|
||||
@@ -185,7 +184,8 @@
|
||||
"jest": "29.6.0",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"tsconfig": "5.40.0"
|
||||
"tsconfig": "5.40.0",
|
||||
"yalc": "1.0.0-pre.53"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^17.0.0 || ^18.0.0",
|
||||
|
||||
@@ -2,6 +2,7 @@ import { createCommand } from 'commander';
|
||||
import { yup } from '@strapi/utils';
|
||||
import _ from 'lodash';
|
||||
import inquirer from 'inquirer';
|
||||
import type { QuestionCollection } from 'inquirer';
|
||||
import { createStrapi, compileStrapi } from '@strapi/core';
|
||||
|
||||
import { runAction } from '../../utils/helpers';
|
||||
@@ -49,10 +50,10 @@ interface Answers {
|
||||
|
||||
/**
|
||||
* It's not an observable, in reality this is
|
||||
* `ReadOnlyArray<inquirer.DistinctQuestion<Answers>>`
|
||||
* `ReadOnlyArray<DistinctQuestion<Answers>>`
|
||||
* but then the logic of the validate function needs to change.
|
||||
*/
|
||||
const promptQuestions: inquirer.QuestionCollection<Answers> = [
|
||||
const promptQuestions: QuestionCollection<Answers> = [
|
||||
{
|
||||
type: 'input',
|
||||
name: 'email',
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import _ from 'lodash';
|
||||
import inquirer from 'inquirer';
|
||||
import type { DistinctQuestion } from 'inquirer';
|
||||
import { createCommand } from 'commander';
|
||||
import { createStrapi, compileStrapi } from '@strapi/core';
|
||||
|
||||
@@ -17,7 +18,7 @@ interface Answers {
|
||||
confirm: boolean;
|
||||
}
|
||||
|
||||
const promptQuestions: ReadonlyArray<inquirer.DistinctQuestion<Answers>> = [
|
||||
const promptQuestions: ReadonlyArray<DistinctQuestion<Answers>> = [
|
||||
{ type: 'input', name: 'email', message: 'User email?' },
|
||||
{ type: 'password', name: 'password', message: 'New password?' },
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
import chalk from 'chalk';
|
||||
import { has, isString, isArray } from 'lodash/fp';
|
||||
import { prompt } from 'inquirer';
|
||||
import inquirer from 'inquirer';
|
||||
import boxen from 'boxen';
|
||||
import type { Command } from 'commander';
|
||||
|
||||
@@ -178,7 +178,7 @@ const notifyExperimentalCommand = async (name: string, { force }: { force?: bool
|
||||
);
|
||||
|
||||
if (!force) {
|
||||
const { confirmed } = await prompt({
|
||||
const { confirmed } = await inquirer.prompt({
|
||||
type: 'confirm',
|
||||
name: 'confirmed',
|
||||
message: 'Do you want to continue?',
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* inquirer v9+ is ESM-only; Jest resolves it here via moduleNameMapper in jest.config.js.
|
||||
* Override per test with jest.spyOn(inquirer, 'prompt') or prompt.mockResolvedValue(...).
|
||||
*/
|
||||
export const prompt = jest.fn().mockResolvedValue({});
|
||||
|
||||
export default {
|
||||
prompt,
|
||||
};
|
||||
@@ -81,7 +81,7 @@
|
||||
"byte-size": "8.1.1",
|
||||
"cropperjs": "1.6.1",
|
||||
"date-fns": "2.30.0",
|
||||
"file-type": "21.0.0",
|
||||
"file-type": "21.3.3",
|
||||
"formik": "2.4.5",
|
||||
"fs-extra": "11.2.0",
|
||||
"immer": "9.0.21",
|
||||
|
||||
@@ -53,17 +53,17 @@
|
||||
"@strapi/typescript-utils": "5.40.0",
|
||||
"@strapi/utils": "5.40.0",
|
||||
"chalk": "4.1.2",
|
||||
"copyfiles": "2.4.1",
|
||||
"fs-extra": "11.2.0",
|
||||
"handlebars": "4.7.7",
|
||||
"jscodeshift": "17.3.0",
|
||||
"lodash": "4.17.23",
|
||||
"plop": "4.0.1",
|
||||
"plop": "4.0.5",
|
||||
"pluralize": "8.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "11.0.4",
|
||||
"@types/jscodeshift": "0.12.0",
|
||||
"@types/jscodeshift": "17.3.0",
|
||||
"copyfiles": "2.4.1",
|
||||
"eslint-config-custom": "5.40.0",
|
||||
"outdent": "^0.8.0",
|
||||
"tsconfig": "5.40.0"
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"grant": "^5.4.8",
|
||||
"immer": "9.0.21",
|
||||
"jsonwebtoken": "9.0.0",
|
||||
"jwk-to-pem": "2.0.5",
|
||||
"jwk-to-pem": "2.0.7",
|
||||
"koa": "2.16.4",
|
||||
"koa2-ratelimit": "^1.1.3",
|
||||
"lodash": "4.17.23",
|
||||
|
||||
@@ -6,6 +6,6 @@
|
||||
"dotenv": "16.4.5",
|
||||
"lodash": "4.17.23",
|
||||
"qs": "6.15.0",
|
||||
"supertest": "6.3.3"
|
||||
"supertest": "7.2.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,9 +85,9 @@
|
||||
"devDependencies": {
|
||||
"@strapi/types": "5.40.0",
|
||||
"@types/fs-extra": "11.0.4",
|
||||
"@types/jscodeshift": "0.12.0",
|
||||
"@types/jscodeshift": "17.3.0",
|
||||
"eslint-config-custom": "5.40.0",
|
||||
"rimraf": "5.0.5"
|
||||
"rimraf": "6.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0 <=24.x.x",
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ import type { modules } from '../../../dist';
|
||||
|
||||
const DEP_NAME = 'better-sqlite3';
|
||||
const DEP_PATH = `dependencies.${DEP_NAME}`;
|
||||
const DEP_VERSION = '11.3.0';
|
||||
const DEP_VERSION = '12.8.0';
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
const path = require('path');
|
||||
const chalk = require('chalk');
|
||||
const inquirer = require('inquirer');
|
||||
const { kebabCase } = require('lodash');
|
||||
const FilesContentSearch = require('../utils/search-files-content');
|
||||
const { readAllTranslationFiles, writeAllTranslationFiles } = require('../utils/translation-files');
|
||||
@@ -26,28 +25,6 @@ const mapDuplicateValues = async (pkgs, fn) => {
|
||||
});
|
||||
};
|
||||
|
||||
const promptShouldMerge = async () => {
|
||||
return (
|
||||
await inquirer.prompt({
|
||||
type: 'confirm',
|
||||
message: 'Should merge?',
|
||||
name: 'shouldMerge',
|
||||
default: false,
|
||||
})
|
||||
).shouldMerge;
|
||||
};
|
||||
|
||||
const promptTargetKey = async (valueGroup) => {
|
||||
return (
|
||||
await inquirer.prompt({
|
||||
type: 'input',
|
||||
name: 'targetKey',
|
||||
message: 'Target key name:',
|
||||
default: `global.${kebabCase(valueGroup[0].value)}`,
|
||||
})
|
||||
).targetKey;
|
||||
};
|
||||
|
||||
const printToMerge = (valueGroup) => {
|
||||
console.log(`Value: "${chalk.yellow(valueGroup[0].value)}"`);
|
||||
|
||||
@@ -121,7 +98,29 @@ const updateTranslationFiles = (keyGroup, targetKey) => {
|
||||
|
||||
// Displays and prompt for every detected duplications
|
||||
// Triggers the merge if necessary
|
||||
const merge = async (valuesToMerge) => {
|
||||
const merge = async (inquirer, valuesToMerge) => {
|
||||
const promptShouldMerge = async () => {
|
||||
return (
|
||||
await inquirer.prompt({
|
||||
type: 'confirm',
|
||||
message: 'Should merge?',
|
||||
name: 'shouldMerge',
|
||||
default: false,
|
||||
})
|
||||
).shouldMerge;
|
||||
};
|
||||
|
||||
const promptTargetKey = async (valueGroup) => {
|
||||
return (
|
||||
await inquirer.prompt({
|
||||
type: 'input',
|
||||
name: 'targetKey',
|
||||
message: 'Target key name:',
|
||||
default: `global.${kebabCase(valueGroup[0].value)}`,
|
||||
})
|
||||
).targetKey;
|
||||
};
|
||||
|
||||
let current = 1;
|
||||
let mergedCount = 0;
|
||||
|
||||
@@ -147,11 +146,13 @@ const merge = async (valuesToMerge) => {
|
||||
};
|
||||
|
||||
(async () => {
|
||||
const { default: inquirer } = await import('inquirer');
|
||||
|
||||
await fcs.loadFiles();
|
||||
|
||||
const duplicates = findDuplicatedTranslations();
|
||||
const keyUsage = getKeysUsage(duplicates);
|
||||
const valuesToMerge = getValuesToMerge(keyUsage);
|
||||
|
||||
await merge(valuesToMerge);
|
||||
await merge(inquirer, valuesToMerge);
|
||||
})();
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"dependencies": {
|
||||
"@strapi/plugin-users-permissions": "latest",
|
||||
"@strapi/strapi": "latest",
|
||||
"better-sqlite3": "12.6.2",
|
||||
"better-sqlite3": "12.8.0",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"react-router-dom": "6.30.3",
|
||||
|
||||
@@ -43,6 +43,8 @@ After tests for remote data-transfer are implemented, there will be utility func
|
||||
|
||||
Each subdirectory within the `./tests` directory here is considered a test "domain" and will have its own test app(s) available. By default only one test app is made available unless additional ones are configured in a config.js within that test domain.
|
||||
|
||||
Some domains need no shared test app (e.g. **`create-strapi-app`** uses `testApps: 0` in `config.js`). Those domains can run in parallel with app-backed domains; the runner reserves apps only when `testApps > 0`. Others put tests in **subfolders** under the domain—e.g. `strapi/strapi/`, `strapi/data-transfer/`, `strapi/version/`. Use the `*.test.cli.js` / `*.test.cli.ts` naming from `jest.config.cli.js` at the repo root.
|
||||
|
||||
#### tests/{domain}/config.js
|
||||
|
||||
This optional file should return a function that returns a configuration object like the following complete example:
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# create-strapi-app domain
|
||||
|
||||
CLI tests for the `create-strapi-app` package. This domain uses **`testApps: 0`** (see `config.js`): tests spawn the built `bin/index.js` and write to a temp directory instead of using `TEST_APPS`.
|
||||
@@ -0,0 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = () => {
|
||||
return {
|
||||
/** Scaffolding tests use a temp dir; no shared test-app from app-template. */
|
||||
testApps: 0,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,136 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const coffee = require('coffee');
|
||||
const semver = require('semver');
|
||||
|
||||
const repoRoot = path.resolve(__dirname, '../../../..');
|
||||
const bin = path.join(repoRoot, 'packages/cli/create-strapi-app/bin/index.js');
|
||||
|
||||
const baseScaffoldArgs = ['--non-interactive', '--skip-cloud', '--no-install', '--no-git-init'];
|
||||
|
||||
function spawnCsa(args, env = {}) {
|
||||
return coffee.spawn(process.execPath, [bin, ...args], {
|
||||
cwd: repoRoot,
|
||||
env: { ...process.env, ...env },
|
||||
});
|
||||
}
|
||||
|
||||
function mkProjectDir() {
|
||||
return fs.mkdtempSync(path.join(os.tmpdir(), 'strapi-csa-cli-test-'));
|
||||
}
|
||||
|
||||
describe('create-strapi-app', () => {
|
||||
beforeAll(() => {
|
||||
if (!fs.existsSync(bin)) {
|
||||
throw new Error(
|
||||
`create-strapi-app bin missing at ${bin}; build the package first (yarn workspace create-strapi-app build)`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('scaffolds a TypeScript project by default', async () => {
|
||||
const projectDir = mkProjectDir();
|
||||
try {
|
||||
const { stdout } = await spawnCsa([projectDir, ...baseScaffoldArgs])
|
||||
.expect('code', 0)
|
||||
.end();
|
||||
|
||||
expect(stdout).toContain('Your application was created');
|
||||
expect(fs.existsSync(path.join(projectDir, 'package.json'))).toBe(true);
|
||||
expect(fs.existsSync(path.join(projectDir, 'tsconfig.json'))).toBe(true);
|
||||
expect(fs.existsSync(path.join(projectDir, 'config', 'database.ts'))).toBe(true);
|
||||
} finally {
|
||||
fs.rmSync(projectDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it('scaffolds a JavaScript project with --javascript', async () => {
|
||||
const projectDir = mkProjectDir();
|
||||
try {
|
||||
await spawnCsa([projectDir, ...baseScaffoldArgs, '--javascript'])
|
||||
.expect('code', 0)
|
||||
.end();
|
||||
|
||||
expect(fs.existsSync(path.join(projectDir, 'config', 'database.js'))).toBe(true);
|
||||
expect(fs.existsSync(path.join(projectDir, 'src', 'index.js'))).toBe(true);
|
||||
expect(fs.existsSync(path.join(projectDir, 'tsconfig.json'))).toBe(false);
|
||||
} finally {
|
||||
fs.rmSync(projectDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it('scaffolds the example template with --example', async () => {
|
||||
const projectDir = mkProjectDir();
|
||||
try {
|
||||
await spawnCsa([projectDir, ...baseScaffoldArgs, '--example'])
|
||||
.expect('code', 0)
|
||||
.end();
|
||||
|
||||
expect(fs.existsSync(path.join(projectDir, 'data', 'data.json'))).toBe(true);
|
||||
expect(fs.existsSync(path.join(projectDir, 'package.json'))).toBe(true);
|
||||
} finally {
|
||||
fs.rmSync(projectDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it('fails when --non-interactive is used without a directory', async () => {
|
||||
const { stderr, stdout } = await spawnCsa(['--non-interactive', '--skip-cloud'])
|
||||
.expect('code', 1)
|
||||
.end();
|
||||
|
||||
const out = `${stdout}${stderr}`;
|
||||
expect(out).toMatch(/non-interactive|directory/i);
|
||||
});
|
||||
|
||||
it('fails when --typescript and --javascript are both set', async () => {
|
||||
const projectDir = mkProjectDir();
|
||||
try {
|
||||
const { stderr, stdout } = await spawnCsa([
|
||||
projectDir,
|
||||
...baseScaffoldArgs,
|
||||
'--typescript',
|
||||
'--javascript',
|
||||
])
|
||||
.expect('code', 1)
|
||||
.end();
|
||||
|
||||
const out = `${stdout}${stderr}`;
|
||||
expect(out).toMatch(/cannot use both|typescript.*javascript/i);
|
||||
} finally {
|
||||
if (fs.existsSync(projectDir)) {
|
||||
fs.rmSync(projectDir, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('fails when multiple package manager flags are used', async () => {
|
||||
const projectDir = mkProjectDir();
|
||||
try {
|
||||
const { stderr, stdout } = await spawnCsa([
|
||||
projectDir,
|
||||
...baseScaffoldArgs,
|
||||
'--use-npm',
|
||||
'--use-yarn',
|
||||
])
|
||||
.expect('code', 1)
|
||||
.end();
|
||||
|
||||
const out = `${stdout}${stderr}`;
|
||||
expect(out).toMatch(/package manager|use-npm|use-yarn/i);
|
||||
} finally {
|
||||
if (fs.existsSync(projectDir)) {
|
||||
fs.rmSync(projectDir, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('prints a semver version with --version', async () => {
|
||||
const { stdout } = await spawnCsa(['--version']).expect('code', 0).end();
|
||||
|
||||
const v = stdout.trim();
|
||||
expect(semver.valid(v)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -119,14 +119,19 @@ yargs
|
||||
testAppsRequired = Math.min(selectedDomains.length, concurrency);
|
||||
}
|
||||
|
||||
// CLI domains may use testApps: 0 (e.g. create-strapi-app scaffolds to tmp, not TEST_APPS).
|
||||
let testAppPaths;
|
||||
if (testAppsRequired === 0) {
|
||||
throw new Error('No test apps to spawn');
|
||||
if (type !== 'cli') {
|
||||
throw new Error('No test apps to spawn');
|
||||
}
|
||||
testAppPaths = [];
|
||||
} else {
|
||||
testAppPaths = Array.from({ length: testAppsRequired }, (_, i) =>
|
||||
path.join(testAppDirectory, `test-app-${i}`)
|
||||
);
|
||||
}
|
||||
|
||||
const testAppPaths = Array.from({ length: testAppsRequired }, (_, i) =>
|
||||
path.join(testAppDirectory, `test-app-${i}`)
|
||||
);
|
||||
|
||||
const currentTestApps = await getCurrentTestApps(testAppDirectory);
|
||||
|
||||
/**
|
||||
@@ -407,13 +412,16 @@ module.exports = config
|
||||
await Promise.all(
|
||||
batch.map(async (domain) => {
|
||||
const config = domainConfigs[domain];
|
||||
// Must not call splice(0): that deletes the entire pool. Use splice only when n > 0.
|
||||
const neededApps =
|
||||
typeof config.testApps === 'number' && config.testApps >= 0 ? config.testApps : 1;
|
||||
|
||||
if (availableTestApps.length < config.testApps) {
|
||||
if (availableTestApps.length < neededApps) {
|
||||
console.error('Not enough test apps available; aborting');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const testApps = availableTestApps.splice(-1 * config.testApps);
|
||||
const testApps = neededApps > 0 ? availableTestApps.splice(-neededApps) : [];
|
||||
|
||||
try {
|
||||
const domainDir = path.join(testDomainRoot, domain);
|
||||
|
||||
Reference in New Issue
Block a user