Merge branch 'main' into feature/market-pagination

This commit is contained in:
Fernando Chávez 2023-03-29 14:22:47 +02:00 committed by GitHub
commit 8ebe038379
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 219 additions and 47 deletions

View File

@ -153,10 +153,11 @@ jobs:
api_ce_mysql: api_ce_mysql:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [lint, unit_back, unit_front] needs: [lint, unit_back, unit_front]
name: '[CE] API Integration (mysql, node: ${{ matrix.node }})' name: '[CE] API Integration (mysql:latest, client: ${{ matrix.db_client }}, node: ${{ matrix.node }})'
strategy: strategy:
matrix: matrix:
node: [14, 16, 18] node: [14, 16, 18]
db_client: ['mysql', 'mysql2']
services: services:
mysql: mysql:
image: bitnami/mysql:latest image: bitnami/mysql:latest
@ -186,15 +187,16 @@ jobs:
- run: yarn install --immutable - run: yarn install --immutable
- uses: ./.github/actions/run-api-tests - uses: ./.github/actions/run-api-tests
with: with:
dbOptions: '--dbclient=mysql --dbhost=localhost --dbport=3306 --dbname=strapi_test --dbusername=strapi --dbpassword=strapi' dbOptions: '--dbclient=${{ matrix.db_client }} --dbhost=localhost --dbport=3306 --dbname=strapi_test --dbusername=strapi --dbpassword=strapi'
api_ce_mysql_5: api_ce_mysql_5:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [lint, unit_back, unit_front] needs: [lint, unit_back, unit_front]
name: '[CE] API Integration (mysql:5 , node: ${{ matrix.node }})' name: '[CE] API Integration (mysql:5, client: ${{ matrix.db_client }} , node: ${{ matrix.node }})'
strategy: strategy:
matrix: matrix:
node: [14, 16, 18] node: [14, 16, 18]
db_client: ['mysql', 'mysql2']
services: services:
mysql: mysql:
image: bitnami/mysql:5.7 image: bitnami/mysql:5.7
@ -223,12 +225,12 @@ jobs:
- run: yarn install --immutable - run: yarn install --immutable
- uses: ./.github/actions/run-api-tests - uses: ./.github/actions/run-api-tests
with: with:
dbOptions: '--dbclient=mysql --dbhost=localhost --dbport=3306 --dbname=strapi_test --dbusername=strapi --dbpassword=strapi' dbOptions: '--dbclient=${{ matrix.db_client }} --dbhost=localhost --dbport=3306 --dbname=strapi_test --dbusername=strapi --dbpassword=strapi'
api_ce_sqlite: api_ce_sqlite:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [lint, unit_back, unit_front] needs: [lint, unit_back, unit_front]
name: '[CE] API Integration (sqlite: ${{ matrix.sqlite_pkg }}, node: ${{ matrix.node }})' name: '[CE] API Integration (sqlite, client: ${{ matrix.sqlite_pkg }}, node: ${{ matrix.node }})'
strategy: strategy:
matrix: matrix:
node: [14, 16, 18] node: [14, 16, 18]
@ -297,13 +299,14 @@ jobs:
api_ee_mysql: api_ee_mysql:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [lint, unit_back, unit_front] needs: [lint, unit_back, unit_front]
name: '[EE] API Integration (mysql, node: ${{ matrix.node }})' name: '[EE] API Integration (mysql:latest, client: ${{ matrix.db_client }}, node: ${{ matrix.node }})'
if: github.event.pull_request.head.repo.full_name == github.repository && !(github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]') if: github.event.pull_request.head.repo.full_name == github.repository && !(github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]')
env: env:
STRAPI_LICENSE: ${{ secrets.strapiLicense }} STRAPI_LICENSE: ${{ secrets.strapiLicense }}
strategy: strategy:
matrix: matrix:
node: [14, 16, 18] node: [14, 16, 18]
db_client: ['mysql', 'mysql2']
services: services:
mysql: mysql:
image: bitnami/mysql:latest image: bitnami/mysql:latest
@ -333,13 +336,13 @@ jobs:
- run: yarn install --immutable - run: yarn install --immutable
- uses: ./.github/actions/run-api-tests - uses: ./.github/actions/run-api-tests
with: with:
dbOptions: '--dbclient=mysql --dbhost=localhost --dbport=3306 --dbname=strapi_test --dbusername=strapi --dbpassword=strapi' dbOptions: '--dbclient=${{ matrix.db_client }} --dbhost=localhost --dbport=3306 --dbname=strapi_test --dbusername=strapi --dbpassword=strapi'
runEE: true runEE: true
api_ee_sqlite: api_ee_sqlite:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [lint, unit_back, unit_front] needs: [lint, unit_back, unit_front]
name: '[EE] API Integration (sqlite: ${{ matrix.sqlite_pkg }}, node: ${{ matrix.node }})' name: '[EE] API Integration (sqlite, client: ${{ matrix.sqlite_pkg }}, node: ${{ matrix.node }})'
if: github.event.pull_request.head.repo.full_name == github.repository && !(github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]') if: github.event.pull_request.head.repo.full_name == github.repository && !(github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]')
env: env:
STRAPI_LICENSE: ${{ secrets.strapiLicense }} STRAPI_LICENSE: ${{ secrets.strapiLicense }}

View File

@ -28,6 +28,17 @@ const mysql = {
}, },
}; };
const mysql2 = {
client: 'mysql2',
connection: {
database: 'strapi',
user: 'strapi',
password: 'strapi',
port: 3306,
host: 'localhost',
},
};
const mariadb = { const mariadb = {
client: 'mysql', client: 'mysql',
connection: { connection: {
@ -41,6 +52,7 @@ const mariadb = {
const db = { const db = {
mysql, mysql,
mysql2,
sqlite, sqlite,
postgres, postgres,
mariadb, mariadb,

View File

@ -27,6 +27,7 @@
"better-sqlite3": "8.0.1", "better-sqlite3": "8.0.1",
"lodash": "4.17.21", "lodash": "4.17.21",
"mysql": "2.18.1", "mysql": "2.18.1",
"mysql2": "3.2.0",
"passport-google-oauth2": "0.2.0", "passport-google-oauth2": "0.2.0",
"pg": "8.8.0", "pg": "8.8.0",
"react": "^17.0.2", "react": "^17.0.2",

View File

@ -8,6 +8,8 @@ const constants = require('../services/constants');
describe('Admin API Token v2 CRUD (api)', () => { describe('Admin API Token v2 CRUD (api)', () => {
let rq; let rq;
let strapi; let strapi;
let now;
let nowSpy;
const deleteAllTokens = async () => { const deleteAllTokens = async () => {
const tokens = await strapi.admin.services['api-token'].list(); const tokens = await strapi.admin.services['api-token'].list();
@ -22,6 +24,9 @@ describe('Admin API Token v2 CRUD (api)', () => {
beforeAll(async () => { beforeAll(async () => {
strapi = await createStrapiInstance(); strapi = await createStrapiInstance();
rq = await createAuthRequest({ strapi }); rq = await createAuthRequest({ strapi });
// To eliminate latency in the request and predict the expiry timestamp, we freeze Date.now()
now = Date.now();
nowSpy = jest.spyOn(Date, 'now').mockImplementation(() => now);
// delete tokens // delete tokens
await deleteAllTokens(); await deleteAllTokens();
@ -29,9 +34,14 @@ describe('Admin API Token v2 CRUD (api)', () => {
// Cleanup actions // Cleanup actions
afterAll(async () => { afterAll(async () => {
nowSpy.mockRestore();
await strapi.destroy(); await strapi.destroy();
}); });
afterEach(async () => {
await deleteAllTokens();
});
// create a predictable valid token that we can test with (delete, list, etc) // create a predictable valid token that we can test with (delete, list, etc)
let currentTokens = 0; let currentTokens = 0;
const createValidToken = async (token = {}) => { const createValidToken = async (token = {}) => {
@ -178,9 +188,6 @@ describe('Admin API Token v2 CRUD (api)', () => {
}); });
test('Creates a token with a 7-day lifespan', async () => { test('Creates a token with a 7-day lifespan', async () => {
const now = Date.now();
jest.useFakeTimers('modern').setSystemTime(now);
const body = { const body = {
name: 'api-token_tests-lifespan7', name: 'api-token_tests-lifespan7',
description: 'api-token_tests-description', description: 'api-token_tests-description',
@ -217,9 +224,6 @@ describe('Admin API Token v2 CRUD (api)', () => {
}); });
test('Creates a token with a 30-day lifespan', async () => { test('Creates a token with a 30-day lifespan', async () => {
const now = Date.now();
jest.useFakeTimers('modern').setSystemTime(now);
const body = { const body = {
name: 'api-token_tests-lifespan30', name: 'api-token_tests-lifespan30',
description: 'api-token_tests-description', description: 'api-token_tests-description',
@ -256,9 +260,6 @@ describe('Admin API Token v2 CRUD (api)', () => {
}); });
test('Creates a token with a 90-day lifespan', async () => { test('Creates a token with a 90-day lifespan', async () => {
const now = Date.now();
jest.useFakeTimers('modern').setSystemTime(now);
const body = { const body = {
name: 'api-token_tests-lifespan90', name: 'api-token_tests-lifespan90',
description: 'api-token_tests-description', description: 'api-token_tests-description',

View File

@ -8,6 +8,8 @@ const constants = require('../services/constants');
describe('Admin Transfer Token CRUD (api)', () => { describe('Admin Transfer Token CRUD (api)', () => {
let rq; let rq;
let strapi; let strapi;
let now;
let nowSpy;
const FULL_ACCESS = ['push', 'pull']; const FULL_ACCESS = ['push', 'pull'];
@ -24,6 +26,9 @@ describe('Admin Transfer Token CRUD (api)', () => {
beforeAll(async () => { beforeAll(async () => {
strapi = await createStrapiInstance(); strapi = await createStrapiInstance();
rq = await createAuthRequest({ strapi }); rq = await createAuthRequest({ strapi });
// To eliminate latency in the request and predict the expiry timestamp, we freeze Date.now()
now = Date.now();
nowSpy = jest.spyOn(Date, 'now').mockImplementation(() => now);
// delete tokens // delete tokens
await deleteAllTokens(); await deleteAllTokens();
@ -31,9 +36,14 @@ describe('Admin Transfer Token CRUD (api)', () => {
// Cleanup actions // Cleanup actions
afterAll(async () => { afterAll(async () => {
nowSpy.mockRestore();
await strapi.destroy(); await strapi.destroy();
}); });
afterEach(async () => {
await deleteAllTokens();
});
// create a predictable valid token that we can test with (delete, list, etc) // create a predictable valid token that we can test with (delete, list, etc)
let currentTokens = 0; let currentTokens = 0;
const createValidToken = async (token = {}) => { const createValidToken = async (token = {}) => {
@ -125,9 +135,6 @@ describe('Admin Transfer Token CRUD (api)', () => {
}); });
test('Creates a transfer token with a 7-day lifespan', async () => { test('Creates a transfer token with a 7-day lifespan', async () => {
const now = Date.now();
jest.useFakeTimers('modern').setSystemTime(now);
const body = { const body = {
name: 'transfer-token_tests-lifespan7', name: 'transfer-token_tests-lifespan7',
description: 'transfer-token_tests-description', description: 'transfer-token_tests-description',
@ -158,14 +165,9 @@ describe('Admin Transfer Token CRUD (api)', () => {
// Datetime stored in some databases may lose ms accuracy, so allow a range of 2 seconds for timing edge cases // Datetime stored in some databases may lose ms accuracy, so allow a range of 2 seconds for timing edge cases
expect(Date.parse(res.body.data.expiresAt)).toBeGreaterThan(now + body.lifespan - 2000); expect(Date.parse(res.body.data.expiresAt)).toBeGreaterThan(now + body.lifespan - 2000);
expect(Date.parse(res.body.data.expiresAt)).toBeLessThan(now + body.lifespan + 2000); expect(Date.parse(res.body.data.expiresAt)).toBeLessThan(now + body.lifespan + 2000);
jest.useRealTimers();
}); });
test('Creates a transfer token with a 30-day lifespan', async () => { test('Creates a transfer token with a 30-day lifespan', async () => {
const now = Date.now();
jest.useFakeTimers('modern').setSystemTime(now);
const body = { const body = {
name: 'transfer-token_tests-lifespan30', name: 'transfer-token_tests-lifespan30',
description: 'transfer-token_tests-description', description: 'transfer-token_tests-description',
@ -196,14 +198,9 @@ describe('Admin Transfer Token CRUD (api)', () => {
// Datetime stored in some databases may lose ms accuracy, so allow a range of 2 seconds for timing edge cases // Datetime stored in some databases may lose ms accuracy, so allow a range of 2 seconds for timing edge cases
expect(Date.parse(res.body.data.expiresAt)).toBeGreaterThan(now + body.lifespan - 2000); expect(Date.parse(res.body.data.expiresAt)).toBeGreaterThan(now + body.lifespan - 2000);
expect(Date.parse(res.body.data.expiresAt)).toBeLessThan(now + body.lifespan + 2000); expect(Date.parse(res.body.data.expiresAt)).toBeLessThan(now + body.lifespan + 2000);
jest.useRealTimers();
}); });
test('Creates a transfer token with a 90-day lifespan', async () => { test('Creates a transfer token with a 90-day lifespan', async () => {
const now = Date.now();
jest.useFakeTimers('modern').setSystemTime(now);
const body = { const body = {
name: 'transfer-token_tests-lifespan90', name: 'transfer-token_tests-lifespan90',
description: 'transfer-token_tests-description', description: 'transfer-token_tests-description',
@ -234,8 +231,6 @@ describe('Admin Transfer Token CRUD (api)', () => {
// Datetime stored in some databases may lose ms accuracy, so allow a range of 2 seconds for timing edge cases // Datetime stored in some databases may lose ms accuracy, so allow a range of 2 seconds for timing edge cases
expect(Date.parse(res.body.data.expiresAt)).toBeGreaterThan(now + body.lifespan - 2000); expect(Date.parse(res.body.data.expiresAt)).toBeGreaterThan(now + body.lifespan - 2000);
expect(Date.parse(res.body.data.expiresAt)).toBeLessThan(now + body.lifespan + 2000); expect(Date.parse(res.body.data.expiresAt)).toBeLessThan(now + body.lifespan + 2000);
jest.useRealTimers();
}); });
test('Creates a transfer token with a null lifespan', async () => { test('Creates a transfer token with a null lifespan', async () => {
@ -492,6 +487,8 @@ describe('Admin Transfer Token CRUD (api)', () => {
}); });
test('Returns a 404 if the resource to update does not exist', async () => { test('Returns a 404 if the resource to update does not exist', async () => {
await deleteAllTokens();
const body = { const body = {
name: 'transfer-token_tests-updated-name', name: 'transfer-token_tests-updated-name',
description: 'transfer-token_tests-updated-description', description: 'transfer-token_tests-updated-description',

View File

@ -1,5 +1,8 @@
'use strict'; 'use strict';
/**
* Require our dialect-specific code
*/
const getDialectClass = (client) => { const getDialectClass = (client) => {
switch (client) { switch (client) {
case 'postgres': case 'postgres':
@ -13,12 +16,34 @@ const getDialectClass = (client) => {
} }
}; };
/**
* Get the dialect of a database client
*
* @param {string} The client value from a project database configuration
* @returns {string} The dialect of that client
*/
const getDialectName = (client) => {
switch (client) {
case 'postgres':
return 'postgres';
case 'mysql':
case 'mysql2':
return 'mysql';
case 'sqlite':
case 'sqlite-legacy':
return 'sqlite';
default:
throw new Error(`Unknown dialect ${client}`);
}
};
const getDialect = (db) => { const getDialect = (db) => {
const { client } = db.config.connection; const { client } = db.config.connection;
const dialectName = getDialectName(client);
const constructor = getDialectClass(client); const constructor = getDialectClass(dialectName);
const dialect = new constructor(db); const dialect = new constructor(db);
dialect.client = client; dialect.client = dialectName;
return dialect; return dialect;
}; };

View File

@ -26,6 +26,27 @@ module.exports = ({ env }) => {
}, },
pool: { min: env.int('DATABASE_POOL_MIN', 2), max: env.int('DATABASE_POOL_MAX', 10) }, pool: { min: env.int('DATABASE_POOL_MIN', 2), max: env.int('DATABASE_POOL_MAX', 10) },
}, },
mysql2: {
connection: {
host: env('DATABASE_HOST', 'localhost'),
port: env.int('DATABASE_PORT', 3306),
database: env('DATABASE_NAME', 'strapi'),
user: env('DATABASE_USERNAME', 'strapi'),
password: env('DATABASE_PASSWORD', 'strapi'),
ssl: env.bool('DATABASE_SSL', false) && {
key: env('DATABASE_SSL_KEY', undefined),
cert: env('DATABASE_SSL_CERT', undefined),
ca: env('DATABASE_SSL_CA', undefined),
capath: env('DATABASE_SSL_CAPATH', undefined),
cipher: env('DATABASE_SSL_CIPHER', undefined),
rejectUnauthorized: env.bool(
'DATABASE_SSL_REJECT_UNAUTHORIZED',
true
),
},
},
pool: { min: env.int('DATABASE_POOL_MIN', 2), max: env.int('DATABASE_POOL_MAX', 10) },
},
postgres: { postgres: {
connection: { connection: {
connectionString: env('DATABASE_URL'), connectionString: env('DATABASE_URL'),

View File

@ -0,0 +1,8 @@
# Database
DATABASE_CLIENT=<%= client %>
DATABASE_HOST=<%= connection.host %>
DATABASE_PORT=<%= connection.port %>
DATABASE_NAME=<%= connection.database %>
DATABASE_USERNAME=<%= connection.username %>
DATABASE_PASSWORD=<%= connection.password %>
DATABASE_SSL=<%= connection.ssl %>

View File

@ -26,6 +26,27 @@ export default ({ env }) => {
}, },
pool: { min: env.int('DATABASE_POOL_MIN', 2), max: env.int('DATABASE_POOL_MAX', 10) }, pool: { min: env.int('DATABASE_POOL_MIN', 2), max: env.int('DATABASE_POOL_MAX', 10) },
}, },
mysql2: {
connection: {
host: env('DATABASE_HOST', 'localhost'),
port: env.int('DATABASE_PORT', 3306),
database: env('DATABASE_NAME', 'strapi'),
user: env('DATABASE_USERNAME', 'strapi'),
password: env('DATABASE_PASSWORD', 'strapi'),
ssl: env.bool('DATABASE_SSL', false) && {
key: env('DATABASE_SSL_KEY', undefined),
cert: env('DATABASE_SSL_CERT', undefined),
ca: env('DATABASE_SSL_CA', undefined),
capath: env('DATABASE_SSL_CAPATH', undefined),
cipher: env('DATABASE_SSL_CIPHER', undefined),
rejectUnauthorized: env.bool(
'DATABASE_SSL_REJECT_UNAUTHORIZED',
true
),
},
},
pool: { min: env.int('DATABASE_POOL_MIN', 2), max: env.int('DATABASE_POOL_MAX', 10) },
},
postgres: { postgres: {
connection: { connection: {
connectionString: env('DATABASE_URL'), connectionString: env('DATABASE_URL'),

View File

@ -2,6 +2,7 @@
const sqlClientModule = { const sqlClientModule = {
mysql: { mysql: '2.18.1' }, mysql: { mysql: '2.18.1' },
mysql2: { mysql2: '3.2.0' },
postgres: { pg: '8.8.0' }, postgres: { pg: '8.8.0' },
sqlite: { 'better-sqlite3': '8.0.1' }, sqlite: { 'better-sqlite3': '8.0.1' },
'sqlite-legacy': { sqlite3: '^5.0.2' }, 'sqlite-legacy': { sqlite3: '^5.0.2' },
@ -11,16 +12,11 @@ const sqlClientModule = {
* Client dependencies * Client dependencies
*/ */
module.exports = ({ client }) => { module.exports = ({ client }) => {
switch (client) { if (client in sqlClientModule) {
case 'sqlite':
case 'sqlite-legacy':
case 'postgres':
case 'mysql':
return { return {
...sqlClientModule[client], ...sqlClientModule[client],
}; };
default:
throw new Error(`Invalid client "${client}"`);
} }
throw new Error(`Invalid client "${client}"`);
}; };

View File

@ -33,6 +33,16 @@ const databases = {
password: 'strapi', password: 'strapi',
}, },
}, },
mysql2: {
client: 'mysql2',
connection: {
host: '127.0.0.1',
port: 3306,
database: 'strapi_test',
username: 'strapi',
password: 'strapi',
},
},
sqlite: { sqlite: {
client: 'sqlite', client: 'sqlite',
connection: { connection: {
@ -80,7 +90,7 @@ yargs
}) })
.command( .command(
'$0', '$0',
'run end to end tests', 'run API integration tests',
(yarg) => { (yarg) => {
yarg.option('database', { yarg.option('database', {
alias: 'db', alias: 'db',

View File

@ -14095,6 +14095,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"denque@npm:^2.1.0":
version: 2.1.0
resolution: "denque@npm:2.1.0"
checksum: 1d4ae1d05e59ac3a3481e7b478293f4b4c813819342273f3d5b826c7ffa9753c520919ba264f377e09108d24ec6cf0ec0ac729a5686cbb8f32d797126c5dae74
languageName: node
linkType: hard
"depd@npm:2.0.0, depd@npm:^2.0.0, depd@npm:~2.0.0": "depd@npm:2.0.0, depd@npm:^2.0.0, depd@npm:~2.0.0":
version: 2.0.0 version: 2.0.0
resolution: "depd@npm:2.0.0" resolution: "depd@npm:2.0.0"
@ -17008,6 +17015,15 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"generate-function@npm:^2.3.1":
version: 2.3.1
resolution: "generate-function@npm:2.3.1"
dependencies:
is-property: ^1.0.2
checksum: 652f083de206ead2bae4caf9c7eeb465e8d98c0b8ed2a29c6afc538cef0785b5c6eea10548f1e13cc586d3afd796c13c830c2cb3dc612ec2457b2aadda5f57c9
languageName: node
linkType: hard
"gensync@npm:^1.0.0-beta.1, gensync@npm:^1.0.0-beta.2": "gensync@npm:^1.0.0-beta.1, gensync@npm:^1.0.0-beta.2":
version: 1.0.0-beta.2 version: 1.0.0-beta.2
resolution: "gensync@npm:1.0.0-beta.2" resolution: "gensync@npm:1.0.0-beta.2"
@ -17202,6 +17218,7 @@ __metadata:
better-sqlite3: 8.0.1 better-sqlite3: 8.0.1
lodash: 4.17.21 lodash: 4.17.21
mysql: 2.18.1 mysql: 2.18.1
mysql2: 3.2.0
passport-google-oauth2: 0.2.0 passport-google-oauth2: 0.2.0
pg: 8.8.0 pg: 8.8.0
react: ^17.0.2 react: ^17.0.2
@ -18523,7 +18540,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2": "iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2, iconv-lite@npm:^0.6.3":
version: 0.6.3 version: 0.6.3
resolution: "iconv-lite@npm:0.6.3" resolution: "iconv-lite@npm:0.6.3"
dependencies: dependencies:
@ -19379,6 +19396,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"is-property@npm:^1.0.2":
version: 1.0.2
resolution: "is-property@npm:1.0.2"
checksum: 33b661a3690bcc88f7e47bb0a21b9e3187e76a317541ea7ec5e8096d954f441b77a46d8930c785f7fbf4ef8dfd624c25495221e026e50f74c9048fe501773be5
languageName: node
linkType: hard
"is-regex@npm:^1.1.2, is-regex@npm:^1.1.4": "is-regex@npm:^1.1.2, is-regex@npm:^1.1.4":
version: 1.1.4 version: 1.1.4
resolution: "is-regex@npm:1.1.4" resolution: "is-regex@npm:1.1.4"
@ -21752,6 +21776,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"long@npm:^5.2.1":
version: 5.2.1
resolution: "long@npm:5.2.1"
checksum: 9264da12d1b7df67e5aa6da4498144293caf1ad12e7f092efe4e9a2d32c53f0bbf7334f7cef997080a2a3af061142558ab366efa71698d98b1cdb883477445a7
languageName: node
linkType: hard
"longest-streak@npm:^2.0.0": "longest-streak@npm:^2.0.0":
version: 2.0.4 version: 2.0.4
resolution: "longest-streak@npm:2.0.4" resolution: "longest-streak@npm:2.0.4"
@ -21847,6 +21878,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"lru-cache@npm:^7.14.1":
version: 7.18.3
resolution: "lru-cache@npm:7.18.3"
checksum: e550d772384709deea3f141af34b6d4fa392e2e418c1498c078de0ee63670f1f46f5eee746e8ef7e69e1c895af0d4224e62ee33e66a543a14763b0f2e74c1356
languageName: node
linkType: hard
"lru_map@npm:^0.3.3": "lru_map@npm:^0.3.3":
version: 0.3.3 version: 0.3.3
resolution: "lru_map@npm:0.3.3" resolution: "lru_map@npm:0.3.3"
@ -22980,6 +23018,22 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"mysql2@npm:3.2.0":
version: 3.2.0
resolution: "mysql2@npm:3.2.0"
dependencies:
denque: ^2.1.0
generate-function: ^2.3.1
iconv-lite: ^0.6.3
long: ^5.2.1
lru-cache: ^7.14.1
named-placeholders: ^1.1.3
seq-queue: ^0.0.5
sqlstring: ^2.3.2
checksum: 7885d3b4f575e7321754de14bb4fadb80d4705d5b00f8b645d760ae7a0f3170ac6d4fe6e7b9307e698fe84c3ee047d7c2652f01b95c9393f56eace993f2952ab
languageName: node
linkType: hard
"mysql@npm:2.18.1": "mysql@npm:2.18.1":
version: 2.18.1 version: 2.18.1
resolution: "mysql@npm:2.18.1" resolution: "mysql@npm:2.18.1"
@ -23003,6 +23057,15 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"named-placeholders@npm:^1.1.3":
version: 1.1.3
resolution: "named-placeholders@npm:1.1.3"
dependencies:
lru-cache: ^7.14.1
checksum: 7834adc91e92ae1b9c4413384e3ccd297de5168bb44017ff0536705ddc4db421723bd964607849265feb3f6ded390f84cf138e5925f22f7c13324f87a803dc73
languageName: node
linkType: hard
"nan@npm:^2.12.1": "nan@npm:^2.12.1":
version: 2.16.0 version: 2.16.0
resolution: "nan@npm:2.16.0" resolution: "nan@npm:2.16.0"
@ -27778,6 +27841,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"seq-queue@npm:^0.0.5":
version: 0.0.5
resolution: "seq-queue@npm:0.0.5"
checksum: f8695a6cb613e1b378b9686cde4ea626944091a412fc1c9d24c5039283d4351dd115f4505e4cf103d3a2e4a9a6a72fc7698fdce703839fb1fec9627aa4ce5563
languageName: node
linkType: hard
"serialize-javascript@npm:^4.0.0": "serialize-javascript@npm:^4.0.0":
version: 4.0.0 version: 4.0.0
resolution: "serialize-javascript@npm:4.0.0" resolution: "serialize-javascript@npm:4.0.0"
@ -28482,6 +28552,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"sqlstring@npm:^2.3.2":
version: 2.3.3
resolution: "sqlstring@npm:2.3.3"
checksum: 1e7e2d51c38a0cf7372e875408ca100b6e0c9a941ab7773975ea41fb36e5528e404dc787689be855780cf6d0a829ff71027964ae3a05a7446e91dce26672fda7
languageName: node
linkType: hard
"sshpk@npm:^1.7.0": "sshpk@npm:^1.7.0":
version: 1.17.0 version: 1.17.0
resolution: "sshpk@npm:1.17.0" resolution: "sshpk@npm:1.17.0"