first commit
This commit is contained in:
commit
4e92b01e01
|
|
@ -0,0 +1,338 @@
|
||||||
|
const mysql = require('mysql')
|
||||||
|
let a = `ABG
|
||||||
|
ASK
|
||||||
|
AX1
|
||||||
|
ABC
|
||||||
|
ADT
|
||||||
|
AGL
|
||||||
|
AIZ
|
||||||
|
A4N
|
||||||
|
ALQ
|
||||||
|
ALU
|
||||||
|
AWC
|
||||||
|
AMC
|
||||||
|
AMP
|
||||||
|
ALD
|
||||||
|
ANN
|
||||||
|
ANZ
|
||||||
|
APA
|
||||||
|
APM
|
||||||
|
ARB
|
||||||
|
LTM
|
||||||
|
ARF
|
||||||
|
ARG
|
||||||
|
ALL
|
||||||
|
ASX
|
||||||
|
ALX
|
||||||
|
AUB
|
||||||
|
AIA
|
||||||
|
AD8
|
||||||
|
AZJ
|
||||||
|
ABB
|
||||||
|
AAC
|
||||||
|
AFI
|
||||||
|
AUI
|
||||||
|
AVZ
|
||||||
|
AZS
|
||||||
|
BOQ
|
||||||
|
BAP
|
||||||
|
BPT
|
||||||
|
BGA
|
||||||
|
BGL
|
||||||
|
BEN
|
||||||
|
BHP
|
||||||
|
BKI
|
||||||
|
SQ2
|
||||||
|
BSL
|
||||||
|
BLY
|
||||||
|
BLD
|
||||||
|
BOE
|
||||||
|
BRN
|
||||||
|
BXB
|
||||||
|
BRG
|
||||||
|
BKW
|
||||||
|
BGP
|
||||||
|
BFL
|
||||||
|
BWP
|
||||||
|
CMM
|
||||||
|
CAR
|
||||||
|
CIN
|
||||||
|
CNI
|
||||||
|
CIP
|
||||||
|
CTT
|
||||||
|
CGF
|
||||||
|
CIA
|
||||||
|
CHC
|
||||||
|
CLW
|
||||||
|
CQR
|
||||||
|
CQE
|
||||||
|
CNU
|
||||||
|
CWY
|
||||||
|
CUV
|
||||||
|
COH
|
||||||
|
CDA
|
||||||
|
COL
|
||||||
|
CKF
|
||||||
|
CBA
|
||||||
|
CPU
|
||||||
|
CEN
|
||||||
|
CRN
|
||||||
|
CTD
|
||||||
|
CGC
|
||||||
|
CCP
|
||||||
|
CMW
|
||||||
|
CSL
|
||||||
|
CSR
|
||||||
|
DBI
|
||||||
|
DTL
|
||||||
|
DYL
|
||||||
|
DEG
|
||||||
|
DRR
|
||||||
|
DXS
|
||||||
|
DXI
|
||||||
|
DDR
|
||||||
|
DUI
|
||||||
|
DJW
|
||||||
|
DHG
|
||||||
|
DMP
|
||||||
|
DOW
|
||||||
|
APE
|
||||||
|
EBO
|
||||||
|
ELD
|
||||||
|
EMR
|
||||||
|
EDV
|
||||||
|
ERA
|
||||||
|
EQT
|
||||||
|
EVN
|
||||||
|
EVT
|
||||||
|
FPH
|
||||||
|
FPR
|
||||||
|
FBU
|
||||||
|
FLT
|
||||||
|
FMG
|
||||||
|
FRW
|
||||||
|
GUD
|
||||||
|
GEM
|
||||||
|
GNE
|
||||||
|
GMD
|
||||||
|
GTK
|
||||||
|
GOR
|
||||||
|
GMG
|
||||||
|
GPT
|
||||||
|
GQG
|
||||||
|
GNC
|
||||||
|
GOZ
|
||||||
|
HSN
|
||||||
|
HVN
|
||||||
|
HLS
|
||||||
|
HCW
|
||||||
|
HGH
|
||||||
|
HLI
|
||||||
|
HMC
|
||||||
|
HDN
|
||||||
|
HUB
|
||||||
|
IEL
|
||||||
|
IGO
|
||||||
|
ILU
|
||||||
|
IMD
|
||||||
|
IMU
|
||||||
|
IPL
|
||||||
|
IFT
|
||||||
|
INA
|
||||||
|
ING
|
||||||
|
IFL
|
||||||
|
IAG
|
||||||
|
IPH
|
||||||
|
IRE
|
||||||
|
JHX
|
||||||
|
JBH
|
||||||
|
JLG
|
||||||
|
JDO
|
||||||
|
JIN
|
||||||
|
KAR
|
||||||
|
KLS
|
||||||
|
KKC
|
||||||
|
LSF
|
||||||
|
LFS
|
||||||
|
LLC
|
||||||
|
LFG
|
||||||
|
360
|
||||||
|
LIC
|
||||||
|
LNW
|
||||||
|
LNK
|
||||||
|
LTR
|
||||||
|
LOV
|
||||||
|
LYC
|
||||||
|
MGH
|
||||||
|
MQG
|
||||||
|
MAQ
|
||||||
|
MAD
|
||||||
|
MAF
|
||||||
|
MFG
|
||||||
|
MGF
|
||||||
|
MMS
|
||||||
|
MPL
|
||||||
|
MP1
|
||||||
|
MCY
|
||||||
|
MEZ
|
||||||
|
MTS
|
||||||
|
MXT
|
||||||
|
MFF
|
||||||
|
MIN
|
||||||
|
MGR
|
||||||
|
MRM
|
||||||
|
MND
|
||||||
|
NAN
|
||||||
|
NAB
|
||||||
|
NSR
|
||||||
|
NWL
|
||||||
|
NEU
|
||||||
|
NHC
|
||||||
|
NEM
|
||||||
|
NWS
|
||||||
|
NXT
|
||||||
|
NHF
|
||||||
|
NIC
|
||||||
|
NCK
|
||||||
|
NEC
|
||||||
|
NST
|
||||||
|
NWH
|
||||||
|
NUF
|
||||||
|
OCL
|
||||||
|
OML
|
||||||
|
ORI
|
||||||
|
ORG
|
||||||
|
ORA
|
||||||
|
PDN
|
||||||
|
PRN
|
||||||
|
PPT
|
||||||
|
PRU
|
||||||
|
PXA
|
||||||
|
PLS
|
||||||
|
PNI
|
||||||
|
PL8
|
||||||
|
PGF
|
||||||
|
PNV
|
||||||
|
PMV
|
||||||
|
PME
|
||||||
|
PFP
|
||||||
|
PSI
|
||||||
|
PWH
|
||||||
|
QAN
|
||||||
|
QBE
|
||||||
|
QAL
|
||||||
|
QUB
|
||||||
|
RMS
|
||||||
|
RHC
|
||||||
|
REA
|
||||||
|
RED
|
||||||
|
RDX
|
||||||
|
REH
|
||||||
|
RGN
|
||||||
|
REG
|
||||||
|
RRL
|
||||||
|
RWC
|
||||||
|
RMD
|
||||||
|
RSG
|
||||||
|
RIC
|
||||||
|
RIO
|
||||||
|
RFF
|
||||||
|
SFR
|
||||||
|
STO
|
||||||
|
SCG
|
||||||
|
SEK
|
||||||
|
SVW
|
||||||
|
SGF
|
||||||
|
SIG
|
||||||
|
SLX
|
||||||
|
SLR
|
||||||
|
SGM
|
||||||
|
SDR
|
||||||
|
SKC
|
||||||
|
SIQ
|
||||||
|
SHL
|
||||||
|
S32
|
||||||
|
SPK
|
||||||
|
SMR
|
||||||
|
SDF
|
||||||
|
SGP
|
||||||
|
SNZ
|
||||||
|
SUN
|
||||||
|
SUL
|
||||||
|
SNL
|
||||||
|
TAH
|
||||||
|
TNE
|
||||||
|
TLX
|
||||||
|
TLS
|
||||||
|
TPW
|
||||||
|
A2M
|
||||||
|
TLC
|
||||||
|
SGR
|
||||||
|
TPG
|
||||||
|
TCL
|
||||||
|
TWE
|
||||||
|
TUA
|
||||||
|
URW
|
||||||
|
VNT
|
||||||
|
VCX
|
||||||
|
VUK
|
||||||
|
VEA
|
||||||
|
VSL
|
||||||
|
WAM
|
||||||
|
WGB
|
||||||
|
WLE
|
||||||
|
SOL
|
||||||
|
WPR
|
||||||
|
WEB
|
||||||
|
WBT
|
||||||
|
WES
|
||||||
|
WAF
|
||||||
|
WGX
|
||||||
|
WBC
|
||||||
|
WHC
|
||||||
|
WTN
|
||||||
|
WTC
|
||||||
|
WDS
|
||||||
|
WOW
|
||||||
|
WOR
|
||||||
|
XRO
|
||||||
|
YAL
|
||||||
|
ZIM
|
||||||
|
ZIP`
|
||||||
|
// Tạo kết nối đến cơ sở dữ liệu MySQL
|
||||||
|
const connection = mysql.createConnection({
|
||||||
|
host: 'localhost', // Thay bằng địa chỉ máy chủ MySQL của bạn
|
||||||
|
user: 'root', // Thay 'username' bằng tên người dùng MySQL của bạn
|
||||||
|
password: 'Maypjtkh0ng', // Thay 'password' bằng mật khẩu của bạn
|
||||||
|
database: 'marketindex', // Thay 'database_name' bằng tên cơ sở dữ liệu của bạn
|
||||||
|
})
|
||||||
|
|
||||||
|
// Đọc dữ liệu từ tệp JavaScript
|
||||||
|
const sourceData = a.split('\n')
|
||||||
|
|
||||||
|
// Kết nối đến cơ sở dữ liệu MySQL
|
||||||
|
connection.connect((err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Lỗi kết nối đến cơ sở dữ liệu:', err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
console.log('Kết nối đến cơ sở dữ liệu thành công.')
|
||||||
|
|
||||||
|
// Lặp qua từng dòng trong mảng dữ liệu và chèn vào cơ sở dữ liệu MySQL
|
||||||
|
sourceData.forEach((row) => {
|
||||||
|
const sql = 'INSERT INTO indice (Idx, code) VALUES ("ASX300",?)' // Thay 'your_table_name' và 'column_name' bằng tên bảng và cột của bạn
|
||||||
|
connection.query(sql, [row], (err, result) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Lỗi chèn dữ liệu vào cơ sở dữ liệu:', err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
console.log('Dòng đã được chèn vào cơ sở dữ liệu thành công.')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Đóng kết nối đến cơ sở dữ liệu MySQL
|
||||||
|
connection.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,297 @@
|
||||||
|
const fs = require('fs')
|
||||||
|
const mysql = require('mysql')
|
||||||
|
const PDFParser = require('pdf-parse')
|
||||||
|
const listItemCheck = [
|
||||||
|
'S&P/ASX 20 ',
|
||||||
|
'S&P/ASX 50',
|
||||||
|
'S&P/ASX 100',
|
||||||
|
'S&P/ASX 200',
|
||||||
|
'S&P/ASX 300',
|
||||||
|
'All Ordinaries',
|
||||||
|
]
|
||||||
|
const months = [
|
||||||
|
'January',
|
||||||
|
'February',
|
||||||
|
'March',
|
||||||
|
'April',
|
||||||
|
'May',
|
||||||
|
'June',
|
||||||
|
'July',
|
||||||
|
'August',
|
||||||
|
'September',
|
||||||
|
'October',
|
||||||
|
'November',
|
||||||
|
'December',
|
||||||
|
]
|
||||||
|
const monthAbbreviations = [
|
||||||
|
'Jan',
|
||||||
|
'Feb',
|
||||||
|
'Mar',
|
||||||
|
'Apr',
|
||||||
|
'May',
|
||||||
|
'Jun',
|
||||||
|
'Jul',
|
||||||
|
'Aug',
|
||||||
|
'Sep',
|
||||||
|
'Oct',
|
||||||
|
'Nov',
|
||||||
|
'Dec',
|
||||||
|
]
|
||||||
|
const allMonths = months.concat(monthAbbreviations)
|
||||||
|
async function readPDF(filePath) {
|
||||||
|
try {
|
||||||
|
// Read the PDF file
|
||||||
|
const dataBuffer = fs.readFileSync(filePath)
|
||||||
|
|
||||||
|
// Parse the PDF content
|
||||||
|
const pdf = await PDFParser(dataBuffer)
|
||||||
|
|
||||||
|
// Extract text from the parsed PDF
|
||||||
|
const text = pdf.text
|
||||||
|
|
||||||
|
return text
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error:', error)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
const getDataToImportDB = async (text) => {
|
||||||
|
try {
|
||||||
|
let results = []
|
||||||
|
text = text.replace(/ /g, ' ')
|
||||||
|
const arrayContent = text
|
||||||
|
.toString()
|
||||||
|
.split('\n')
|
||||||
|
.filter(
|
||||||
|
(line) =>
|
||||||
|
line.trim() !== '' &&
|
||||||
|
!line.replace(/ /g, '').includes('INDEXANNOUNCEMENT') &&
|
||||||
|
!line.replace(/ /g, '').includes('ActionCodeCompany') &&
|
||||||
|
((line.replace(/ /g, '').includes('S&P') &&
|
||||||
|
line.replace(/ /g, '').includes('Index')) ||
|
||||||
|
line.includes('Addition') ||
|
||||||
|
line.includes('Removal') ||
|
||||||
|
line.includes('All Ordinaries ')),
|
||||||
|
)
|
||||||
|
const positionItem = []
|
||||||
|
listItemCheck.map((item) => {
|
||||||
|
arrayContent.map((line, index) => {
|
||||||
|
if (line.includes(item)) {
|
||||||
|
positionItem.push({ itemName: item, index: index })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arrayContent[index].includes('Addition')) {
|
||||||
|
arrayContent[index] = arrayContent[index].slice(
|
||||||
|
arrayContent[index].indexOf('Addition'),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arrayContent[index].includes('Removal')) {
|
||||||
|
arrayContent[index] = arrayContent[index].slice(
|
||||||
|
arrayContent[index].indexOf('Removal'),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
positionItem.map((item, index) => {
|
||||||
|
let count = item.index
|
||||||
|
if (item.itemName === 'All Ordinaries') {
|
||||||
|
positionItem[index].itemName = 'S&P/ASX 500'
|
||||||
|
}
|
||||||
|
|
||||||
|
while (
|
||||||
|
arrayContent[count + 1] && (arrayContent[count + 1].includes('Addition') || arrayContent[count + 1].includes('Removal') )
|
||||||
|
) {
|
||||||
|
const line = arrayContent[count + 1]
|
||||||
|
let date = ''
|
||||||
|
// Regular expression pattern to match month names
|
||||||
|
const regex = new RegExp('(' + allMonths.join('|') + ')', 'i') // 'i' flag for case-insensitive matching
|
||||||
|
|
||||||
|
// Use match method to find the month
|
||||||
|
const match = arrayContent[item.index].replace(/ /g, '').match(regex)
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
const monthName = match[0]
|
||||||
|
const monthIndex =
|
||||||
|
(allMonths.findIndex(
|
||||||
|
(m) => m.toLowerCase() === monthName.toLowerCase(),
|
||||||
|
) %
|
||||||
|
12) +
|
||||||
|
1 // Take modulo to handle abbreviations
|
||||||
|
date = monthIndex + '-15'
|
||||||
|
} else {
|
||||||
|
console.log('Month not found in the string.')
|
||||||
|
}
|
||||||
|
// Regular expression pattern to match year (4 digits)
|
||||||
|
const regexYear = /[0-9][0-9][0-9][0-9]/
|
||||||
|
|
||||||
|
// Use match method to find the year
|
||||||
|
const matchYear = arrayContent[item.index]
|
||||||
|
.replace(/ /g, '')
|
||||||
|
.match(regexYear)
|
||||||
|
|
||||||
|
if (matchYear) {
|
||||||
|
date = matchYear[0] + '-' + date
|
||||||
|
} else {
|
||||||
|
console.log('Year not found in the string.')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line.includes('Addition')) {
|
||||||
|
results.push({
|
||||||
|
Idx: item.itemName.split('/')[1].replace(/ /g, '').trim(),
|
||||||
|
Code: line.split(' ')[1],
|
||||||
|
StartDate: date,
|
||||||
|
// EndDate: '2099-12-15',
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
results.push({
|
||||||
|
Idx: item.itemName.split('/')[1].replace(/ /g, '').trim(),
|
||||||
|
Code: line.split(' ')[1],
|
||||||
|
// StartDate: '1990-3-15',
|
||||||
|
EndDate: date,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
count += 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
updateDB(results)
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to read the directory asynchronously
|
||||||
|
async function readDirectory(path) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
fs.readdir(path, (err, files) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err)
|
||||||
|
} else {
|
||||||
|
resolve(files)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const directoryPath = 'E:\\Downloads\\marketindex\\rebalancePDFFile'
|
||||||
|
// Function to log files sequentially with random delays
|
||||||
|
async function logFiles(files) {
|
||||||
|
for (const file of files) {
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
readPDF(directoryPath + '\\' + file)
|
||||||
|
.then((text) => {
|
||||||
|
console.log(directoryPath + '\\' + file)
|
||||||
|
getDataToImportDB(text)
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve()
|
||||||
|
}, 5000);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('Error:', error)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
readDirectory(directoryPath)
|
||||||
|
.then((files) => {
|
||||||
|
return logFiles(files)
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error('Error reading directory:', err)
|
||||||
|
})
|
||||||
|
|
||||||
|
const pdfFilePath = 'E:\\Downloads\\marketindex\\2018-rebalance-march.pdf'
|
||||||
|
|
||||||
|
// Hàm thực hiện truy vấn với promise
|
||||||
|
const query = (connection, sql, values) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
connection.query(sql, values, (error, results) => {
|
||||||
|
if (error) {
|
||||||
|
reject(error)
|
||||||
|
} else {
|
||||||
|
resolve(results)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateDB = async (data) => {
|
||||||
|
// Tạo kết nối đến cơ sở dữ liệu MySQL
|
||||||
|
const connection = mysql.createConnection({
|
||||||
|
host: 'localhost', // Thay bằng địa chỉ máy chủ MySQL của bạn
|
||||||
|
user: 'root', // Thay 'username' bằng tên người dùng MySQL của bạn
|
||||||
|
password: 'Maypjtkh0ng', // Thay 'password' bằng mật khẩu của bạn
|
||||||
|
database: 'marketindex', // Thay 'database_name' bằng tên cơ sở dữ liệu của bạn
|
||||||
|
})
|
||||||
|
|
||||||
|
// Kết nối đến cơ sở dữ liệu MySQL
|
||||||
|
connection.connect((err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Error connecting to MySQL:', err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
console.log('Connected to MySQL database.')
|
||||||
|
})
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (const row of data) {
|
||||||
|
const results = await query(
|
||||||
|
connection,
|
||||||
|
'SELECT * FROM indice WHERE Code = ? AND Idx = ?',
|
||||||
|
[row.Code, row.Idx],
|
||||||
|
)
|
||||||
|
if (results.length > 0) {
|
||||||
|
if (row.StartDate) {
|
||||||
|
await query(
|
||||||
|
connection,
|
||||||
|
'UPDATE indice SET StartDate = ?, EndDate = "2099-12-15" WHERE Idx = ? AND Code = ?',
|
||||||
|
[row.StartDate, row.Idx, row.Code],
|
||||||
|
)
|
||||||
|
console.log(
|
||||||
|
`Update ${row.Code}-${row.Idx} (Add at ${row.StartDate}) success`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (row.EndDate) {
|
||||||
|
await query(
|
||||||
|
connection,
|
||||||
|
'UPDATE indice SET EndDate = ? WHERE Idx = ? AND Code = ?',
|
||||||
|
[row.EndDate, row.Idx, row.Code],
|
||||||
|
)
|
||||||
|
console.log(
|
||||||
|
`Update ${row.Code}-${row.Idx} (Remove at ${row.EndDate}) success`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (row.StartDate) {
|
||||||
|
await query(
|
||||||
|
connection,
|
||||||
|
'INSERT INTO indice (Idx, Code, StartDate, EndDate) VALUES (?, ?, ?, "2099-12-15")',
|
||||||
|
[row.Idx, row.Code, row.StartDate],
|
||||||
|
)
|
||||||
|
console.log(
|
||||||
|
`Insert new code: ${row.Code}-${row.Idx} (Insert)(Add at ${row.StartDate}) success`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (row.EndDate) {
|
||||||
|
await query(
|
||||||
|
connection,
|
||||||
|
'INSERT INTO indice (Idx, Code, EndDate) VALUES (?, ?, ?)',
|
||||||
|
[row.Idx, row.Code, row.EndDate],
|
||||||
|
)
|
||||||
|
console.log(
|
||||||
|
`Insert new code: ${row.Code}-${row.Idx} (Insert)(Remove at ${row.EndDate}) success`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error:', error)
|
||||||
|
} finally {
|
||||||
|
// Đóng kết nối đến cơ sở dữ liệu MySQL
|
||||||
|
console.log(`\nUpdated ${data.length} code!`)
|
||||||
|
connection.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"name": "marketindex",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "Joseph Le",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"fs": "^0.0.1-security",
|
||||||
|
"https": "^1.0.0",
|
||||||
|
"mysql": "^2.18.1",
|
||||||
|
"pdf-parse": "^1.1.1",
|
||||||
|
"puppeteer": "^22.2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue