Compare commits

...
29 Commits
Author SHA1 Message Date
devlikepro a64820048c [core] Add health-cmd
Release / WEBJS - chrome - amd64 - chrome (push) Waiting to run
Release / WEBJS - chromium - amd64 - latest (push) Waiting to run
Release / WEBJS - chromium - linux/arm64 - arm (push) Waiting to run
Release / GOWS - none - amd64 - gows (push) Waiting to run
Release / GOWS - none - linux/arm64 - gows-arm (push) Waiting to run
Release / NOWEB - none - amd64 - noweb (push) Waiting to run
Release / NOWEB - none - linux/arm64 - noweb-arm (push) Waiting to run
2025-07-01 13:35:00 +07:00
devlikepro 4ff4a5a893 [core] 2025.7.1 2025-07-01 13:23:38 +07:00
devlikepro 5ea5681d2b [core] Use PORT first
fix #1090
2025-07-01 13:23:38 +07:00
devlikepro 2bb327b747 [core] move HEALTHCHECK from Dockerfile to docker-compose.yaml
fix #1090
2025-07-01 13:23:38 +07:00
devlikepro 4dcdf60309 [core] make build-all 2025-07-01 13:23:37 +07:00
devlikepro 009fd5b2ec [core] NOWEB - share() events 2025-07-01 13:23:37 +07:00
devlikepro 091e7e5bc1 [core] Use this.knex or query methods directly 2025-07-01 13:23:37 +07:00
devlikepro ea1202bb65 [core] Use knex by for sqlite3, not database connection 2025-07-01 13:23:32 +07:00
devlikepro cb413febaa [core] Handle WhatsApp News profile picture 2025-07-01 13:23:32 +07:00
devlikepro 364e55d477 [core] Add KnexEngine (copy paste from psql) 2025-07-01 13:23:32 +07:00
devlikepro 680a35a26d [core] rm start-interval from docker run - docker 24 doesn't have it (used in CI)
Release / WEBJS - chrome - amd64 - chrome (push) Waiting to run
Release / WEBJS - chromium - amd64 - latest (push) Waiting to run
Release / WEBJS - chromium - linux/arm64 - arm (push) Waiting to run
Release / GOWS - none - amd64 - gows (push) Waiting to run
Release / GOWS - none - linux/arm64 - gows-arm (push) Waiting to run
Release / NOWEB - none - amd64 - noweb (push) Waiting to run
Release / NOWEB - none - linux/arm64 - noweb-arm (push) Waiting to run
2025-06-29 11:31:54 +07:00
devlikepro 08ff59e463 [core] 2025.6.7 2025-06-29 11:17:51 +07:00
devlikepro 9db4c8c333 [core] Check docker health in CI
fix #1085
2025-06-29 11:17:51 +07:00
devlikepro 2489c2da46 [core] Install curl in all images
fix #1085
2025-06-29 11:17:51 +07:00
devlikepro fbc58b0707 [core] 2025.6.6
Release / WEBJS - chrome - amd64 - chrome (push) Waiting to run
Release / WEBJS - chromium - amd64 - latest (push) Waiting to run
Release / WEBJS - chromium - linux/arm64 - arm (push) Waiting to run
Release / GOWS - none - amd64 - gows (push) Waiting to run
Release / GOWS - none - linux/arm64 - gows-arm (push) Waiting to run
Release / NOWEB - none - amd64 - noweb (push) Waiting to run
Release / NOWEB - none - linux/arm64 - noweb-arm (push) Waiting to run
2025-06-27 11:09:33 +07:00
devlikepro d5a525789e [core] NOWEB - show poll on the device
fix #988
2025-06-27 11:09:32 +07:00
devlikepro 34066921e1 [core] run xvfb only for WEBJS engine 2025-06-27 11:09:32 +07:00
devlikepro 901c594311 [core] WEBJS - fix pin message
fix #1081
2025-06-27 11:09:32 +07:00
devlikepro 5f619e608b [core] WEBJS - return response for a message
fix #1083
2025-06-27 11:09:31 +07:00
devlikepro 49295090ad [core] Use 501 Not Implemented HTTP status for NotImplemented by engine error
fix #1047
2025-06-27 11:09:31 +07:00
devlikepro a6e43adb0a [core] use xvfb-run 2025-06-27 11:09:30 +07:00
devlikepro 1f165bb6cb [core] Puppeteer 24.10.0 2025-06-27 11:09:30 +07:00
devlikepro 8fc9d88d2e [core] No security reminder, it creates a zombie process
fix #1078
2025-06-27 11:09:29 +07:00
devlikepro d7e5a5ce05 [core] Add ping check 2025-06-27 11:09:29 +07:00
devlikepro 09d446fdeb [core] Install wget for chrome 2025-06-27 11:09:28 +07:00
devlikepro c0bbd60e15 [core] Up Dashboard 2025-06-27 11:09:28 +07:00
devlikepro af3fc137be [core] fix del usage 2025-06-27 11:09:27 +07:00
devlikepro 0ee5e1bd88 [core] Up del, rimraf 2025-06-27 11:09:27 +07:00
devlikepro f92ea18651 [core] Use Debian Bookworm 2025-06-27 11:09:27 +07:00
27 changed files with 316 additions and 292 deletions

No files matched your search

+10 -1
View File
@@ -126,7 +126,16 @@ jobs:
working-directory: tests/smoke
timeout-minutes: 2
run: |
docker run -d --name smoke --rm -p3000:3000 ${{ vars.DOCKER_IMAGE }}:${{ matrix.tag }}
docker run -d \
--name smoke \
--health-cmd "/bin/bash /ping-check.sh" \
--health-interval 1s \
--health-retries 60 \
--health-timeout 2s \
--health-start-period 2s \
--rm -p3000:3000 \
${{ vars.DOCKER_IMAGE }}:${{ matrix.tag }}
sleep 3
docker logs smoke
goss validate --retry-timeout 30s --sleep 1s
+1
View File
@@ -39,6 +39,7 @@ repos:
(?x)^(
docs/.*|
README.md|
tests/smoke/goss.yaml|
)$
- repo: https://github.com/Lucas-C/pre-commit-hooks-nodejs
rev: v1.1.2
+32 -7
View File
@@ -1,8 +1,10 @@
ARG NODE_IMAGE_TAG=22.16-bookworm-slim
ARG GOLANG_IMAGE_TAG=1.23-bookworm
#
# Build
#
ARG NODE_VERSION=22.16-bullseye
FROM node:${NODE_VERSION} AS build
FROM node:${NODE_IMAGE_TAG} AS build
ENV PUPPETEER_SKIP_DOWNLOAD=True
# npm packages
@@ -10,6 +12,10 @@ WORKDIR /git
COPY package.json .
COPY yarn.lock .
ENV YARN_CHECKSUM_BEHAVIOR=update
# git
RUN apt-get update && apt-get install -y git
RUN npm install -g corepack && corepack enable
RUN yarn set version 3.6.3
RUN yarn install
@@ -23,11 +29,14 @@ RUN yarn build && find ./dist -name "*.d.ts" -delete
#
# Dashboard
#
FROM node:${NODE_VERSION} AS dashboard
FROM node:${NODE_IMAGE_TAG} AS dashboard
# jq to parse json
RUN apt-get update && apt-get install -y jq && rm -rf /var/lib/apt/lists/*
# wget, unzip
RUN apt-get update && apt-get install -y wget unzip && rm -rf /var/lib/apt/lists/*
COPY waha.config.json /tmp/waha.config.json
RUN \
WAHA_DASHBOARD_GITHUB_REPO=$(jq -r '.waha.dashboard.repo' /tmp/waha.config.json) && \
@@ -42,7 +51,7 @@ RUN \
#
# GOWS
#
FROM golang:1.23-bullseye AS gows
FROM golang:${GOLANG_IMAGE_TAG} AS gows
# jq to parse json
RUN apt-get update && apt-get install -y jq && rm -rf /var/lib/apt/lists/*
@@ -73,7 +82,7 @@ RUN \
#
# Final
#
FROM node:${NODE_VERSION} AS release
FROM node:${NODE_IMAGE_TAG} AS release
ENV PUPPETEER_SKIP_DOWNLOAD=True
# Quick fix for memory potential memory leaks
# https://github.com/devlikeapro/waha/issues/347
@@ -98,6 +107,13 @@ RUN if [ "$USE_BROWSER" = "chromium" ] || [ "$USE_BROWSER" = "chrome" ]; then \
&& rm -rf /var/lib/apt/lists/*; \
fi
# Install wget - either for chromium or chrome
RUN if [ "$USE_BROWSER" = "chromium" ] || [ "$USE_BROWSER" = "chrome" ]; then \
apt-get update \
&& apt-get install -y wget \
&& rm -rf /var/lib/apt/lists/*; \
fi
# Install fonts if using either chromium or chrome
RUN if [ "$USE_BROWSER" = "chromium" ] || [ "$USE_BROWSER" = "chrome" ]; then \
apt-get update \
@@ -119,10 +135,11 @@ RUN if [ "$USE_BROWSER" = "chromium" ] || [ "$USE_BROWSER" = "chrome" ]; then \
&& rm -rf /var/lib/apt/lists/*; \
fi
# Install xvfb
# Install xvfb, xauth
RUN if [ "$USE_BROWSER" = "chromium" ] || [ "$USE_BROWSER" = "chrome" ]; then \
apt-get update && apt-get install -y --no-install-recommends \
xvfb \
xauth \
libnss3 \
libxss1 \
libasound2 \
@@ -130,7 +147,6 @@ RUN if [ "$USE_BROWSER" = "chromium" ] || [ "$USE_BROWSER" = "chrome" ]; then \
libgtk-3-0 \
libdrm2 \
ca-certificates \
curl \
&& rm -rf /var/lib/apt/lists/*; \
fi
@@ -155,6 +171,11 @@ RUN if [ "$USE_BROWSER" = "chrome" ]; then \
&& rm -rf /var/lib/apt/lists/*; \
fi
# curl
RUN apt-get update \
&& apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*
# GOWS requirements
# libc6
RUN apt-get update \
@@ -179,6 +200,10 @@ ENV WAHA_GOWS_SOCKET /tmp/gows.sock
COPY entrypoint.sh /entrypoint.sh
# Add healthcheck script
COPY ping-check.sh /ping-check.sh
RUN chmod +x /ping-check.sh
# Chokidar options to monitor file changes
ENV CHOKIDAR_USEPOLLING=1
ENV CHOKIDAR_INTERVAL=5000
+3 -1
View File
@@ -1,13 +1,15 @@
build:
docker build . -t devlikeapro/waha
build-all: build-plus build-chrome build-gows build-noweb
build-chrome:
docker build . -t devlikeapro/waha-plus:chrome --build-arg USE_BROWSER=chrome
build-noweb:
docker build . -t devlikeapro/waha:noweb --build-arg USE_BROWSER=none --build-arg WHATSAPP_DEFAULT_ENGINE=NOWEB
build-plus-gows:
build-gows:
docker build . -t devlikeapro/waha-plus:gows --build-arg USE_BROWSER=none --build-arg WHATSAPP_DEFAULT_ENGINE=GOWS
build-all: build build-chrome build-noweb
+6
View File
@@ -7,6 +7,12 @@ services:
image: devlikeapro/waha-plus
# WAHA Core
# image: devlikeapro/waha:latest
healthcheck:
test: ['CMD', '/bin/bash', '/ping-check.sh']
interval: 60s
timeout: 10s
retries: 3
start_period: 30s
logging:
driver: 'json-file'
+19 -23
View File
@@ -1,16 +1,5 @@
#!/bin/sh
#
# Run Xvfb if exists
#
if command -v Xvfb > /dev/null 2>&1; then
# Start virtual X server in the background
Xvfb :99 -screen 0 1280x720x24 &
export DISPLAY=:99
sleep 2
else
echo "Xvfb command not found, skipping virtual X server setup"
fi
#
# Calculate UV_THREADPOOL_SIZE based on number of CPUs
@@ -47,24 +36,31 @@ if [ -n "$key" ]; then
echo "WARNING: Plain text API key detected. Converting to hashed format for security."
echo "For better security, use WAHA_API_KEY=sha512:{SHA512_HASH_FOR_YOUR_API_KEY}"
echo "⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️"
# Start a background task to display another warning after 5 seconds
(
sleep 5
echo "⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️"
echo "SECURITY REMINDER: Your plain text API key has been hashed for this session."
echo "In the future, please use WAHA_API_KEY=sha512:{SHA512_HASH_FOR_YOUR_API_KEY}"
echo "to avoid exposing your API key in environment variables or process lists."
echo "⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️"
) &
# Hash the key using sha512sum
HASHED_KEY=$(echo -n "$key" | sha512sum | awk '{print $1}')
export WAHA_API_KEY="sha512:$HASHED_KEY"
fi
fi
#
# xvfb-run
#
USE_XVFB=false
if [ -z "$WHATSAPP_DEFAULT_ENGINE" ] || [ "$WHATSAPP_DEFAULT_ENGINE" = "WEBJS" ]; then
# Try to run xvfb-run with a test command
if xvfb-run --auto-servernum echo "xvfb-run is working!"; then
USE_XVFB=true
else
echo "xvfb-run test failed, do not run it"
USE_XVFB=false
fi
fi
#
# Start your application using node with exec to ensure proper signal handling
#
exec node dist/main
if [ "$USE_XVFB" = "true" ]; then
exec xvfb-run --auto-servernum node dist/main
else
exec node dist/main
fi
+3 -3
View File
@@ -56,7 +56,7 @@
"chokidar": "^3.6.0",
"class-transformer": "^0.5.1",
"class-validator": "0.14.0",
"del": "^6.0.0",
"del": "^8.0.0",
"express-basic-auth": "^1.2.1",
"file-type": "16.5.4",
"fs-extra": "^11.2.0",
@@ -79,11 +79,11 @@
"pino-pretty": "^11.2.1",
"pretty-bytes": "5.6.0",
"promise-retry": "^2.0.1",
"puppeteer": "^23.6.0",
"puppeteer": "^24.10.0",
"qrcode": "^1.5.1",
"qrcode-terminal": "^0.12.0",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rimraf": "^4.3.0",
"rxjs": "^7.8.1",
"sharp": "^0.33.4",
"swagger-ui-express": "^4.1.4",
+14
View File
@@ -0,0 +1,14 @@
#!/bin/bash
# Try PORT first, then WHATSAPP_API_PORT, then default to 3000
PORT=${PORT:-${WHATSAPP_API_PORT:-3000}}
# Check if HTTPS is enabled
if [[ "${WAHA_HTTPS_ENABLED}" == "true" || "${WAHA_HTTPS_ENABLED}" == "1" ]]; then
PROTOCOL="https"
else
PROTOCOL="http"
fi
# Execute curl command with SSL verification disabled
curl -f -s -k "${PROTOCOL}://127.0.0.1:${PORT}/ping" || exit 1
+10 -3
View File
@@ -682,10 +682,17 @@ export abstract class WhatsappSession {
}
protected async refreshProfilePicture(id: string) {
let fn: Promise<string>;
if (isJidBroadcast(id)) {
this.logger.debug(`Refreshing profile picture for id "${id}"...`);
// Have no pictures
if (id === '0@c.us' || id === '0@s.whatsapp.net') {
return null;
} else if (isJidNewsletter(id)) {
} else if (isJidBroadcast(id)) {
return null;
}
// Find the right method
let fn: Promise<string>;
if (isJidNewsletter(id)) {
fn = this.channelsGetChannel(id).then(
(channel: Channel) => channel.picture || channel.preview,
);
+1
View File
@@ -76,6 +76,7 @@ export const IMPORTS_CORE = [
autoLogging: {
ignore: (req) => {
return (
req.url.startsWith('/ping') ||
req.url.startsWith('/dashboard/') ||
req.url.startsWith('/api/files/') ||
req.url.startsWith('/api/s3/')
+19 -12
View File
@@ -1805,6 +1805,7 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
const messagesUpsert$ = fromEvent(this.sock.ev, 'messages.upsert').pipe(
map((event: BaileysEventMap['messages.upsert']) => event.messages),
mergeAll(),
share(),
);
let [messagesFromMe$, messagesFromOthers$] = partition(
messagesUpsert$,
@@ -1888,6 +1889,7 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
).pipe(
// @ts-ignore
mergeAll(),
share(),
);
const messageAckDirect$ = messageUpdates$.pipe(
filter(isMine), // ack comes only for MY messages
@@ -1898,6 +1900,7 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
fromEvent(this.sock.ev, 'message-receipt.update').pipe(
// @ts-ignore
mergeAll(),
share(),
);
const messageAckGroups$ = messageReceiptUpdate$.pipe(
@@ -1914,7 +1917,7 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
//
this.events2
.get(WAHAEvents.STATE_CHANGE)
.switch(fromEvent(this.sock.ev, 'connection.update'));
.switch(fromEvent(this.sock.ev, 'connection.update').pipe(share()));
const groupsUpsert$: Observable<GroupMetadata> = fromEvent(
this.sock.ev,
@@ -1922,6 +1925,7 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
).pipe(
// @ts-ignore
mergeAll(),
share(),
);
const groupsUpdate$: Observable<Partial<GroupMetadata>> = fromEvent(
this.sock.ev,
@@ -1929,11 +1933,12 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
).pipe(
// @ts-ignore
mergeAll(),
share(),
);
const groupsParticipantsUpdate$: Observable<any> = fromEvent(
this.sock.ev,
'group-participants.update',
);
).pipe(share());
this.events2.get(WAHAEvents.GROUP_JOIN).switch(groupsUpsert$);
@@ -1960,13 +1965,12 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
);
this.events2.get(WAHAEvents.GROUP_V2_LEAVE).switch(groupV2Leave$);
this.events2
.get(WAHAEvents.PRESENCE_UPDATE)
.switch(
fromEvent(this.sock.ev, 'presence.update').pipe(
map((data: any) => this.toWahaPresences(data.id, data.presences)),
),
);
this.events2.get(WAHAEvents.PRESENCE_UPDATE).switch(
fromEvent(this.sock.ev, 'presence.update').pipe(
map((data: any) => this.toWahaPresences(data.id, data.presences)),
share(),
),
);
//
// Poll votes
@@ -1993,7 +1997,7 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
//
// @ts-ignore
const calls$: Observable<WACallEvent[]> = fromEvent(this.sock.ev, 'call');
const call$ = calls$.pipe(mergeMap(identity));
const call$ = calls$.pipe(mergeMap(identity), share());
this.events2.get(WAHAEvents.CALL_RECEIVED).switch(
call$.pipe(
filter((call: WACallEvent) => call.status === 'offer'),
@@ -2026,7 +2030,7 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
const labelsEdit$: Observable<NOWEBLabel> = fromEvent(
this.sock.ev,
'labels.edit',
);
).pipe(share());
this.events2.get(WAHAEvents.LABEL_UPSERT).switch(
labelsEdit$.pipe(
exclude((data: NOWEBLabel) => data.deleted),
@@ -2039,7 +2043,10 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
map(this.toLabel.bind(this)),
),
);
const labelsAssociation$ = fromEvent(this.sock.ev, 'labels.association');
const labelsAssociation$ = fromEvent(
this.sock.ev,
'labels.association',
).pipe(share());
const labelsAssociationAdd$: Observable<ChatLabelAssociation> =
labelsAssociation$.pipe(
filter(({ type }: any) => type === 'add'),
@@ -1,20 +1,18 @@
import { Schema } from '@waha/core/storage/Schema';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const Database = require('better-sqlite3');
import Knex from 'knex';
export class Sqlite3SchemaValidation {
constructor(
private table: Schema,
private db,
private knex: Knex.Knex,
) {}
validate() {
async validate() {
const table = this.table;
// Check table has the columns
const columns = this.db.prepare(`PRAGMA table_info(${table.name})`).all();
// Check exact number of columns
const columns = await this.knex.raw(`PRAGMA table_info(${table.name})`);
// Check the exact number of columns
if (columns.length !== table.columns.length) {
throw new Error(
`Table '${table.name}' does not have expected number of columns. Expected ${table.columns.length}, got ${columns.length}`,
@@ -37,7 +35,7 @@ export class Sqlite3SchemaValidation {
}
// Check table has expected indexes
const indexes = this.db.prepare(`PRAGMA index_list(${table.name})`).all();
const indexes = await this.knex.raw(`PRAGMA index_list(${table.name})`);
const indexNames = indexes.map((index) => index.name);
for (const index of table.indexes) {
if (!indexNames.includes(index.name)) {
@@ -6,6 +6,7 @@ import { Sqlite3LabelAssociationsRepository } from '@waha/core/engines/noweb/sto
import { Sqlite3LabelsRepository } from '@waha/core/engines/noweb/store/sqlite3/Sqlite3LabelsRepository';
import { Sqlite3LidPNRepository } from '@waha/core/engines/noweb/store/sqlite3/Sqlite3LidPNRepository';
import { Schema } from '@waha/core/storage/Schema';
import Knex from 'knex';
import { INowebStorage } from '../INowebStorage';
import { Migrations, NOWEB_STORE_SCHEMA } from '../schemas';
@@ -14,70 +15,71 @@ import { Sqlite3ContactRepository } from './Sqlite3ContactRepository';
import { Sqlite3MessagesRepository } from './Sqlite3MessagesRepository';
import { Sqlite3SchemaValidation } from './Sqlite3SchemaValidation';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const Database = require('better-sqlite3');
export class Sqlite3Storage extends INowebStorage {
private readonly db: any;
private readonly tables: Schema[];
private readonly knex: Knex.Knex;
constructor(filePath: string) {
super();
this.db = new Database(filePath);
this.knex = Knex({
client: 'better-sqlite3',
connection: { filename: filePath },
useNullAsDefault: true,
});
this.tables = NOWEB_STORE_SCHEMA;
}
async init() {
this.db.pragma('journal_mode = WAL;');
this.migrate();
this.validateSchema();
await this.knex.raw('PRAGMA journal_mode = WAL;');
await this.migrate();
await this.validateSchema();
}
private migrate() {
this.migration0001init();
private async migrate() {
await this.migration0001init();
}
private validateSchema() {
private async validateSchema() {
for (const table of this.tables) {
new Sqlite3SchemaValidation(table, this.db).validate();
await new Sqlite3SchemaValidation(table, this.knex).validate();
}
}
private migration0001init() {
private async migration0001init() {
for (const migration of Migrations) {
this.db.exec(migration);
await this.knex.raw(migration);
}
}
async close() {
return this.db.close();
return this.knex.destroy();
}
getContactsRepository() {
return new Sqlite3ContactRepository(this.db);
return new Sqlite3ContactRepository(this.knex);
}
getChatRepository() {
return new Sqlite3ChatRepository(this.db);
return new Sqlite3ChatRepository(this.knex);
}
getGroupRepository() {
return new Sqlite3GroupRepository(this.db);
return new Sqlite3GroupRepository(this.knex);
}
getLabelsRepository(): ILabelsRepository {
return new Sqlite3LabelsRepository(this.db);
return new Sqlite3LabelsRepository(this.knex);
}
getLabelAssociationRepository(): ILabelAssociationRepository {
return new Sqlite3LabelAssociationsRepository(this.db);
return new Sqlite3LabelAssociationsRepository(this.knex);
}
getMessagesRepository() {
return new Sqlite3MessagesRepository(this.db);
return new Sqlite3MessagesRepository(this.knex);
}
getLidPNRepository(): INowebLidPNRepository {
return new Sqlite3LidPNRepository(this.db);
return new Sqlite3LidPNRepository(this.knex);
}
}
+5 -2
View File
@@ -1,8 +1,11 @@
import { UnprocessableEntityException } from '@nestjs/common';
import {
NotImplementedException,
UnprocessableEntityException,
} from '@nestjs/common';
export const DOCS_URL = 'https://waha.devlike.pro/';
export class NotImplementedByEngineError extends UnprocessableEntityException {
export class NotImplementedByEngineError extends NotImplementedException {
constructor(msg = '') {
let error = 'The method is not implemented by the engine.';
if (msg) {
+2 -2
View File
@@ -4,8 +4,8 @@ import * as fsp from 'fs/promises';
import * as path from 'path';
import { Logger } from 'pino';
import fs = require('fs');
import del = require('del');
import { fileExists } from '@waha/utils/files';
import { deleteAsync } from 'del';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const writeFileAtomic = require('write-file-atomic');
@@ -59,7 +59,7 @@ export class MediaLocalStorage implements IMediaStorage {
}
if (fs.existsSync(this.filesFolder)) {
del([`${this.filesFolder}/*`], { force: true }).then((paths) => {
deleteAsync([`${this.filesFolder}/*`], { force: true }).then((paths) => {
if (paths.length === 0) {
return;
}
+3 -1
View File
@@ -1,3 +1,5 @@
import Knex from 'knex';
import { DataStore } from '../abc/DataStore';
export abstract class LocalStore extends DataStore {
@@ -23,5 +25,5 @@ export abstract class LocalStore extends DataStore {
*/
abstract getFilePath(session: string, file: string): string;
abstract getWAHADatabase(): any;
abstract getWAHADatabase(): Knex.Knex;
}
+22 -12
View File
@@ -1,18 +1,16 @@
import { safeJoin } from '@waha/utils/files';
import * as fs from 'fs/promises';
import Knex from 'knex';
import * as path from 'path';
import { LocalStore } from './LocalStore';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const Database = require('better-sqlite3');
export class LocalStoreCore extends LocalStore {
protected readonly baseDirectory: string =
process.env.WAHA_LOCAL_STORE_BASE_DIR || './.sessions';
private readonly engine: string;
private db: any;
private knex: Knex.Knex;
constructor(engine: string) {
super();
@@ -21,6 +19,11 @@ export class LocalStoreCore extends LocalStore {
async init(sessionName?: string) {
await fs.mkdir(this.getEngineDirectory(), { recursive: true });
if (!this.knex) {
this.knex = this.buildKnex();
await this.knex.raw('PRAGMA journal_mode = WAL;');
await this.knex.raw('PRAGMA foreign_keys = ON;');
}
if (sessionName) {
await fs.mkdir(this.getSessionDirectory(sessionName), {
recursive: true,
@@ -54,17 +57,24 @@ export class LocalStoreCore extends LocalStore {
return safeJoin(this.getEngineDirectory(), name);
}
getWAHADatabase(): any {
if (!this.db) {
const engineDir = this.getEngineDirectory();
const database = safeJoin(engineDir, 'waha.sqlite3');
this.db = new Database(database);
this.db.pragma('journal_mode = WAL;');
getWAHADatabase(): Knex.Knex {
if (!this.knex) {
throw new Error('Knex is not initialized, call LocalStore.init() first');
}
return this.db;
return this.knex;
}
buildKnex(): Knex.Knex {
const engineDir = this.getEngineDirectory();
const database = path.join(engineDir, 'waha.sqlite3');
return Knex({
client: 'better-sqlite3',
connection: { filename: database },
useNullAsDefault: true,
});
}
async close() {
this.db?.close();
await this.knex.destroy();
}
}
-28
View File
@@ -1,28 +0,0 @@
import Knex from 'knex';
export interface ISQLEngine {
/**
* Run a query that does not return any data
*/
run(query: Knex.QueryBuilder): Promise<void>;
/**
* Get a single row from the database
*/
get(query: Knex.QueryBuilder): Promise<any | null>;
/**
* Get all rows from the database
*/
all(query: Knex.QueryBuilder): Promise<any[]>;
/**
* Run a raw SQL query with bindings
*/
raw(sql: string, bindings: any[]): Promise<void>;
/**
* Execute a raw SQL query
*/
exec(sql: string): Promise<void>;
}
+9 -13
View File
@@ -1,9 +1,8 @@
import { Field, Schema } from '@waha/core/storage/Schema';
import { IJsonQuery } from '@waha/core/storage/sql/IJsonQuery';
import { ISQLEngine } from '@waha/core/storage/sql/ISQLEngine';
import { PaginationParams } from '@waha/structures/pagination.dto';
import { KnexPaginator } from '@waha/utils/Paginator';
import Knex from 'knex';
import { Knex } from 'knex';
import * as lodash from 'lodash';
export type Migration = string;
@@ -26,10 +25,7 @@ export class SqlKVRepository<Entity> {
return [];
}
constructor(
private engine: ISQLEngine,
protected knex: Knex.Knex,
) {}
constructor(protected knex: Knex) {}
get columns(): Field[] {
return this.schema.columns;
@@ -49,7 +45,7 @@ export class SqlKVRepository<Entity> {
protected async applyMigrations() {
for (const migration of this.migrations) {
await this.engine.exec(migration);
await this.knex.raw(migration);
}
}
@@ -119,7 +115,7 @@ export class SqlKVRepository<Entity> {
async getCount(): Promise<number> {
const query = this.select().count({ count: 'id' });
const row = await this.engine.get(query);
const row = await query.first();
if (!row) {
return 0;
}
@@ -138,7 +134,7 @@ export class SqlKVRepository<Entity> {
return new Map();
}
const rows = await this.engine.all(this.select().whereIn('id', ids));
const rows = await this.select().whereIn('id', ids);
const entitiesMap = new Map<string, Entity | null>();
// Initialize a map with null values for all requested IDs
@@ -191,15 +187,15 @@ export class SqlKVRepository<Entity> {
* SQL Implementation details
*/
public async raw(sql: string, bindings: any[]): Promise<void> {
await this.engine.raw(sql, bindings);
await this.knex.raw(sql, bindings);
}
protected async run(query: Knex.QueryBuilder): Promise<void> {
await this.engine.run(query);
await query;
}
protected async get(query: Knex.QueryBuilder): Promise<Entity | null> {
const row = await this.engine.get(query);
const row = await query.first();
if (!row) {
return null;
}
@@ -207,7 +203,7 @@ export class SqlKVRepository<Entity> {
}
public async all(query: Knex.QueryBuilder): Promise<Entity[]> {
const rows = await this.engine.all(query);
const rows = await query;
return rows.map((row) => this.parse(row));
}
-38
View File
@@ -1,38 +0,0 @@
import { ISQLEngine } from '@waha/core/storage/sql/ISQLEngine';
import { Database } from 'better-sqlite3';
import { Knex } from 'knex';
export class Sqlite3Engine implements ISQLEngine {
constructor(protected db: Database) {}
async all(query: Knex.QueryBuilder): Promise<any[]> {
const sql = query.toSQL().sql;
const bind = query.toSQL().bindings;
return this.db.prepare(sql).all(bind);
}
async get(query: Knex.QueryBuilder): Promise<any | null> {
const sql = query.toSQL().sql;
const bind = query.toSQL().bindings;
const row: any = this.db.prepare(sql).get(bind);
if (!row) {
return null;
}
return row;
}
async run(query: Knex.QueryBuilder): Promise<void> {
const sql = query.toSQL().sql;
const bind = query.toSQL().bindings;
this.db.prepare(sql).run(bind);
return;
}
async raw(sql: string, bindings: any[]) {
this.db.prepare(sql).run(bindings);
}
async exec(sql): Promise<void> {
this.db.exec(sql);
}
}
@@ -1,23 +1,17 @@
import { SqlKVRepository } from '@waha/core/storage/sql/SqlKVRepository';
import { Sqlite3Engine } from '@waha/core/storage/sqlite3/Sqlite3Engine';
import { Sqlite3JsonQuery } from '@waha/core/storage/sqlite3/Sqlite3JsonQuery';
import { sleep } from '@waha/utils/promiseTimeout';
import { Database } from 'better-sqlite3';
import Knex from 'knex';
/**
* Key value repository with extra metadata
*/
export class Sqlite3KVRepository<Entity> extends SqlKVRepository<Entity> {
protected db: Database;
protected knex: Knex.Knex;
protected jsonQuery = new Sqlite3JsonQuery();
constructor(db: Database) {
// sqlite does not support inserting default values. Set the `useNullAsDefault` flag to hide this warning. (see docs https://knexjs.org/guide/query-builder.html#insert).
const knex = Knex({ client: 'better-sqlite3', useNullAsDefault: true });
const engine = new Sqlite3Engine(db);
super(engine, knex);
this.db = db;
constructor(knex: Knex.Knex) {
super(knex);
}
protected async upsertBatch(entities: Entity[]): Promise<void> {
@@ -23,8 +23,8 @@ export class Sqlite3SessionMeRepository
}
constructor(store: LocalStore) {
const db = store.getWAHADatabase();
super(db);
const knex = store.getWAHADatabase();
super(knex);
}
upsertMe(sessionName: string, me: MeInfo): Promise<void> {
@@ -41,7 +41,7 @@ export class Sqlite3SessionMeRepository
}
protected async validateSchema() {
const validation = new Sqlite3SchemaValidation(this.schema, this.db);
validation.validate();
const validation = new Sqlite3SchemaValidation(this.schema, this.knex);
await validation.validate();
}
}
@@ -23,8 +23,8 @@ export class Sqlite3SessionWorkerRepository
}
constructor(store: LocalStore) {
const db = store.getWAHADatabase();
super(db);
const knex = store.getWAHADatabase();
super(knex);
}
assign(session: string, worker: string): Promise<void> {
@@ -45,7 +45,7 @@ export class Sqlite3SessionWorkerRepository
}
protected async validateSchema() {
const validation = new Sqlite3SchemaValidation(this.schema, this.db);
validation.validate();
const validation = new Sqlite3SchemaValidation(this.schema, this.knex);
await validation.validate();
}
}
+1 -1
View File
@@ -33,7 +33,7 @@ export function getEngineName(): string {
}
export const VERSION: WAHAEnvironment = {
version: '2025.6.5',
version: '2025.7.1',
engine: getEngineName(),
tier: getWAHAVersion(),
browser:
+8
View File
@@ -5,3 +5,11 @@ http:
no-follow-redirects: true
timeout: 5000
body: ['version']
command:
docker smoke health:
exec: "docker inspect --format '{{`{{if .State.Health}}{{.State.Health.Status}}{{else}}no healthcheck{{end}}`}}' smoke"
exit-status: 0
stdout:
- 'healthy'
timeout: 5000
+1 -1
View File
@@ -6,7 +6,7 @@
},
"dashboard": {
"repo": "devlikeapro/dashboard",
"ref": "52750393583e215d212d22bc613d75c106add3a1"
"ref": "fd8594d89ef369ed669c8b8b529ab29058c0d13c"
}
}
}
+106 -97
View File
@@ -7,7 +7,7 @@ __metadata:
"@adiwajshing/baileys@github:devlikeapro/Baileys#fork-master-2025-05-01":
version: 6.7.16
resolution: "@adiwajshing/baileys@https://github.com/devlikeapro/Baileys.git#commit=5835c558607cb85ff81a32ea93f12a4bd3e36648"
resolution: "@adiwajshing/baileys@https://github.com/devlikeapro/Baileys.git#commit=17db13bd44d54e00d5740b002aca0b33c15b6e7b"
dependencies:
"@cacheable/node-cache": ^1.4.0
"@hapi/boom": ^9.1.3
@@ -34,7 +34,7 @@ __metadata:
optional: true
sharp:
optional: true
checksum: e90ede6bdfd1a79afe4a3f1946ba820f92796f06e13414106cdefbc0060a7e826a04b5d9f7ef47f4233e12e7f9130ace4dd3f80e1a754191a72b6650bd769410
checksum: f89150418538cc3d11ed94da91ff5ba89a49b9a29c1d8a060fd8a211c3ab2e9cdf84c2f8bd3962e67835decc4fb78783dd8f1d297b8caf6d4b026dfa3bd42126
languageName: node
linkType: hard
@@ -2665,6 +2665,13 @@ __metadata:
languageName: node
linkType: hard
"@sindresorhus/merge-streams@npm:^2.1.0":
version: 2.3.0
resolution: "@sindresorhus/merge-streams@npm:2.3.0"
checksum: e989d53dee68d7e49b4ac02ae49178d561c461144cea83f66fa91ff012d981ad0ad2340cbd13f2fdb57989197f5c987ca22a74eb56478626f04e79df84291159
languageName: node
linkType: hard
"@sinonjs/commons@npm:^3.0.0":
version: 3.0.1
resolution: "@sinonjs/commons@npm:3.0.1"
@@ -4316,16 +4323,6 @@ __metadata:
languageName: node
linkType: hard
"aggregate-error@npm:^3.0.0":
version: 3.1.0
resolution: "aggregate-error@npm:3.1.0"
dependencies:
clean-stack: ^2.0.0
indent-string: ^4.0.0
checksum: 1101a33f21baa27a2fa8e04b698271e64616b886795fd43c31068c07533c7b3facfcaf4e9e0cab3624bd88f729a592f1c901a1a229c9e490eafce411a8644b79
languageName: node
linkType: hard
"ajv-formats@npm:3.0.1":
version: 3.0.1
resolution: "ajv-formats@npm:3.0.1"
@@ -4624,13 +4621,6 @@ __metadata:
languageName: node
linkType: hard
"array-union@npm:^2.1.0":
version: 2.1.0
resolution: "array-union@npm:2.1.0"
checksum: 5bee12395cba82da674931df6d0fea23c4aa4660cb3b338ced9f828782a65caa232573e6bf3968f23e0c5eb301764a382cef2f128b170a9dc59de0e36c39f98d
languageName: node
linkType: hard
"array.prototype.findlastindex@npm:^1.2.5":
version: 1.2.6
resolution: "array.prototype.findlastindex@npm:1.2.6"
@@ -5516,13 +5506,6 @@ __metadata:
languageName: node
linkType: hard
"clean-stack@npm:^2.0.0":
version: 2.2.0
resolution: "clean-stack@npm:2.2.0"
checksum: 2ac8cd2b2f5ec986a3c743935ec85b07bc174d5421a5efc8017e1f146a1cf5f781ae962618f416352103b32c9cd7e203276e8c28241bbe946160cab16149fb68
languageName: node
linkType: hard
"cli-boxes@npm:^2.2.1":
version: 2.2.1
resolution: "cli-boxes@npm:2.2.1"
@@ -6140,19 +6123,17 @@ __metadata:
languageName: node
linkType: hard
"del@npm:^6.0.0":
version: 6.1.1
resolution: "del@npm:6.1.1"
"del@npm:^8.0.0":
version: 8.0.0
resolution: "del@npm:8.0.0"
dependencies:
globby: ^11.0.1
graceful-fs: ^4.2.4
is-glob: ^4.0.1
is-path-cwd: ^2.2.0
is-path-inside: ^3.0.2
p-map: ^4.0.0
rimraf: ^3.0.2
slash: ^3.0.0
checksum: 563288b73b8b19a7261c47fd21a330eeab6e2acd7c6208c49790dfd369127120dd7836cdf0c1eca216b77c94782a81507eac6b4734252d3bef2795cb366996b6
globby: ^14.0.2
is-glob: ^4.0.3
is-path-cwd: ^3.0.0
is-path-inside: ^4.0.0
p-map: ^7.0.2
slash: ^5.1.0
checksum: 502dea7a846f989e1d921733f5d41ae4ae9b3eff168d335bfc050c9ce938ddc46198180be133814269268c4b0aed441a82fbace948c0ec5eed4ed086a4ad3b0e
languageName: node
linkType: hard
@@ -6226,15 +6207,6 @@ __metadata:
languageName: node
linkType: hard
"dir-glob@npm:^3.0.1":
version: 3.0.1
resolution: "dir-glob@npm:3.0.1"
dependencies:
path-type: ^4.0.0
checksum: fa05e18324510d7283f55862f3161c6759a3f2f8dbce491a2fc14c8324c498286c54282c1f0e933cb930da8419b30679389499b919122952a4f8592362ef4615
languageName: node
linkType: hard
"doctrine@npm:^2.1.0":
version: 2.1.0
resolution: "doctrine@npm:2.1.0"
@@ -7074,7 +7046,7 @@ __metadata:
languageName: node
linkType: hard
"fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.2":
"fast-glob@npm:^3.3.2, fast-glob@npm:^3.3.3":
version: 3.3.3
resolution: "fast-glob@npm:3.3.3"
dependencies:
@@ -7701,6 +7673,18 @@ __metadata:
languageName: node
linkType: hard
"glob@npm:^9.2.0":
version: 9.3.5
resolution: "glob@npm:9.3.5"
dependencies:
fs.realpath: ^1.0.0
minimatch: ^8.0.2
minipass: ^4.2.4
path-scurry: ^1.6.1
checksum: 94b093adbc591bc36b582f77927d1fb0dbf3ccc231828512b017601408be98d1fe798fc8c0b19c6f2d1a7660339c3502ce698de475e9d938ccbb69b47b647c84
languageName: node
linkType: hard
"globals@npm:^11.1.0":
version: 11.12.0
resolution: "globals@npm:11.12.0"
@@ -7727,17 +7711,17 @@ __metadata:
languageName: node
linkType: hard
"globby@npm:^11.0.1":
version: 11.1.0
resolution: "globby@npm:11.1.0"
"globby@npm:^14.0.2":
version: 14.1.0
resolution: "globby@npm:14.1.0"
dependencies:
array-union: ^2.1.0
dir-glob: ^3.0.1
fast-glob: ^3.2.9
ignore: ^5.2.0
merge2: ^1.4.1
slash: ^3.0.0
checksum: b4be8885e0cfa018fc783792942d53926c35c50b3aefd3fdcfb9d22c627639dc26bd2327a40a0b74b074100ce95bb7187bfeae2f236856aa3de183af7a02aea6
"@sindresorhus/merge-streams": ^2.1.0
fast-glob: ^3.3.3
ignore: ^7.0.3
path-type: ^6.0.0
slash: ^5.1.0
unicorn-magic: ^0.3.0
checksum: b1f27dccc999c010ee7e0ce7c6581fd2326ac86cf0508474d526d699a029b66b35d6fa4361c8b4ad8e80809582af71d5e2080e671cf03c26e98ca67aba8834bd
languageName: node
linkType: hard
@@ -7990,14 +7974,7 @@ __metadata:
languageName: node
linkType: hard
"ignore@npm:^5.2.0":
version: 5.3.2
resolution: "ignore@npm:5.3.2"
checksum: 2acfd32a573260ea522ea0bfeff880af426d68f6831f973129e2ba7363f422923cf53aab62f8369cbf4667c7b25b6f8a3761b34ecdb284ea18e87a5262a865be
languageName: node
linkType: hard
"ignore@npm:^7.0.0":
"ignore@npm:^7.0.0, ignore@npm:^7.0.3":
version: 7.0.5
resolution: "ignore@npm:7.0.5"
checksum: d0862bf64d3d58bf34d5fb0a9f725bec9ca5ce8cd1aecc8f28034269e8f69b8009ffd79ca3eda96962a6a444687781cd5efdb8c7c8ddc0a6996e36d31c217f14
@@ -8033,13 +8010,6 @@ __metadata:
languageName: node
linkType: hard
"indent-string@npm:^4.0.0":
version: 4.0.0
resolution: "indent-string@npm:4.0.0"
checksum: 824cfb9929d031dabf059bebfe08cf3137365e112019086ed3dcff6a0a7b698cb80cf67ccccde0e25b9e2d7527aa6cc1fed1ac490c752162496caba3e6699612
languageName: node
linkType: hard
"inflight@npm:^1.0.4":
version: 1.0.6
resolution: "inflight@npm:1.0.6"
@@ -8298,17 +8268,17 @@ __metadata:
languageName: node
linkType: hard
"is-path-cwd@npm:^2.2.0":
version: 2.2.0
resolution: "is-path-cwd@npm:2.2.0"
checksum: 46a840921bb8cc0dc7b5b423a14220e7db338072a4495743a8230533ce78812dc152548c86f4b828411fe98c5451959f07cf841c6a19f611e46600bd699e8048
"is-path-cwd@npm:^3.0.0":
version: 3.0.0
resolution: "is-path-cwd@npm:3.0.0"
checksum: bc34d13b6a03dfca4a3ab6a8a5ba78ae4b24f4f1db4b2b031d2760c60d0913bd16a4b980dcb4e590adfc906649d5f5132684079a3972bd219da49deebb9adea8
languageName: node
linkType: hard
"is-path-inside@npm:^3.0.2":
version: 3.0.3
resolution: "is-path-inside@npm:3.0.3"
checksum: abd50f06186a052b349c15e55b182326f1936c89a78bf6c8f2b707412517c097ce04bc49a0ca221787bc44e1049f51f09a2ffb63d22899051988d3a618ba13e9
"is-path-inside@npm:^4.0.0":
version: 4.0.0
resolution: "is-path-inside@npm:4.0.0"
checksum: 8810fa11c58e6360b82c3e0d6cd7d9c7d0392d3ac9eb10f980b81f9839f40ac6d1d6d6f05d069db0d227759801228f0b072e1b6c343e4469b065ab5fe0b68fe5
languageName: node
linkType: hard
@@ -9552,7 +9522,7 @@ __metadata:
languageName: node
linkType: hard
"merge2@npm:^1.3.0, merge2@npm:^1.4.1":
"merge2@npm:^1.3.0":
version: 1.4.1
resolution: "merge2@npm:1.4.1"
checksum: 7268db63ed5169466540b6fb947aec313200bcf6d40c5ab722c22e242f651994619bcd85601602972d3c85bd2cc45a358a4c61937e9f11a061919a1da569b0c2
@@ -9667,6 +9637,15 @@ __metadata:
languageName: node
linkType: hard
"minimatch@npm:^8.0.2":
version: 8.0.4
resolution: "minimatch@npm:8.0.4"
dependencies:
brace-expansion: ^2.0.1
checksum: 2e46cffb86bacbc524ad45a6426f338920c529dd13f3a732cc2cf7618988ee1aae88df4ca28983285aca9e0f45222019ac2d14ebd17c1edadd2ee12221ab801a
languageName: node
linkType: hard
"minimatch@npm:^9.0.4":
version: 9.0.5
resolution: "minimatch@npm:9.0.5"
@@ -9743,6 +9722,13 @@ __metadata:
languageName: node
linkType: hard
"minipass@npm:^4.2.4":
version: 4.2.8
resolution: "minipass@npm:4.2.8"
checksum: 7f4914d5295a9a30807cae5227a37a926e6d910c03f315930fde52332cf0575dfbc20295318f91f0baf0e6bb11a6f668e30cde8027dea7a11b9d159867a3c830
languageName: node
linkType: hard
"minipass@npm:^5.0.0":
version: 5.0.0
resolution: "minipass@npm:5.0.0"
@@ -10344,15 +10330,6 @@ __metadata:
languageName: node
linkType: hard
"p-map@npm:^4.0.0":
version: 4.0.0
resolution: "p-map@npm:4.0.0"
dependencies:
aggregate-error: ^3.0.0
checksum: cb0ab21ec0f32ddffd31dfc250e3afa61e103ef43d957cc45497afe37513634589316de4eb88abdfd969fe6410c22c0b93ab24328833b8eb1ccc087fc0442a1c
languageName: node
linkType: hard
"p-map@npm:^7.0.2":
version: 7.0.3
resolution: "p-map@npm:7.0.3"
@@ -10503,7 +10480,7 @@ __metadata:
languageName: node
linkType: hard
"path-scurry@npm:^1.11.1":
"path-scurry@npm:^1.11.1, path-scurry@npm:^1.6.1":
version: 1.11.1
resolution: "path-scurry@npm:1.11.1"
dependencies:
@@ -10544,6 +10521,13 @@ __metadata:
languageName: node
linkType: hard
"path-type@npm:^6.0.0":
version: 6.0.0
resolution: "path-type@npm:6.0.0"
checksum: b9f6eaf7795c48d5c9bc4c6bc3ac61315b8d36975a73497ab2e02b764c0836b71fb267ea541863153f633a069a1c2ed3c247cb781633842fc571c655ac57c00e
languageName: node
linkType: hard
"pause@npm:0.0.1":
version: 0.0.1
resolution: "pause@npm:0.0.1"
@@ -11482,6 +11466,17 @@ __metadata:
languageName: node
linkType: hard
"rimraf@npm:^4.3.0":
version: 4.4.1
resolution: "rimraf@npm:4.4.1"
dependencies:
glob: ^9.2.0
bin:
rimraf: dist/cjs/src/bin.js
checksum: b786adc02651e2e24bbedb04bbdea80652fc9612632931ff2d9f898c5e4708fe30956186597373c568bd5230a4dc2fadfc816ccacba8a1daded3a006a6b74f1a
languageName: node
linkType: hard
"router@npm:^2.2.0":
version: 2.2.0
resolution: "router@npm:2.2.0"
@@ -11925,6 +11920,13 @@ __metadata:
languageName: node
linkType: hard
"slash@npm:^5.1.0":
version: 5.1.0
resolution: "slash@npm:5.1.0"
checksum: 70434b34c50eb21b741d37d455110258c42d2cf18c01e6518aeb7299f3c6e626330c889c0c552b5ca2ef54a8f5a74213ab48895f0640717cacefeef6830a1ba4
languageName: node
linkType: hard
"slice-ansi@npm:^2.1.0":
version: 2.1.0
resolution: "slice-ansi@npm:2.1.0"
@@ -13057,6 +13059,13 @@ __metadata:
languageName: node
linkType: hard
"unicorn-magic@npm:^0.3.0":
version: 0.3.0
resolution: "unicorn-magic@npm:0.3.0"
checksum: bdd7d7c522f9456f32a0b77af23f8854f9a7db846088c3868ec213f9550683ab6a2bdf3803577eacbafddb4e06900974385841ccb75338d17346ccef45f9cb01
languageName: node
linkType: hard
"unique-filename@npm:^4.0.0":
version: 4.0.0
resolution: "unique-filename@npm:4.0.0"
@@ -13248,7 +13257,7 @@ __metadata:
chokidar: ^3.6.0
class-transformer: ^0.5.1
class-validator: 0.14.0
del: ^6.0.0
del: ^8.0.0
eslint: 7.7.0
eslint-config-prettier: ^6.10.0
eslint-plugin-import: ^2.20.1
@@ -13279,11 +13288,11 @@ __metadata:
pretty-bytes: 5.6.0
promise-retry: ^2.0.1
protoc-gen-ts: ^0.8.7
puppeteer: ^23.6.0
puppeteer: ^24.10.0
qrcode: ^1.5.1
qrcode-terminal: ^0.12.0
reflect-metadata: ^0.1.13
rimraf: ^3.0.2
rimraf: ^4.3.0
rxjs: ^7.8.1
sharp: ^0.33.4
supertest: ^4.0.2
@@ -13390,7 +13399,7 @@ __metadata:
"whatsapp-web.js@github:devlikeapro/whatsapp-web.js#fork-main-2025-06-09":
version: 1.30.1-alpha.2
resolution: "whatsapp-web.js@https://github.com/devlikeapro/whatsapp-web.js.git#commit=f0e8284c9a281fa15ce2086d5668c02011947416"
resolution: "whatsapp-web.js@https://github.com/devlikeapro/whatsapp-web.js.git#commit=48fcc59575b46386747673d1b01b8f89e8c49c2d"
dependencies:
"@pedroslopez/moduleraid": ^5.0.2
archiver: ^5.3.1
@@ -13408,7 +13417,7 @@ __metadata:
optional: true
unzipper:
optional: true
checksum: ad0b97ac3b5246801af33e4e7cc34ce34b8541a3737bb97f53322f4612b8eb435eec2b47a6ef9f7f794649324d70041e3f6f6f5453be8d4b74da0051334ee98e
checksum: 7d867a4180321e85477e57b15f9ea85d2e26b6d1cf875f7e40131e4a047aaae1ad5e8b977c1ff9b3a64538276271fed06202ac6eb9168c7c5dd01eb155402f7f
languageName: node
linkType: hard