Conversation
|
Caution Review failedThe pull request is closed. WalkthroughMigrates codebase toward ES modules and dual CJS/ESM distribution, replaces legacy ESLint config with a flat eslint.config.js, tightens TypeScript types (Object/String → object/string), adjusts numerous import specifiers to explicit .js/.mjs entries, refactors callback guards, and adds build wrappers and separate TS configs. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Caller
participant Module as Library
participant Callback as OptionalCallback
Note over Module,Callback: Changed callback guard pattern
Caller->>Module: invokeOperation(..., done?)
alt done is function
Module->>Callback: if (done) done(...)
else
Module-->>Caller: proceed without invoking callback
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (46)
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
3c2a3fd to
6b6979c
Compare
There was a problem hiding this comment.
Actionable comments posted: 16
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (11)
src/api/layers/profile.layer.ts (1)
143-150: Shelling out with interpolated path is unsafe, POSIX-only, and not awaited
- Command injection/path mishandling risk via string interpolation.
- rm -Rf breaks on Windows.
- exec is fire-and-forget here; deletion isn’t awaited or checked.
Prefer retrying fs.rmSync with backoff (cross‑platform) and log on failure; drop the exec fallback.
- } catch { - exec(`rm -Rf ${folderSession}`); - } + } catch (err) { + // Retry with backoff; avoid shelling out for portability and safety + try { + fs.rmSync(folderSession, { + recursive: true, + force: true, + maxRetries: 3, + retryDelay: 100 + }); + } catch (err2) { + console.warn(`Failed to remove session folder ${folderSession}`, err2); + } + }If you must keep a fallback, use execFile with args (no shell) and await it via a Promise, but strongly prefer staying within fs APIs.
src/api/layers/business.layer.ts (2)
16-23: Missing return inside page.evaluate callback (always resolves undefined)The evaluated function doesn’t return the value from
WAPI.getBusinessProfilesProducts.- return this.page.evaluate( - ({ id }) => { - WAPI.getBusinessProfilesProducts(id); - }, - { id } - ); + return this.page.evaluate(({ id }) => WAPI.getBusinessProfilesProducts(id), { id });
33-46: Same: missing return inside page.evaluate for sendImageWithProductNo value is returned from the evaluated function.
- return this.page.evaluate( - ({ to, base64, businessId, caption, productId }) => { - WAPI.sendImageWithProduct(base64, to, caption, businessId, productId); - }, - { to, base64, businessId, caption, productId } - ); + return this.page.evaluate( + ({ to, base64, businessId, caption, productId }) => + WAPI.sendImageWithProduct(base64, to, caption, businessId, productId), + { to, base64, businessId, caption, productId } + );src/api/helpers/check-token-file.ts (1)
4-17: Harden path construction and tighten typing; simplify return.Avoid string concatenation with paths; add return type; use lowerCamelCase param; collapse boolean return.
-export function checkFileJson(mergedOptions: any, Session: string) { - const pathTokens: string = path.join( - path.resolve( - process.cwd() + mergedOptions.mkdirFolderToken, - mergedOptions.folderNameToken - ), - `${Session}.data.json` - ); - if (existsSync(pathTokens)) { - return true; - } else { - return false; - } -} +export function checkFileJson(mergedOptions: any, session: string): boolean { + const pathTokens = path.join( + process.cwd(), + mergedOptions.mkdirFolderToken, + mergedOptions.folderNameToken, + `${session}.data.json` + ); + return existsSync(pathTokens); +}src/api/helpers/delete-file.ts (1)
9-33: Await unlink and handle errors deterministically; fix path join.Wrap
unlinkin a promise/await, stop swallowing errors, and build the path portably.- const pathTokens: string = path.join( - path.resolve( - process.cwd() + mergedOptions.mkdirFolderToken, - mergedOptions.folderNameToken - ), - `${Session}.data.json` - ); + const pathTokens = path.join( + process.cwd(), + mergedOptions.mkdirFolderToken, + mergedOptions.folderNameToken, + `${session}.data.json` + ); if (existsSync(pathTokens)) { - unlink(pathTokens, (err) => { - if (err) { - spinnies.fail(`removeFile`, { - text: `Not removed file: ${pathTokens}` - }); - } - spinnies.succeed(`removeFile`, { - text: `Removed file: ${pathTokens}` - }); - }); + try { + await fs.unlink(pathTokens); + spinnies.succeed(`removeFile`, { text: `Removed file: ${pathTokens}` }); + } catch (err) { + spinnies.fail(`removeFile`, { text: `Not removed file: ${pathTokens}` }); + throw err; + } } else { spinnies.fail(`removeFile`, { text: `Not Files: ${pathTokens}` }); } - } catch (e) {} + } catch (e) { + // Optional: rethrow or log upstream + }src/api/helpers/callback-wile.ts (2)
7-21: Use Array APIs with proper typing; avoid bracket-indexed method calls.Safer, faster, clearer: short-circuit with
someand push once.- addObjects(ids: AckType | string, serializeds: string) { - let checkFilter = this.obj['filter']( - (order: any) => order.serialized === serializeds - ); - let add = null; - if (!checkFilter.length) { - add = { - id: ids, - serialized: serializeds - }; - this.obj['push'](add); - return true; - } - return false; - } + addObjects(ids: AckType | string, serializeds: string) { + if (this.obj.some(o => o.serialized === serializeds)) return false; + this.obj.push({ id: ids, serialized: serializeds }); + return true; + }
23-30: Avoidfor..inover arrays and inconsistent return types.Return an index or
-1; present code returns either a string key orfalse.- getObjKey(serialized: string) { - for (let i in this.obj) { - if (this.obj[i].serialized === serialized) { - return i; - } - } - return false; - } + getObjKey(serialized: string) { + return this.obj.findIndex(o => o.serialized === serialized); + }src/api/layers/group.layer.ts (2)
30-80: Type validation mismatch:valueis boolean but checked as'string'.
checkValuesSenderlikely expects the real type name; pass'boolean'forvalue. Also avoid the sharedtypeconstant and inline per-param types.- const typeFunction = 'setGroupSettings'; - const type = 'string'; + const typeFunction = 'setGroupSettings'; const check = [ { param: 'groupId', - type: type, + type: 'string', value: groupId, function: typeFunction, isUser: true }, { param: 'settings', - type: type, + type: 'string', // or a specific type if `GroupSettings` is enum-backed string/number value: settings, function: typeFunction, isUser: true }, { param: 'value', - type: type, + type: 'boolean', value: value, function: typeFunction, isUser: true } ];
417-444: Missingawaitonthis.page.evaluate(...)before inspectingresult.Currently
resultis a Promise;result['erro']will always beundefined, and the condition won’t behave as intended.- const result = this.page.evaluate( + const result = await this.page.evaluate( (groupId: string) => WAPI.getGroupAdmins(groupId), groupId ); - if (result['erro'] == true) { + if (result['erro'] === true) { reject(result); } else { resolve(result); }src/api/helpers/layers-interface.ts (1)
10-34: Fix non-executing loop and inconsistent return contract
- for-in with
typeof i == 'number'never enters; validation silently passes.- Return type is inconsistent when
dataisn’t an array (logs and returnsundefined).Suggested refactor for correctness and clarity:
- if (Array.isArray(data)) { - for (let i in data) { - if (typeof i == 'number') { - let result = - data[i].type && data[i].value && infoType(data[i].value, data[i].type) - ? true - : !data[i].value && data[i].isUser === false - ? true - : false; - if (!result) { - return { - erro: true, - param: data[i].param, - function: data[i].function, - text: `Invalid parameter in ${data[i].param}! Pass a variable of type ${data[i].type}!` - }; - } - } - } - return true; - } else { - console.error('Error: checkValuesSender is not array'); - } + if (!Array.isArray(data)) { + return { erro: true, to: '', text: 'checkValuesSender expects an array' }; + } + for (let i = 0; i < data.length; i++) { + const item = data[i]; + const ok = + (!!item.type && infoType(item.value, item.type)) || + (!item.value && item.isUser === false); + if (!ok) { + return { + erro: true, + param: item.param, + function: item.function, + text: `Invalid parameter in ${item.param}! Pass a variable of type ${item.type}!` + }; + } + } + return true;src/lib/wapi/serializers/serialize-message.js (1)
71-75: Guard .find() result to avoid runtime error
.find()can return undefined; accessing.contactwill throw.- groupInfo: - obj?.to?.server === 'g.us' || obj?.from?.server === 'g.us' - ? chats.find((chat) => chat.id._serialized === obj.from._serialized) - .contact - : null, + groupInfo: + obj?.to?.server === 'g.us' || obj?.from?.server === 'g.us' + ? chats.find((c) => c.id?._serialized === obj.from?._serialized)?.contact ?? null + : null,
🧹 Nitpick comments (44)
src/lib/wapi/functions/create-newsletter.js (4)
3-7: Use const and clarify payload key ('picture' vs 'image').
- options isn’t reassigned; use const.
- Verify the API expects
picture(notimage). If it expectsimage, this will silently drop the file.Suggested (keeps current API mapping while tightening style):
- let options = { - name: name, - description: description, - picture: image - }; + const options = { + name, + description, + picture: image + };If the API expects
imageinstead ofpicture, use:- const options = { - name, - description, - picture: image - }; + const options = { + name, + description, + image + };
8-9: Add a defensive guard before calling Store API.Avoid TypeErrors if Store isn’t hydrated or the module isn’t present in some WA builds.
- const resp = - await window.Store.createNewsletterQuery.createNewsletterQuery(options); + if (!window?.Store?.createNewsletterQuery?.createNewsletterQuery) { + return false; + } + const resp = + await window.Store.createNewsletterQuery.createNewsletterQuery(options);
11-12: Don’t swallow errors completely.Capture the error for debugging (browser context is fine to log at debug level).
- } catch { - return false; + } catch (err) { + console.debug('createNewsletter failed', err); + return false;
1-14: Remember to rebuild WAPI bundle.Given WAPI runs in the browser via webpack injection, rebuild after changes.
Run:
- npm run build:wapi
src/api/layers/profile.layer.ts (2)
4-4: Prefer the node: protocol for core modulesUse the node: scheme to satisfy modern ESLint rules and avoid resolver edge cases.
-import { exec } from 'child_process'; +import { exec } from 'node:child_process';
6-6: Avoid default import for fs; use namespace + node: protocolDefault import relies on esModuleInterop; the namespace form is safer and aligns with Node typings.
-import fs from 'fs'; +import * as fs from 'node:fs';src/lib/wapi/serializers/serialize-contact.js (1)
22-22: Boolean simplification + confirm fallback semantics for isUserThis already yields a boolean; the ternary is redundant. Also confirm that a defined
falseforobj.isUsershould not fall back to the server check (current??logic preservesfalse).After updating WAPI code, remember to rebuild the bundle:
npm run build:wapi.- isUser: (obj?.isUser ?? obj?.id?.server === 'c.us') ? true : false, + isUser: obj?.isUser ?? (obj?.id?.server === 'c.us'),src/api/model/enum/message-type.ts (1)
20-25: Remove duplicate enum members and model aliases externally
String-enum duplicates (PTT, STICKER) can confuse switch logic and analytics; search found no direct uses ofMediaType.PTTor.STICKER, so drop them from the enum and expose as a const alias map instead.src/api/layers/business.layer.ts (1)
12-16: Typo fixes in JSDoc“Querys” → “Queries”; “Buisness” → “Business”.
- /** - * Querys product catalog - * @param id Buisness profile id ('00000@c.us') - */ + /** + * Queries product catalog + * @param id Business profile id ('00000@c.us') + */src/controllers/initializer.ts (1)
406-417: Type narrowing for device: handle rejected evaluate with boolean default
catch(() => undefined)makesdevicepotentiallyundefined. Use a boolean default to match the annotation and simplify the subsequent check.- const device: boolean = await page + const device: boolean = await page .evaluate(() => { if ( document.querySelector('[tabindex="-1"]') && window?.Store?.Stream?.mode === InterfaceMode.SYNCING && window?.Store?.Stream?.obscurity === 'SHOW' ) { return true; } return false; }) - .catch(() => undefined); + .catch(() => false);src/lib/wapi/functions/send-contact-vcard.js (1)
31-36: Prefer a prototype-safe own-property checkAvoid potential shadowing of
hasOwnPropertyby using the prototype orObject.hasOwn(if target supports it). Behavior otherwise looks good.Rebuild WAPI after changes:
npm run build:wapi.- if (chat.lastReceivedKey?.hasOwnProperty('_serialized')) { + if (chat.lastReceivedKey && Object.prototype.hasOwnProperty.call(chat.lastReceivedKey, '_serialized')) { chat.lastReceivedKey._serialized = inChat._serialized; } - if (chat.lastReceivedKey?.hasOwnProperty('id')) { + if (chat.lastReceivedKey && Object.prototype.hasOwnProperty.call(chat.lastReceivedKey, 'id')) { chat.lastReceivedKey.id = inChat.id; }src/api/helpers/check-token-file.ts (1)
1-1: Use Node built-in specifier for clarity and bundler safety.Prefer
node:pathover'path'in ESM contexts.-import path from 'path'; +import path from 'node:path';src/lib/wapi/functions/send-file.js (1)
69-74: Use a safe own-property check and guard source fields.
obj.hasOwnPropertycan be shadowed; preferObject.prototype.hasOwnProperty.call. Also ensureinChatfields exist before assignment.- if (chat.lastReceivedKey?.hasOwnProperty('_serialized')) { - chat.lastReceivedKey._serialized = inChat._serialized; - } - if (chat.lastReceivedKey?.hasOwnProperty('id')) { - chat.lastReceivedKey.id = inChat.id; - } + if ( + chat.lastReceivedKey && + inChat?._serialized && + Object.prototype.hasOwnProperty.call(chat.lastReceivedKey, '_serialized') + ) { + chat.lastReceivedKey._serialized = inChat._serialized; + } + if ( + chat.lastReceivedKey && + inChat?.id && + Object.prototype.hasOwnProperty.call(chat.lastReceivedKey, 'id') + ) { + chat.lastReceivedKey.id = inChat.id; + }Note: after touching WAPI files, remember to rebuild the injected bundle:
npm run build:wapi.src/lib/wapi/functions/send-sticker.js (1)
11-16: Same own-property/guarding concerns as send-file.Harden checks and avoid shadowable
hasOwnProperty.- if (chat.lastReceivedKey?.hasOwnProperty('_serialized')) { - chat.lastReceivedKey._serialized = inChat._serialized; - } - if (chat.lastReceivedKey?.hasOwnProperty('id')) { - chat.lastReceivedKey.id = inChat.id; - } + if ( + chat.lastReceivedKey && + inChat?._serialized && + Object.prototype.hasOwnProperty.call(chat.lastReceivedKey, '_serialized') + ) { + chat.lastReceivedKey._serialized = inChat._serialized; + } + if ( + chat.lastReceivedKey && + inChat?.id && + Object.prototype.hasOwnProperty.call(chat.lastReceivedKey, 'id') + ) { + chat.lastReceivedKey.id = inChat.id; + }Remember to rebuild WAPI after changes:
npm run build:wapi.src/lib/middleware/webpack.config.mjs (2)
1-3: Minor: use Node built-in specifiers consistently.-import path from 'path'; +import path from 'node:path';
8-26: Stabilize entry resolution by setting context.Without
context,entry: './middleware.ts'is resolved from CWD, not from the config’s folder. Addcontext: __dirname.-export default { +export default { + context: __dirname, entry: './middleware.ts',src/api/helpers/callback-wile.ts (1)
32-40: Boolean existence check can be simpler.Use
someinstead of allocating withfilter.- checkObj(id: AckType | string, serialized: string) { - let checkFilter = this.obj['filter']( - (order: any) => order.id === id && order.serialized === serialized - ); - if (checkFilter.length) { - return true; - } - return false; - } + checkObj(id: AckType | string, serialized: string) { + return this.obj.some(order => order.id === id && order.serialized === serialized); + }src/lib/wapi/functions/test.js (1)
13-18: Prefer'in'guards (or a single null-check) overhasOwnPropertyhere.
hasOwnPropertycan be shadowed;'in'is safer given typed shape. Or just set both whenlastReceivedKeyexists.- if (chat.lastReceivedKey?.hasOwnProperty('_serialized')) { - chat.lastReceivedKey._serialized = inChat._serialized; - } - if (chat.lastReceivedKey?.hasOwnProperty('id')) { - chat.lastReceivedKey.id = inChat.id; - } + if (chat.lastReceivedKey) { + if ('_serialized' in chat.lastReceivedKey) chat.lastReceivedKey._serialized = inChat._serialized; + if ('id' in chat.lastReceivedKey) chat.lastReceivedKey.id = inChat.id; + }Please run
npm run build:wapiafter updating WAPI functions per project guidelines to ensure the injected bundle is rebuilt.src/api/helpers/file-to-base64.ts (1)
21-27: Minor: function nameMinelooks like a typo.Consider renaming to
mimeLookupfor clarity; keep return type asPromise<string | false>.src/lib/wapi/webpack.config.mjs (1)
9-30: Confirm ESM config is used; optional env-driven config enhancements
npm run build:wapirunscd src/lib/wapi && webpack, which by default loadswebpack.config.mjswhen"type":"module"is set (stackoverflow.com).- Optional in src/lib/wapi/webpack.config.mjs (lines 9–30):
- // mode: 'development', - // devtool: 'source-map', + mode: process.env.NODE_ENV === 'development' ? 'development' : 'production', + devtool: process.env.NODE_ENV === 'development' ? 'source-map' : false, ... - filename: 'wapi.js' + filename: 'wapi.js', + clean: truesrc/lib/wapi/functions/send-ptt.js (1)
32-37: Same guard style nit: prefer'in'or a single null-check.Keeps consistency and avoids
hasOwnPropertypitfalls.- if (chat.lastReceivedKey?.hasOwnProperty('_serialized')) { - chat.lastReceivedKey._serialized = inChat._serialized; - } - if (chat.lastReceivedKey?.hasOwnProperty('id')) { - chat.lastReceivedKey.id = inChat.id; - } + if (chat.lastReceivedKey) { + if ('_serialized' in chat.lastReceivedKey) chat.lastReceivedKey._serialized = inChat._serialized; + if ('id' in chat.lastReceivedKey) chat.lastReceivedKey.id = inChat.id; + }Remember to rebuild the WAPI bundle after changes:
npm run build:wapi.src/api/layers/host.layer.ts (1)
220-246: Usethis.statusFind(...)consistently.You check
this.statusFindbut invoke the barestatusFind(...). Call the instance field to avoid accidental drift and for consistency with Line 96.- if (this.statusFind) statusFind('notLogged', this.session); + if (this.statusFind) this.statusFind('notLogged', this.session); ... - if (this.statusFind) statusFind('qrReadFail', this.session); + if (this.statusFind) this.statusFind('qrReadFail', this.session); ... - if (this.statusFind) statusFind('qrReadSuccess', this.session); + if (this.statusFind) this.statusFind('qrReadSuccess', this.session); ... - if (this.statusFind) statusFind('qrReadFail', this.session); + if (this.statusFind) this.statusFind('qrReadFail', this.session); ... - if (this.statusFind) statusFind('isLogged', this.session); + if (this.statusFind) this.statusFind('isLogged', this.session); ... - if (this.statusFind) statusFind('phoneNotConnected', this.session); + if (this.statusFind) this.statusFind('phoneNotConnected', this.session);Also applies to: 259-259
src/api/layers/group.layer.ts (1)
255-284: Consider validatingtimeor make it optional.You ignore
timein the checks but pass it to WAPI; add a check entry or make it optional.src/types/WAPI.d.ts (5)
71-72: Narrow return types for connection state and message key.
- Prefer a string-literal union for connection state.
- Expose a structured
MessageKeyinstead of opaqueobject.Apply:
- getStateConnection: () => string; - getNewMessageId: (chatId: string) => object; + getStateConnection: () => + 'OPEN' | 'CONNECTING' | 'DISCONNECTED' | 'TIMEOUT' | 'CONFLICT' | 'UNPAIRED'; + getNewMessageId: (chatId: string) => MessageKey;Add this type in the same file:
export interface MessageKey { fromMe: boolean; remote: string; // chatId id: string; _serialized: string; }
134-147: Avoidobjectfor passId; use a safer structural type.
objecthampers usage and narrowing. Preferstring | number | Record<string, unknown>.- passId?: object, + passId?: string | number | Record<string, unknown>,Repeat for other occurrences in sendImage/sendMessage/sendPtt.
186-196: Return types for sendListMenu/sendMessage should be structured.
Promise<object>obscures the result contract. If an envelope is returned, useRecord<string, unknown>or defineSendMessageResult.- ) => Promise<object>; + ) => Promise<Record<string, unknown>>;Optionally, introduce:
export interface SendMessageResult { id: string; ack: number; isNewMsg: boolean; /* ... */ }
266-266: Consider restricting emoji input.If only a single emoji is valid, document or validate it (e.g., non-empty string), otherwise
stringis acceptable.
74-74: Align getNumberProfile signature to return Promise- getNumberProfile: (contactId: string) => object; + getNumberProfile: (contactId: string) => Promise<WhatsappProfile>;Ensure
_serializeMeObjoutput matches theWhatsappProfileshape.src/lib/wapi/functions/get-list-mute.js (3)
1-10: Simplify loop and prefer const/let; aligns with upgraded ESLint rules.Use
for...ofwithconstand literal arrays; behavior unchanged, readability improved.-export async function getListMute(type = 'all') { - var muteList = (await window.Store.Mute)._models, - noMute = new Array(), - toMute = new Array(); - for (var i in muteList) - if (muteList[i].__x_isMuted) { - toMute.push(WAPI.interfaceMute(muteList[i])); - } else { - noMute.push(WAPI.interfaceMute(muteList[i])); - } +export async function getListMute(type = 'all') { + const muteList = (await window.Store.Mute)._models; + const noMute = []; + const toMute = []; + for (const item of muteList) { + if (item.__x_isMuted) { + toMute.push(WAPI.interfaceMute(item)); + } else { + noMute.push(WAPI.interfaceMute(item)); + } + }
12-12: Remove stray console.log or guard it behind a debug flag.This leaks noise into the page console during injection.
- console.log(0, type); + // debug: console.debug('[getListMute]', type);
13-31: Handle unexpected type values with a default case.Without a default, the function returns
nullfor invalid inputs.switch (type) { case 'all': r = [ { total: toMute.length + noMute.length, amountToMute: toMute.length, amountnoMute: noMute.length }, toMute, noMute ]; break; case 'toMute': r = [{ total: toMute.length }, toMute]; break; case 'noMute': r = [{ total: noMute.length }, noMute]; break; + default: + r = [{ total: 0 }, []]; + break; }Also consider narrowing the signature to
type?: 'all' | 'toMute' | 'noMute'insrc/types/WAPI.d.tsfor stronger contracts.src/api/helpers/layers-interface.ts (1)
15-19: Simplify nested ternaryMinor readability tweak:
- let result = - data[i].type && data[i].value && infoType(data[i].value, data[i].type) - ? true - : !data[i].value && data[i].isUser === false - ? true - : false; + const ok = + (!!item.type && infoType(item.value, item.type)) || + (!item.value && item.isUser === false);src/lib/wapi/serializers/serialize-message.js (2)
15-19: Prefer nullish coalescing for chatIdSame behavior, simpler:
- chatId: obj?.id?.remote - ? obj?.id?.remote - : obj?.chatId?._serialized - ? obj?.chatId?._serialized - : undefined, + chatId: obj?.id?.remote ?? obj?.chatId?._serialized ?? undefined,
76-77: Null-guard reply target
_chatmay be{};_chat.idcould be undefined.- reply: (body) => window.WAPI.reply(_chat.id._serialized, body, obj) + reply: (body) => _chat?.id?._serialized + ? window.WAPI.reply(_chat.id._serialized, body, obj) + : undefinedAlso ensure to rebuild WAPI after changes:
npm run build:wapi..commitlintrc.js (1)
1-1: ESM config loading confirmed—no changes required
commitlint v18+ supports consuming.commitlintrc.jswithexport defaultwhen yourpackage.jsonhas"type":"module"cite12• Optional: to follow the docs recommendation for Node v24+ and avoid potential
ERR_REQUIRE_ESM, you may rename.commitlintrc.jsto.commitlintrc.mjsorcommitlint.config.mjs.src/api/layers/callback-on.layes.ts (2)
1-1: Filename and layer naming conventionFile name appears misspelled and doesn’t follow
*.layer.tsguideline. Consider renaming tocallback-on.layer.ts.
17-25: Endless loop without cancellation
while (true)with 50ms sleep lacks an exit/cancel path. Consider supporting anAbortSignalor a class-level cancel.- async onChange(event: (status: any) => void) { + async onChange(event: (status: any) => void, signal?: AbortSignal) { let change = null; - while (true) { + while (!signal?.aborted) { if (this.statusFind !== change) { change = this.statusFind; if (event) event(change); } await sleep(50); } + return; }src/lib/wapi/serialize/serialize-message.js (1)
23-27: Prefer nullish coalescing for chatIdStylistic only:
- obj.id && obj.id.remote - ? obj.id.remote - : obj.chatId && obj.chatId._serialized - ? obj.chatId._serialized - : undefined, + obj.id?.remote ?? obj.chatId?._serialized ?? undefined,src/api/layers/sender.layer.ts (2)
55-56: Type narrowing looks fine; consider a concrete result type for better DX.Changing Promise → Promise is a safe narrowing, but all these methods gate on result['erro'] at runtime. Defining a shared result shape (e.g., type WapiResult = { erro?: boolean } & Record<string, unknown>) will give callers proper intellisense and prevent accidental misuse.
Apply this minimal change to the four signatures:
-): Promise<object> { +): Promise<WapiResult> {Add near the top of this file (or a shared types module):
type WapiResult = { erro?: boolean } & Record<string, unknown>;Also applies to: 291-292, 351-352, 382-383
16-16: Unused import: Mutex.Mutex is imported but never used in this class. Drop it to keep the file clean.
-import { Mutex } from 'async-mutex';package.json (3)
23-27: Lint scripts: redundant executions and config flag inconsistency.fix:imports runs eslint twice (and lint:fix doesn’t pass -c like lint:js/ts). Simplify to one pass with the same config.
- "fix:imports": "eslint --fix \"src/**/*.{js,jsx,ts,tsx}\" && npm run lint:fix", + "fix:imports": "eslint -c eslint.config.js --fix \"src/**/*.{js,jsx,ts,tsx}\"", - "lint:fix": "npx eslint src --fix", + "lint:fix": "eslint -c eslint.config.js src --fix",
76-78: typescript-eslint deps are duplicated; align on one approach.You have both @typescript-eslint/* and typescript-eslint. Prefer either:
- Classic: keep @typescript-eslint/eslint-plugin + @typescript-eslint/parser and remove typescript-eslint; or
- New API: use typescript-eslint’s helpers/configs and drop the separate plugin/parser imports.
Mixing both increases drift risk.
Option A (remove meta package):
- "typescript-eslint": "^8.43.0",Option B (adopt meta package; remove plugin & parser and update config accordingly):
- "@typescript-eslint/eslint-plugin": "^8.0.0", - "@typescript-eslint/parser": "^8.0.0", + "typescript-eslint": "^8.43.0",I can update eslint.config.js for Option B if you choose it.
Also applies to: 92-92
1-120: Optional: declare supported Node engine to reflect ESM + tooling requirements.Pinning engines helps avoid Node <18 environments where ESM/ESLint 9/webpack-cli 6 can fail.
"homepage": "https://github.com/orkestral/venom#readme", + "engines": { + "node": ">=18.18.0" + },eslint.config.js (1)
19-61: Optional: simplify by using typescript-eslint’s flat presets directly.If you adopt the meta package, you can drop FlatCompat here and use tseslint.configs.recommended.
I can provide a cleaned-up config if you choose Option B in package.json.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json📒 Files selected for processing (45)
.commitlintrc.js(1 hunks).eslintignore(0 hunks).eslintrc.cjs(2 hunks)eslint.config.js(1 hunks)package.json(3 hunks)src/api/helpers/callback-wile.ts(2 hunks)src/api/helpers/check-token-file.ts(1 hunks)src/api/helpers/closes-browser.ts(1 hunks)src/api/helpers/delete-file.ts(1 hunks)src/api/helpers/file-to-base64.ts(1 hunks)src/api/helpers/layers-interface.ts(1 hunks)src/api/layers/business.layer.ts(1 hunks)src/api/layers/callback-on.layes.ts(1 hunks)src/api/layers/controls.layer.ts(1 hunks)src/api/layers/group.layer.ts(5 hunks)src/api/layers/host.layer.ts(5 hunks)src/api/layers/profile.layer.ts(2 hunks)src/api/layers/sender.layer.ts(4 hunks)src/api/model/enum/message-type.ts(1 hunks)src/controllers/check-up-to-date.ts(1 hunks)src/controllers/initializer.ts(12 hunks)src/lib/counter/gulpfile.js(0 hunks)src/lib/counter/gulpfile.mjs(1 hunks)src/lib/middleware/webpack.config.mjs(1 hunks)src/lib/wapi/functions/create-newsletter.js(1 hunks)src/lib/wapi/functions/demote-participant.js(2 hunks)src/lib/wapi/functions/get-list-mute.js(1 hunks)src/lib/wapi/functions/promote-participant.js(2 hunks)src/lib/wapi/functions/remove-participant.js(2 hunks)src/lib/wapi/functions/send-contact-vcard.js(1 hunks)src/lib/wapi/functions/send-file.js(1 hunks)src/lib/wapi/functions/send-message.js(1 hunks)src/lib/wapi/functions/send-ptt.js(1 hunks)src/lib/wapi/functions/send-sticker.js(1 hunks)src/lib/wapi/functions/sendMessageOptions.js(1 hunks)src/lib/wapi/functions/test.js(1 hunks)src/lib/wapi/jssha/index.js(22 hunks)src/lib/wapi/serialize/serialize-message.js(1 hunks)src/lib/wapi/serializers/serialize-contact.js(1 hunks)src/lib/wapi/serializers/serialize-message.js(1 hunks)src/lib/wapi/wapi.js(3 hunks)src/lib/wapi/webpack.config.cjs(0 hunks)src/lib/wapi/webpack.config.js(0 hunks)src/lib/wapi/webpack.config.mjs(1 hunks)src/types/WAPI.d.ts(5 hunks)💤 Files with no reviewable changes (4)
- src/lib/wapi/webpack.config.js
- .eslintignore
- src/lib/counter/gulpfile.js
- src/lib/wapi/webpack.config.cjs
🧰 Additional context used
📓 Path-based instructions (6)
src/api/helpers/**/*.{ts,js}
📄 CodeRabbit inference engine (CLAUDE.md)
Put utility helpers (e.g., encryption, QR code utilities) under src/api/helpers
Files:
src/api/helpers/layers-interface.tssrc/api/helpers/check-token-file.tssrc/api/helpers/closes-browser.tssrc/api/helpers/delete-file.tssrc/api/helpers/file-to-base64.tssrc/api/helpers/callback-wile.tssrc/api/layers/*.layer.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Keep functionality layers in src/api/layers using the *.layer.ts naming (e.g., sender.layer.ts, listener.layer.ts, group.layer.ts, profile.layer.ts, controls.layer.ts, retriever.layer.ts)
Files:
src/api/layers/controls.layer.tssrc/api/layers/sender.layer.tssrc/api/layers/business.layer.tssrc/api/layers/host.layer.tssrc/api/layers/profile.layer.tssrc/api/layers/group.layer.tssrc/lib/wapi/functions/**/*.js
📄 CodeRabbit inference engine (CLAUDE.md)
WAPI functions in src/lib/wapi/functions are JavaScript files injected into the browser; after changing them, run
npm run build:wapito rebuildFiles:
src/lib/wapi/functions/get-list-mute.jssrc/lib/wapi/functions/send-contact-vcard.jssrc/lib/wapi/functions/demote-participant.jssrc/lib/wapi/functions/send-message.jssrc/lib/wapi/functions/send-file.jssrc/lib/wapi/functions/send-ptt.jssrc/lib/wapi/functions/promote-participant.jssrc/lib/wapi/functions/sendMessageOptions.jssrc/lib/wapi/functions/remove-participant.jssrc/lib/wapi/functions/create-newsletter.jssrc/lib/wapi/functions/send-sticker.jssrc/lib/wapi/functions/test.jssrc/lib/wapi/**/*.js
📄 CodeRabbit inference engine (CLAUDE.md)
WAPI layer code is built with webpack and injected into the Puppeteer browser context
Files:
src/lib/wapi/functions/get-list-mute.jssrc/lib/wapi/functions/send-contact-vcard.jssrc/lib/wapi/wapi.jssrc/lib/wapi/functions/demote-participant.jssrc/lib/wapi/functions/send-message.jssrc/lib/wapi/serialize/serialize-message.jssrc/lib/wapi/functions/send-file.jssrc/lib/wapi/functions/send-ptt.jssrc/lib/wapi/functions/promote-participant.jssrc/lib/wapi/serializers/serialize-message.jssrc/lib/wapi/functions/sendMessageOptions.jssrc/lib/wapi/serializers/serialize-contact.jssrc/lib/wapi/functions/remove-participant.jssrc/lib/wapi/functions/create-newsletter.jssrc/lib/wapi/functions/send-sticker.jssrc/lib/wapi/functions/test.jssrc/lib/wapi/jssha/index.jssrc/controllers/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Controllers (initializer.ts for session creation, browser.ts for Puppeteer management, auth.ts for authentication/QR) live under src/controllers
Files:
src/controllers/check-up-to-date.tssrc/controllers/initializer.tssrc/api/model/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Place TypeScript interfaces and data models under src/api/model
Files:
src/api/model/enum/message-type.ts🧠 Learnings (7)
📓 Common learnings
Learnt from: CR PR: venomlib/venom#0 File: CLAUDE.md:0-0 Timestamp: 2025-09-08T17:49:03.312Z Learning: Applies to src/lib/wapi/**/*.js : WAPI layer code is built with webpack and injected into the Puppeteer browser context📚 Learning: 2025-09-08T17:49:03.312Z
Learnt from: CR PR: venomlib/venom#0 File: CLAUDE.md:0-0 Timestamp: 2025-09-08T17:49:03.312Z Learning: Applies to src/api/layers/*.layer.ts : Keep functionality layers in src/api/layers using the *.layer.ts naming (e.g., sender.layer.ts, listener.layer.ts, group.layer.ts, profile.layer.ts, controls.layer.ts, retriever.layer.ts)Applied to files:
src/api/helpers/layers-interface.tssrc/api/layers/sender.layer.ts📚 Learning: 2025-09-08T17:49:03.312Z
Learnt from: CR PR: venomlib/venom#0 File: CLAUDE.md:0-0 Timestamp: 2025-09-08T17:49:03.312Z Learning: Applies to src/lib/wapi/**/*.js : WAPI layer code is built with webpack and injected into the Puppeteer browser contextApplied to files:
src/lib/wapi/webpack.config.mjssrc/lib/wapi/wapi.js.eslintrc.cjssrc/api/layers/profile.layer.tssrc/lib/middleware/webpack.config.mjs📚 Learning: 2025-09-08T17:49:03.312Z
Learnt from: CR PR: venomlib/venom#0 File: CLAUDE.md:0-0 Timestamp: 2025-09-08T17:49:03.312Z Learning: Applies to src/lib/wapi/functions/**/*.js : WAPI functions in src/lib/wapi/functions are JavaScript files injected into the browser; after changing them, run `npm run build:wapi` to rebuildApplied to files:
src/lib/wapi/webpack.config.mjssrc/lib/wapi/wapi.js.eslintrc.cjs📚 Learning: 2025-09-08T17:49:03.312Z
Learnt from: CR PR: venomlib/venom#0 File: CLAUDE.md:0-0 Timestamp: 2025-09-08T17:49:03.312Z Learning: Applies to tsconfig.json : TypeScript must target ESNext with CommonJS modules, output to ./dist, and generate declaration files and source mapsApplied to files:
eslint.config.js.eslintrc.cjs📚 Learning: 2025-09-08T17:49:03.312Z
Learnt from: CR PR: venomlib/venom#0 File: CLAUDE.md:0-0 Timestamp: 2025-09-08T17:49:03.312Z Learning: Applies to src/config/**/*.ts : Keep browser/Puppeteer and session management configuration under src/configApplied to files:
.eslintrc.cjs📚 Learning: 2025-09-08T17:49:03.312Z
Learnt from: CR PR: venomlib/venom#0 File: CLAUDE.md:0-0 Timestamp: 2025-09-08T17:49:03.312Z Learning: Run ESLint for both TypeScript and JavaScript code and fix issues (`npm run lint`, `lint:fix`, `lint:ts`, `lint:js`)Applied to files:
package.json🧬 Code graph analysis (23)
src/lib/counter/gulpfile.mjs (3)
eslint.config.js (2)
__filename(10-10)__dirname(11-11)src/lib/middleware/webpack.config.mjs (2)
__filename(5-5)__dirname(6-6)src/lib/wapi/webpack.config.mjs (2)
__filename(6-6)__dirname(7-7)src/lib/wapi/webpack.config.mjs (3)
eslint.config.js (2)
__filename(10-10)__dirname(11-11)src/lib/middleware/webpack.config.mjs (2)
__filename(5-5)__dirname(6-6)src/api/whatsapp.ts (1)
initService(29-77)src/lib/wapi/functions/get-list-mute.js (1)
src/api/layers/retriever.layer.ts (1)
getListMutes(78-83)src/lib/wapi/functions/send-contact-vcard.js (2)
src/api/model/chat.ts (2)
LastReceivedKey(42-47)Chat(5-31)src/api/model/message.ts (1)
LastReceivedKey(112-117)src/lib/wapi/wapi.js (2)
src/lib/wapi/store/store-objects.js (3)
module(344-347)module(319-319)module(189-190)src/lib/wapi/functions/send-seen.js (1)
WAPI(5-7)eslint.config.js (3)
src/lib/counter/gulpfile.mjs (2)
__filename(6-6)__dirname(7-7)src/lib/middleware/webpack.config.mjs (2)
__filename(5-5)__dirname(6-6)src/lib/wapi/webpack.config.mjs (2)
__filename(6-6)__dirname(7-7)src/lib/wapi/functions/send-message.js (2)
src/api/model/chat.ts (2)
LastReceivedKey(42-47)Chat(5-31)src/api/model/message.ts (1)
LastReceivedKey(112-117)src/api/layers/callback-on.layes.ts (2)
src/lib/wapi/listeners/add-on-state-change.js (2)
callback(27-27)callback(9-9)src/api/layers/listener.layer.ts (1)
participantChangedEvent(455-456)src/lib/wapi/serialize/serialize-message.js (5)
src/lib/wapi/functions/send-message.js (5)
obj(85-90)obj(98-103)obj(119-119)obj(124-129)obj(141-141)src/lib/wapi/functions/send-ptt.js (2)
obj(169-169)obj(178-178)src/lib/wapi/functions/send-sticker.js (2)
obj(47-47)obj(51-51)src/lib/wapi/functions/send-location.js (1)
sendLocation(1-66)src/api/whatsapp.ts (1)
messageId(167-167)src/lib/wapi/functions/send-file.js (2)
src/api/model/chat.ts (2)
LastReceivedKey(42-47)Chat(5-31)src/api/model/message.ts (1)
LastReceivedKey(112-117)src/api/layers/business.layer.ts (2)
src/api/layers/listener.layer.ts (1)
constructor(51-63)src/api/layers/retriever.layer.ts (1)
constructor(8-15)src/lib/wapi/functions/send-ptt.js (2)
src/api/model/chat.ts (2)
LastReceivedKey(42-47)Chat(5-31)src/api/model/message.ts (1)
LastReceivedKey(112-117)src/lib/wapi/serializers/serialize-message.js (1)
src/api/model/message.ts (3)
Message(1-81)LastReceivedKey(112-117)Presence(119-122)src/api/helpers/delete-file.ts (1)
src/controllers/browser.ts (1)
error(795-834)src/lib/wapi/serializers/serialize-contact.js (2)
src/lib/wapi/functions/send-message.js (5)
obj(85-90)obj(98-103)obj(119-119)obj(124-129)obj(141-141)src/lib/wapi/functions/get-all-contacts.js (1)
result(6-8)src/api/layers/profile.layer.ts (1)
src/controllers/browser.ts (2)
folderSession(135-195)execAsync(256-264)src/api/helpers/file-to-base64.ts (1)
src/lib/wapi/helper/base64-to-file.js (1)
mime(4-4)src/lib/middleware/webpack.config.mjs (4)
eslint.config.js (2)
__filename(10-10)__dirname(11-11)src/lib/counter/gulpfile.mjs (2)
__filename(6-6)__dirname(7-7)src/lib/wapi/webpack.config.mjs (2)
__filename(6-6)__dirname(7-7)src/lib/wapi/store/store-objects.js (1)
module(270-271)src/lib/wapi/functions/create-newsletter.js (1)
src/lib/wapi/store/store-objects.js (1)
module(490-490)src/lib/wapi/functions/send-sticker.js (2)
src/api/model/chat.ts (2)
LastReceivedKey(42-47)Chat(5-31)src/api/model/message.ts (1)
LastReceivedKey(112-117)src/lib/wapi/functions/test.js (2)
src/api/model/chat.ts (2)
LastReceivedKey(42-47)Chat(5-31)src/api/model/message.ts (1)
LastReceivedKey(112-117)src/api/model/enum/message-type.ts (1)
src/api/model/message.ts (3)
MediaData(124-131)Message(1-81)Sender(83-101)src/types/WAPI.d.ts (2)
src/api/model/message.ts (1)
Message(1-81)src/api/model/chat.ts (1)
Chat(5-31)🪛 Biome (2.1.2)
src/lib/wapi/jssha/index.js
[error] 1145-1145: A global variable should not be reassigned.
Assigning to a global variable can override essential functionality.
(lint/suspicious/noGlobalAssign)
🔇 Additional comments (15)
src/controllers/initializer.ts (1)
188-188: LGTM: explicit callback guards are clearer and saferReplacing short-circuit calls with explicit
ifguards improves readability and avoids accidental non-function invocation. No behavior change beyond clarity.Also applies to: 210-210, 215-215, 221-221, 250-250, 262-262, 271-271, 277-277, 295-295, 307-307, 326-326, 333-333, 340-340, 349-349, 356-356, 363-363, 436-436, 469-469, 483-483
src/api/helpers/closes-browser.ts (1)
21-26: LGTM on explicit callback guards.Replacing short-circuit invocation with explicit checks improves readability without semantic change.
src/api/helpers/file-to-base64.ts (1)
1-1: Verify TypeScript module interop settings
File: src/api/helpers/file-to-base64.ts:1 — no tsconfig.json found; ensureesModuleInteroporallowSyntheticDefaultImportsis enabled, or switch toimport * as mimeTypes from 'mime-types'to prevent runtime import-shape issues.
src/api/layers/host.layer.ts (1)
315-317: Return type change looks good.
Promise<object>aligns with the repo-wide primitive type usage.src/api/layers/group.layer.ts (2)
129-168: OK: return type tightened.Signature change to
Promise<object>is consistent with the codebase shift.
175-217: OK: return type tightened.Same as above.
src/types/WAPI.d.ts (2)
64-64: Verify getGroupAdmins return shape
The implementation insrc/lib/wapi/functions/get-group-admins.jscurrently only guards ongroupIdbut the actual returned value isn’t apparent. Confirm whether it returns an array of admin IDs (string[]) or fullContactobjects (Contact[]) and tighten the signature insrc/types/WAPI.d.tsaccordingly.
68-68: Update getGroupParticipant signature in types/WAPI.d.ts
- Change
time: stringtotime?: numberto match the implementation’s default numeric timeout (1000).- Replace the vague
objectreturn with the correctPromise<…>type (e.g.Promise<Contact>); confirm the actual return type.src/lib/wapi/wapi.js (2)
158-158: getStore is correctly exported as a named export; no changes required.
125-158: Verify ESM aggregators and rebuild WAPI bundle
- Aggregator index.js files export all expected symbols (confirmed).
- After installing dependencies, run
npm installthennpm run build:wapito rebuild the injected bundle.src/api/layers/callback-on.layes.ts (1)
22-22: Explicit guard is fine
if (event) event(change);is equivalent to the short-circuit call and clearer. LGTM.src/lib/wapi/serialize/serialize-message.js (1)
7-8: Do not overridequotedMsgObj—keep the call unchanged.
obj.quotedMsgObj()is a WAPI‐provided method that populatesobj.quotedMsgfor serialization; assigning it would break that functionality.Likely an incorrect or invalid review comment.
src/lib/wapi/functions/sendMessageOptions.js (1)
82-84: Formatting-only change looks goodNo behavioral differences introduced.
src/api/layers/controls.layer.ts (1)
181-182: Type tightening to Promise is OKMatches the PR’s typing normalization. Ensure corresponding declarations in
src/types/WAPI.d.tsand downstream call sites align.package.json (1)
88-89: Confirm release-it downgrade to v16.1.0 is intentional and compatible
Ensure CI/release scripts and docs don’t rely on v19 behaviors that may have changed.
There was a problem hiding this comment.
Actionable comments posted: 14
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (6)
src/api/layers/business.layer.ts (1)
17-22: page.evaluate callback doesn’t return a value; always resolves to undefined.Return the WAPI call so the result is propagated.
- return this.page.evaluate( - ({ id }) => { - WAPI.getBusinessProfilesProducts(id); - }, - { id } - ); + return this.page.evaluate(({ id }) => WAPI.getBusinessProfilesProducts(id), { id });src/lib/wapi/serializers/serialize-message.js (1)
71-76: Fix potential TypeError in groupInfo and hardening reply target resolution.
- chats.find(...).contact will throw if find returns undefined; obj.from may be undefined too.
- _chat may be {} when obj.chat is absent; accessing _chat.id._serialized in reply() can throw.
Apply this diff to guard both paths and avoid computing chats unless needed:
- let chats = await WAPI.getAllChats(); + // Lazily load chats only if we need group info + let chats = null; ... - groupInfo: - obj?.to?.server === 'g.us' || obj?.from?.server === 'g.us' - ? chats.find((chat) => chat.id._serialized === obj.from._serialized) - .contact - : null, - reply: (body) => window.WAPI.reply(_chat.id._serialized, body, obj) + groupInfo: + obj?.to?.server === 'g.us' || obj?.from?.server === 'g.us' + ? (() => { + if (!chats) return null; + const groupJid = + obj?.to?.server === 'g.us' + ? obj?.to?._serialized + : obj?.from?._serialized; + return ( + chats + ?.find((chat) => chat?.id?._serialized === groupJid) + ?.contact ?? null + ); + })() + : null, + reply: (body) => { + const targetId = + _chat?.id?._serialized ?? + obj?.id?.remote ?? + obj?.chatId?._serialized; + if (!targetId) return null; + return window.WAPI.reply(targetId, body, obj); + }Follow-up: if you keep groupInfo, initialize
chats = await WAPI.getAllChats()only when group context is detected to avoid a hot path call per message.src/api/helpers/layers-interface.ts (1)
11-31: Loop never runs: typeof i is always "string". Validation effectively disabled.Using
for (let i in data)and checkingtypeof i == 'number'means the body is skipped; returns true even for invalid input.Apply this fix:
- if (Array.isArray(data)) { - for (let i in data) { - if (typeof i == 'number') { - let result = - data[i].type && data[i].value && infoType(data[i].value, data[i].type) - ? true - : !data[i].value && data[i].isUser === false - ? true - : false; - if (!result) { - return { - erro: true, - param: data[i].param, - function: data[i].function, - text: `Invalid parameter in ${data[i].param}! Pass a variable of type ${data[i].type}!` - }; - } - } - } - return true; - } else { + if (Array.isArray(data)) { + for (let i = 0; i < data.length; i++) { + const item = data[i]; + const result = + (item?.type && item?.value && infoType(item.value, item.type)) || + (!item?.value && item?.isUser === false); + if (!result) { + return { + erro: true, + param: item?.param, + function: item?.function, + text: `Invalid parameter in ${item?.param}! Pass a variable of type ${item?.type}!` + }; + } + } + return true; + } else { console.error('Error: checkValuesSender is not array'); }Optional: return a consistent shape (boolean vs error object) or type this function accordingly.
src/api/layers/host.layer.ts (1)
220-246: Call the same source you guard: usethis.statusFind?.(...)consistently.You check
this.statusFindbut call the shadowed parameterstatusFind(...). Use the instance field to avoid drift.Apply:
- if (this.statusFind) statusFind('notLogged', this.session); + this.statusFind?.('notLogged', this.session); @@ - if (this.statusFind) statusFind('qrReadFail', this.session); + this.statusFind?.('qrReadFail', this.session); @@ - if (this.statusFind) statusFind('qrReadSuccess', this.session); + this.statusFind?.('qrReadSuccess', this.session); @@ - if (this.statusFind) statusFind('qrReadFail', this.session); + this.statusFind?.('qrReadFail', this.session); @@ - if (this.statusFind) statusFind('isLogged', this.session); + this.statusFind?.('isLogged', this.session); @@ - if (this.statusFind) statusFind('phoneNotConnected', this.session); + this.statusFind?.('phoneNotConnected', this.session);Also applies to: 258-260
src/controllers/initializer.ts (1)
406-417: Type mismatch from evaluate().catch — ensure boolean, not boolean|undefined.
.catch(() => undefined)widens the type; later strict builds may fail. Returnfalseon catch or widen the type explicitly.- const device: boolean = await page + const device: boolean = await page .evaluate(() => { if ( document.querySelector('[tabindex="-1"]') && window?.Store?.Stream?.mode === InterfaceMode.SYNCING && window?.Store?.Stream?.obscurity === 'SHOW' ) { return true; } return false; }) - .catch(() => undefined); + .catch(() => false);src/api/layers/group.layer.ts (1)
434-441: Bug: missing await on this.page.evaluate() leads to Promise misuse.
resultis a Promise; property access on it is wrong and control flow will misbehave.- const result = this.page.evaluate( + const result = await this.page.evaluate( (groupId: string) => WAPI.getGroupAdmins(groupId), groupId ); - if (result['erro'] == true) { + if (result['erro'] == true) { reject(result); } else { resolve(result); }
🧹 Nitpick comments (31)
src/lib/wapi/functions/create-newsletter.js (2)
3-7: Use const and object shorthand for options.Minor cleanup; avoids a mutable binding and redundant keys.
- let options = { - name: name, - description: description, - picture: image - }; + const options = { + name, + description, + picture: image + };
11-12: Capture the error for easier diagnostics (optional).Helps when debugging failures without changing return shape.
- } catch { - return false; - } + } catch (e) { + // eslint-disable-next-line no-console + console.debug('createNewsletter failed', e); + return false; + }src/api/layers/business.layer.ts (3)
12-15: JSDoc typos.“Querys” → “Queries”; “Buisness” → “Business”.
- /** - * Querys product catalog - * @param id Buisness profile id ('00000@c.us') - */ + /** + * Queries the product catalog + * @param id Business profile id ('00000@c.us') + */
26-32: Clarify parameter docs and types.“Business id number” conflicts with the string example. Use “Business ID” and keep it as a string.
- * @param businessId Business id number that owns the product ('0000@c.us') + * @param businessId Business ID that owns the product (e.g., '0000@c.us')
16-23: Add explicit return types for better API clarity.Make the methods’ return types explicit (unknown or the concrete WAPI return type).
- public async getBusinessProfilesProducts(id: string) { + public async getBusinessProfilesProducts(id: string): Promise<unknown> { ... - ) { + ): Promise<unknown> {Also applies to: 33-46
src/api/helpers/layers-interface.ts (1)
7-9: Nit: simplify boolean helper.
infoTypecan return the comparison directly.-function infoType(data: string, type: string) { - return typeof data === type ? true : false; -} +function infoType(data: unknown, type: string) { + return typeof data === type; +}src/lib/wapi/serialize/serialize-message.js (2)
2-2: Nit: prefer strict/nullish check.Use
obj == nullor strict=== undefinedto avoid accidental coercion.- if (obj == undefined) { + if (obj == null) {
12-17: Tidy redundant nested ternary.Can be simplified with optional chaining; same for author and to.
- quotedParticipant: obj.quotedParticipant - ? obj.quotedParticipant._serialized - ? obj.quotedParticipant._serialized - : undefined - : undefined, + quotedParticipant: obj.quotedParticipant?._serialized,src/api/layers/callback-on.layes.ts (1)
19-25: Optional: add a cancellation mechanism to avoid runaway loop.Expose an abort signal or return a disposer to stop the while(true) when the listener is no longer needed.
Example sketch:
async onChange(event: (status: any) => void, signal?: AbortSignal) { let change = null; while (!signal?.aborted) { if (this.statusFind !== change) { change = this.statusFind; event?.(change); } await sleep(50); } }src/lib/wapi/functions/demote-participant.js (1)
15-18: No-contacts path: callback is fine but consider a scoped result object.If other participant functions return a WAPI.scope object on failure, keep consistency here too.
src/lib/wapi/functions/sendMessageOptions.js (1)
82-84: Ensure vCard body is set when parsing raw VCARD textFor consistency with the single-contact branch (which sets
body), setbody: contenthere so the message payload shape is uniform.- vcardOptions = { - type: 'vcard', - vcardFormattedName: - await window.Store.VCard.vcardGetNameFromParsed(parsed) - }; + vcardOptions = { + type: 'vcard', + body: content, + vcardFormattedName: await window.Store.VCard.vcardGetNameFromParsed(parsed) + };src/api/helpers/delete-file.ts (1)
11-17: Fix path construction (string concat with cwd is brittle)Use path segments instead of
process.cwd() + …to avoid malformed paths.- const pathTokens: string = path.join( - path.resolve( - process.cwd() + mergedOptions.mkdirFolderToken, - mergedOptions.folderNameToken - ), - `${Session}.data.json` - ); + const pathTokens: string = path.join( + path.resolve( + process.cwd(), + mergedOptions.mkdirFolderToken, + mergedOptions.folderNameToken + ), + `${Session}.data.json` + );src/api/helpers/check-token-file.ts (1)
5-11: Use safe path joins (avoid string concat with cwd)Same path construction issue as in delete-file.ts.
- const pathTokens: string = path.join( - path.resolve( - process.cwd() + mergedOptions.mkdirFolderToken, - mergedOptions.folderNameToken - ), - `${Session}.data.json` - ); + const pathTokens: string = path.join( + path.resolve( + process.cwd(), + mergedOptions.mkdirFolderToken, + mergedOptions.folderNameToken + ), + `${Session}.data.json` + );src/lib/wapi/functions/get-list-mute.js (1)
12-12: Remove console.log from injected WAPI codeAvoid noisy logs in the browser context.
- console.log(0, type); + // console.log removedsrc/lib/wapi/jssha/index.js (1)
1-1: Prefer vendoring rule-exceptions at repo level for minified libs.Rather than file-wide disabling of
@typescript-eslint/no-unused-expressions, consider excluding this vendor/minified file from lint or scoping disables to specific lines. Keeps noise out of app code.src/lib/wapi/functions/send-file.js (1)
68-75: Use safehasOwnPropertycheck to avoid shadowing.Calling
obj.hasOwnPropertycan be unsafe if overridden. UseObject.prototype.hasOwnProperty.call(...).Apply:
- if (chat.lastReceivedKey?.hasOwnProperty('_serialized')) { + if ( + chat.lastReceivedKey && + Object.prototype.hasOwnProperty.call(chat.lastReceivedKey, '_serialized') + ) { chat.lastReceivedKey._serialized = inChat._serialized; } - if (chat.lastReceivedKey?.hasOwnProperty('id')) { + if ( + chat.lastReceivedKey && + Object.prototype.hasOwnProperty.call(chat.lastReceivedKey, 'id') + ) { chat.lastReceivedKey.id = inChat.id; }src/api/helpers/file-to-base64.ts (1)
21-27: Nit:Minereturnsstring | falsesynchronously; keep return consistent.Optional: make it non-async since no awaits; or explicitly coerce falsy.
Example:
-export async function Mine(path: string) { +export function Mine(path: string) { if (fs.existsSync(path)) { - return mimeTypes.lookup(path); + return mimeTypes.lookup(path) || false; } else { return false; } }src/lib/wapi/functions/test.js (1)
12-18: Mirror safehasOwnPropertypattern here as well.Consistent with
send-file.js, avoid directhasOwnPropertycalls.Apply:
- if (chat.lastReceivedKey?.hasOwnProperty('_serialized')) { + if ( + chat.lastReceivedKey && + Object.prototype.hasOwnProperty.call(chat.lastReceivedKey, '_serialized') + ) { chat.lastReceivedKey._serialized = inChat._serialized; } - if (chat.lastReceivedKey?.hasOwnProperty('id')) { + if ( + chat.lastReceivedKey && + Object.prototype.hasOwnProperty.call(chat.lastReceivedKey, 'id') + ) { chat.lastReceivedKey.id = inChat.id; }src/lib/wapi/functions/send-contact-vcard.js (1)
31-36: Prefer a prototype-safe property check.Using obj.hasOwnProperty can fail if the prototype is null or overridden. Use Object.prototype.hasOwnProperty.call for robustness.
- if (chat.lastReceivedKey?.hasOwnProperty('_serialized')) { + if (chat.lastReceivedKey && Object.prototype.hasOwnProperty.call(chat.lastReceivedKey, '_serialized')) { chat.lastReceivedKey._serialized = inChat._serialized; } - if (chat.lastReceivedKey?.hasOwnProperty('id')) { + if (chat.lastReceivedKey && Object.prototype.hasOwnProperty.call(chat.lastReceivedKey, 'id')) { chat.lastReceivedKey.id = inChat.id; }I can apply this pattern across similar WAPI functions for consistency. Also remember to run
npm run build:wapiafter WAPI edits.src/lib/wapi/functions/send-sticker.js (1)
11-16: Make the property guard prototype-safe (mirrors other WAPI spots).Avoid direct
.hasOwnPropertyon possibly exotic objects.- if (chat.lastReceivedKey?.hasOwnProperty('_serialized')) { + if (chat.lastReceivedKey && Object.prototype.hasOwnProperty.call(chat.lastReceivedKey, '_serialized')) { chat.lastReceivedKey._serialized = inChat._serialized; } - if (chat.lastReceivedKey?.hasOwnProperty('id')) { + if (chat.lastReceivedKey && Object.prototype.hasOwnProperty.call(chat.lastReceivedKey, 'id')) { chat.lastReceivedKey.id = inChat.id; }I can roll this change into a single commit covering all WAPI functions. Don’t forget
npm run build:wapi.src/lib/wapi/webpack.config.mjs (1)
2-5: Minor ESM tidy + env-driven mode/devtool.Unify path imports and enable mode/devtool from NODE_ENV for predictable builds.
-import path from 'path'; -import { fileURLToPath } from 'node:url'; -import { dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { dirname, resolve } from 'node:path'; @@ export default { entry: './wapi.js', - // mode: 'development', - // devtool: 'source-map', + mode: process.env.NODE_ENV === 'production' ? 'production' : 'development', + devtool: process.env.NODE_ENV === 'production' ? false : 'source-map', output: { - path: path.resolve(__dirname, '../../../dist/lib/wapi'), + path: resolve(__dirname, '../../../dist/lib/wapi'), filename: 'wapi.js' }, resolve: { extensions: ['.js'] // let you omit .js }, module: { rules: [ { test: /\.js$/, resolve: { fullySpecified: false // <─ here, inside resolve } } ] } };Also applies to: 11-16, 14-15, 18-29
src/api/layers/sender.layer.ts (1)
375-383: Align passId type with WAPI.d.ts.WAPI now types
passId?: object; mirror it here for better safety.- public async sendText( + public async sendText( to: string, content: string, - passId?: any, + passId?: object, checkNumber?: boolean, forcingReturn?: boolean, delSend?: boolean ): Promise<object> {eslint.config.js (4)
50-61: Right-size a few broad rule disablesTurning these fully off can hide bugs. Suggest narrower settings:
- Use
no-constant-conditionwith{ checkLoops: false }to allowwhile (true)but flag others.- Prefer
no-useless-catch: 'warn'andprefer-const: 'warn'to keep signal without blocking.- 'no-constant-condition': 'off', + 'no-constant-condition': ['warn', { checkLoops: false }], @@ - 'no-useless-catch': 'off', + 'no-useless-catch': 'warn', @@ - 'prefer-const': 'off' + 'prefer-const': 'warn'
35-44: Re-enable unused vars with safe defaults (keeps signal, avoids churn)Completely disabling
@typescript-eslint/no-unused-varsoften hides mistakes. Recommend warning level with common ignore patterns.- '@typescript-eslint/no-unused-vars': 'off', + '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_', caughtErrorsIgnorePattern: '^_' }],
19-61: Optional: adopt@typescript-eslintflat preset for type-checked rulesSwitch your TS extends to the flat, type-checked preset and enable
parserOptions.project:...compat.extends( - 'plugin:@typescript-eslint/eslint-recommended', - 'plugin:@typescript-eslint/recommended', + // eslint:recommended via compat + ...typescriptEslint.configs.recommendedTypeChecked, 'prettier', 'plugin:prettier/recommended' ),languageOptions: { parser: tsParser, + parserOptions: { project: true } },Then install deps and confirm it loads without errors:
npm install npx eslint --print-config src/index.ts >/dev/null && echo "Flat config OK"
102-103: Optional: make ignores recursive for nestedstore/files and directories
Update the pattern tosrc/lib/wapi/store/**so that all nested files and folders understore/are ignored, not just its immediate entries. (eslint.org)- globalIgnores(['src/lib/wapi/store/*']) + globalIgnores(['src/lib/wapi/store/**'])src/lib/wapi/serializers/serialize-contact.js (1)
22-22: Prefer Boolean(...) over ternary for clarity.Equivalent, shorter, and avoids any operator-precedence second-guessing.
Apply this diff:
- isUser: (obj?.isUser ?? obj?.id?.server === 'c.us') ? true : false, + isUser: Boolean(obj?.isUser ?? (obj?.id?.server === 'c.us')),src/api/helpers/closes-browser.ts (1)
21-21: Type/usage mismatch: guard implies optional callback; make it optional and use?..Current signature requires
callStatus, but you guard its presence. Make it optional and simplify calls.Apply this diff:
- callStatus: (e: string) => void + callStatus?: (e: string) => void- if (callStatus) callStatus('serverClose'); + callStatus?.('serverClose');- if (callStatus) callStatus('browserClose'); + callStatus?.('browserClose');Also applies to: 25-25
src/api/model/enum/message-type.ts (1)
20-25: Avoid duplicate enum values; use explicit aliases instead.Duplicate values complicate reverse lookups and tooling; prefer aliases or a mapping object.
Apply this diff to remove duplicates:
AUDIO = 'Audio', - // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values - PTT = 'Audio', DOCUMENT = 'Document', - // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values - STICKER = 'Image' + STICKER = 'Image'Then add an alias map (outside this enum):
export const MediaAliases = { PTT: MediaType.AUDIO, STICKER: MediaType.IMAGE } as const;src/api/layers/controls.layer.ts (1)
178-182: Return type tweak is fine; update JSDoc to match and remove stale param.JSDoc above still mentions “onlyLocal” and
@returns boolean. Align it withPromise<object>and actual params.Do you want me to sweep the layer APIs for similar doc/type drifts?
.eslintrc.cjs (1)
10-11: Deprecated Prettier config entry.
prettier/@typescript-eslinthas been removed; useprettier.Apply this diff:
- 'prettier/@typescript-eslint', + 'prettier',If migrating to flat config (
eslint.config.js), consider deleting.eslintrc.cjsentirely to avoid split-brain config.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (45)
.commitlintrc.js(1 hunks).eslintignore(0 hunks).eslintrc.cjs(2 hunks)eslint.config.js(1 hunks)package.json(3 hunks)src/api/helpers/callback-wile.ts(2 hunks)src/api/helpers/check-token-file.ts(1 hunks)src/api/helpers/closes-browser.ts(1 hunks)src/api/helpers/delete-file.ts(1 hunks)src/api/helpers/file-to-base64.ts(1 hunks)src/api/helpers/layers-interface.ts(1 hunks)src/api/layers/business.layer.ts(1 hunks)src/api/layers/callback-on.layes.ts(1 hunks)src/api/layers/controls.layer.ts(1 hunks)src/api/layers/group.layer.ts(5 hunks)src/api/layers/host.layer.ts(5 hunks)src/api/layers/profile.layer.ts(2 hunks)src/api/layers/sender.layer.ts(4 hunks)src/api/model/enum/message-type.ts(1 hunks)src/controllers/check-up-to-date.ts(1 hunks)src/controllers/initializer.ts(12 hunks)src/lib/counter/gulpfile.js(0 hunks)src/lib/counter/gulpfile.mjs(1 hunks)src/lib/middleware/webpack.config.mjs(1 hunks)src/lib/wapi/functions/create-newsletter.js(1 hunks)src/lib/wapi/functions/demote-participant.js(2 hunks)src/lib/wapi/functions/get-list-mute.js(1 hunks)src/lib/wapi/functions/promote-participant.js(2 hunks)src/lib/wapi/functions/remove-participant.js(2 hunks)src/lib/wapi/functions/send-contact-vcard.js(1 hunks)src/lib/wapi/functions/send-file.js(1 hunks)src/lib/wapi/functions/send-message.js(1 hunks)src/lib/wapi/functions/send-ptt.js(1 hunks)src/lib/wapi/functions/send-sticker.js(1 hunks)src/lib/wapi/functions/sendMessageOptions.js(1 hunks)src/lib/wapi/functions/test.js(1 hunks)src/lib/wapi/jssha/index.js(22 hunks)src/lib/wapi/serialize/serialize-message.js(1 hunks)src/lib/wapi/serializers/serialize-contact.js(1 hunks)src/lib/wapi/serializers/serialize-message.js(1 hunks)src/lib/wapi/wapi.js(3 hunks)src/lib/wapi/webpack.config.cjs(0 hunks)src/lib/wapi/webpack.config.js(0 hunks)src/lib/wapi/webpack.config.mjs(1 hunks)src/types/WAPI.d.ts(5 hunks)
💤 Files with no reviewable changes (4)
- .eslintignore
- src/lib/counter/gulpfile.js
- src/lib/wapi/webpack.config.js
- src/lib/wapi/webpack.config.cjs
🧰 Additional context used
📓 Path-based instructions (6)
src/controllers/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Controllers (initializer.ts for session creation, browser.ts for Puppeteer management, auth.ts for authentication/QR) live under src/controllers
Files:
src/controllers/check-up-to-date.tssrc/controllers/initializer.ts
src/api/layers/*.layer.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Keep functionality layers in src/api/layers using the *.layer.ts naming (e.g., sender.layer.ts, listener.layer.ts, group.layer.ts, profile.layer.ts, controls.layer.ts, retriever.layer.ts)
Files:
src/api/layers/controls.layer.tssrc/api/layers/group.layer.tssrc/api/layers/sender.layer.tssrc/api/layers/profile.layer.tssrc/api/layers/host.layer.tssrc/api/layers/business.layer.ts
src/lib/wapi/functions/**/*.js
📄 CodeRabbit inference engine (CLAUDE.md)
WAPI functions in src/lib/wapi/functions are JavaScript files injected into the browser; after changing them, run
npm run build:wapito rebuild
Files:
src/lib/wapi/functions/promote-participant.jssrc/lib/wapi/functions/send-message.jssrc/lib/wapi/functions/send-file.jssrc/lib/wapi/functions/test.jssrc/lib/wapi/functions/send-ptt.jssrc/lib/wapi/functions/demote-participant.jssrc/lib/wapi/functions/sendMessageOptions.jssrc/lib/wapi/functions/create-newsletter.jssrc/lib/wapi/functions/send-contact-vcard.jssrc/lib/wapi/functions/send-sticker.jssrc/lib/wapi/functions/get-list-mute.jssrc/lib/wapi/functions/remove-participant.js
src/lib/wapi/**/*.js
📄 CodeRabbit inference engine (CLAUDE.md)
WAPI layer code is built with webpack and injected into the Puppeteer browser context
Files:
src/lib/wapi/functions/promote-participant.jssrc/lib/wapi/functions/send-message.jssrc/lib/wapi/functions/send-file.jssrc/lib/wapi/wapi.jssrc/lib/wapi/functions/test.jssrc/lib/wapi/serialize/serialize-message.jssrc/lib/wapi/functions/send-ptt.jssrc/lib/wapi/functions/demote-participant.jssrc/lib/wapi/functions/sendMessageOptions.jssrc/lib/wapi/functions/create-newsletter.jssrc/lib/wapi/functions/send-contact-vcard.jssrc/lib/wapi/serializers/serialize-contact.jssrc/lib/wapi/functions/send-sticker.jssrc/lib/wapi/functions/get-list-mute.jssrc/lib/wapi/functions/remove-participant.jssrc/lib/wapi/serializers/serialize-message.jssrc/lib/wapi/jssha/index.js
src/api/helpers/**/*.{ts,js}
📄 CodeRabbit inference engine (CLAUDE.md)
Put utility helpers (e.g., encryption, QR code utilities) under src/api/helpers
Files:
src/api/helpers/check-token-file.tssrc/api/helpers/file-to-base64.tssrc/api/helpers/closes-browser.tssrc/api/helpers/layers-interface.tssrc/api/helpers/delete-file.tssrc/api/helpers/callback-wile.ts
src/api/model/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Place TypeScript interfaces and data models under src/api/model
Files:
src/api/model/enum/message-type.ts
🧠 Learnings (8)
📓 Common learnings
Learnt from: CR
PR: venomlib/venom#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-08T17:49:03.312Z
Learning: Applies to src/lib/wapi/**/*.js : WAPI layer code is built with webpack and injected into the Puppeteer browser context
📚 Learning: 2025-09-08T17:49:03.312Z
Learnt from: CR
PR: venomlib/venom#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-08T17:49:03.312Z
Learning: Applies to src/lib/wapi/functions/**/*.js : WAPI functions in src/lib/wapi/functions are JavaScript files injected into the browser; after changing them, run `npm run build:wapi` to rebuild
Applied to files:
src/lib/wapi/wapi.js.eslintrc.cjssrc/lib/wapi/jssha/index.jssrc/lib/wapi/webpack.config.mjs
📚 Learning: 2025-09-08T17:49:03.312Z
Learnt from: CR
PR: venomlib/venom#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-08T17:49:03.312Z
Learning: Applies to src/lib/wapi/**/*.js : WAPI layer code is built with webpack and injected into the Puppeteer browser context
Applied to files:
src/lib/wapi/wapi.js.eslintrc.cjssrc/api/layers/profile.layer.tssrc/lib/middleware/webpack.config.mjssrc/lib/wapi/webpack.config.mjs
📚 Learning: 2025-09-08T17:49:03.312Z
Learnt from: CR
PR: venomlib/venom#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-08T17:49:03.312Z
Learning: Applies to src/api/layers/*.layer.ts : Keep functionality layers in src/api/layers using the *.layer.ts naming (e.g., sender.layer.ts, listener.layer.ts, group.layer.ts, profile.layer.ts, controls.layer.ts, retriever.layer.ts)
Applied to files:
src/api/layers/sender.layer.ts
📚 Learning: 2025-09-08T17:49:03.312Z
Learnt from: CR
PR: venomlib/venom#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-08T17:49:03.312Z
Learning: Applies to tsconfig.json : TypeScript must target ESNext with CommonJS modules, output to ./dist, and generate declaration files and source maps
Applied to files:
.eslintrc.cjseslint.config.jspackage.json
📚 Learning: 2025-09-08T17:49:03.312Z
Learnt from: CR
PR: venomlib/venom#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-08T17:49:03.312Z
Learning: Applies to src/config/**/*.ts : Keep browser/Puppeteer and session management configuration under src/config
Applied to files:
.eslintrc.cjs
📚 Learning: 2025-09-08T17:49:03.312Z
Learnt from: CR
PR: venomlib/venom#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-08T17:49:03.312Z
Learning: Applies to src/controllers/*.ts : Controllers (initializer.ts for session creation, browser.ts for Puppeteer management, auth.ts for authentication/QR) live under src/controllers
Applied to files:
src/controllers/initializer.ts
📚 Learning: 2025-09-08T17:49:03.312Z
Learnt from: CR
PR: venomlib/venom#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-08T17:49:03.312Z
Learning: Run ESLint for both TypeScript and JavaScript code and fix issues (`npm run lint`, `lint:fix`, `lint:ts`, `lint:js`)
Applied to files:
package.json
🧬 Code graph analysis (25)
src/lib/wapi/functions/send-message.js (2)
src/api/model/chat.ts (2)
LastReceivedKey(42-47)Chat(5-31)src/api/model/message.ts (1)
LastReceivedKey(112-117)
src/lib/wapi/functions/send-file.js (5)
src/lib/wapi/functions/send-contact-vcard.js (2)
chat(15-15)inChat(26-28)src/lib/wapi/functions/send-sticker.js (2)
chat(2-2)inChat(7-9)src/lib/wapi/functions/reply.js (2)
chat(26-26)inChat(61-61)src/lib/wapi/functions/send-message.js (1)
inChat(42-44)src/lib/wapi/functions/send-image.js (1)
sendImage(11-21)
src/lib/wapi/wapi.js (1)
src/lib/wapi/store/store-objects.js (1)
module(344-347)
src/lib/wapi/functions/test.js (2)
src/lib/wapi/functions/send-contact-vcard.js (2)
chat(15-15)inChat(26-28)src/api/model/chat.ts (2)
LastReceivedKey(42-47)Chat(5-31)
src/api/helpers/file-to-base64.ts (1)
src/lib/wapi/helper/base64-to-file.js (1)
mime(4-4)
src/lib/wapi/serialize/serialize-message.js (5)
src/lib/wapi/functions/send-message.js (5)
obj(85-90)obj(98-103)obj(119-119)obj(124-129)obj(141-141)src/lib/wapi/functions/send-ptt.js (2)
obj(169-169)obj(178-178)src/lib/wapi/functions/send-sticker.js (2)
obj(47-47)obj(51-51)src/api/model/chat.ts (2)
Chat(5-31)LastReceivedKey(42-47)src/api/model/message.ts (1)
Message(1-81)
src/lib/wapi/functions/send-ptt.js (2)
src/lib/wapi/functions/send-location.js (3)
chat(7-7)inChat(18-18)sendLocation(1-66)src/api/model/chat.ts (2)
LastReceivedKey(42-47)Chat(5-31)
src/api/layers/callback-on.layes.ts (2)
src/lib/wapi/listeners/add-on-state-change.js (1)
callback(27-27)src/api/layers/listener.layer.ts (1)
participantChangedEvent(455-456)
src/api/helpers/closes-browser.ts (1)
src/controllers/browser.ts (3)
statusLog(703-738)browser(579-582)() => {}(732-732)
src/lib/wapi/functions/demote-participant.js (1)
src/lib/wapi/functions/send-seen.js (1)
sendSeen(1-15)
src/lib/wapi/functions/sendMessageOptions.js (1)
src/lib/wapi/functions/send-contact-vcard-list.js (1)
e(45-49)
src/api/helpers/layers-interface.ts (1)
src/api/model/message.ts (1)
Sender(83-101)
src/lib/wapi/functions/create-newsletter.js (1)
src/lib/wapi/store/store-objects.js (1)
module(490-490)
src/lib/wapi/functions/send-contact-vcard.js (1)
src/lib/wapi/functions/send-contact-vcard-list.js (5)
chat(29-29)inChat(53-53)sendContactVcardList(1-96)e(32-34)e(45-49)
src/lib/wapi/serializers/serialize-contact.js (1)
src/lib/wapi/functions/get-all-contacts.js (2)
result(6-8)allContacts(1-9)
src/lib/wapi/functions/send-sticker.js (2)
src/lib/wapi/functions/send-contact-vcard.js (2)
chat(15-15)inChat(26-28)src/api/model/chat.ts (2)
Chat(5-31)LastReceivedKey(42-47)
src/lib/wapi/functions/get-list-mute.js (2)
src/api/layers/retriever.layer.ts (1)
getListMutes(78-83)src/lib/wapi/store/store-objects.js (1)
module(311-311)
src/api/layers/profile.layer.ts (1)
src/controllers/browser.ts (1)
folderSession(135-195)
src/lib/middleware/webpack.config.mjs (3)
eslint.config.js (2)
__filename(10-10)__dirname(11-11)src/lib/counter/gulpfile.mjs (2)
__filename(6-6)__dirname(7-7)src/lib/wapi/webpack.config.mjs (2)
__filename(6-6)__dirname(7-7)
src/controllers/initializer.ts (1)
src/controllers/browser.ts (3)
initWhatsapp(41-122)statusLog(703-738)target(720-731)
eslint.config.js (3)
src/lib/counter/gulpfile.mjs (2)
__filename(6-6)__dirname(7-7)src/lib/middleware/webpack.config.mjs (2)
__filename(5-5)__dirname(6-6)src/lib/wapi/webpack.config.mjs (2)
__filename(6-6)__dirname(7-7)
src/lib/counter/gulpfile.mjs (3)
eslint.config.js (2)
__filename(10-10)__dirname(11-11)src/lib/middleware/webpack.config.mjs (2)
__filename(5-5)__dirname(6-6)src/lib/wapi/webpack.config.mjs (2)
__filename(6-6)__dirname(7-7)
src/api/layers/business.layer.ts (3)
app.js (2)
page(24-24)browser(25-25)src/api/layers/retriever.layer.ts (1)
constructor(8-15)src/api/layers/listener.layer.ts (1)
constructor(51-63)
src/lib/wapi/webpack.config.mjs (4)
eslint.config.js (2)
__filename(10-10)__dirname(11-11)src/lib/counter/gulpfile.mjs (2)
__filename(6-6)__dirname(7-7)src/lib/middleware/webpack.config.mjs (2)
__filename(5-5)__dirname(6-6)src/api/whatsapp.ts (1)
initService(29-77)
src/types/WAPI.d.ts (1)
src/api/model/message.ts (1)
Message(1-81)
🪛 Biome (2.1.2)
src/lib/wapi/jssha/index.js
[error] 1145-1145: A global variable should not be reassigned.
Assigning to a global variable can override essential functionality.
(lint/suspicious/noGlobalAssign)
🔇 Additional comments (31)
src/lib/wapi/functions/create-newsletter.js (2)
8-9: LGTM: formatting-only; behavior unchanged.No functional impact; await path and return remain identical.
2-13: Verifybuild:wapienvironment and rerun build
Thenpm run build:wapistep failed withwebpack: not found. Ensurewebpackis installed (e.g., listed in devDependencies) and available on your PATH, then rerunnpm run build:wapito confirm the Store-guard refactor builds cleanly.src/api/layers/business.layer.ts (2)
41-45: The shell script will confirm the exact parameter order forsendImageWithProduct(and reveal ifgetBusinessProfilesProductsexists under a similar path). Once you have that output, I can verify the parameter mapping in yourevaluatecall and finalize the review comment.
5-8: Align BusinessLayer constructor signature to (browser, page)BusinessLayer declares
(page, browser)but callssuper(browser, page)and all other layers use(browser, page). This mismatch risks swapping arguments at instantiation.
Apply:src/api/layers/business.layer.ts constructor( - public page: Page, - public browser: Browser + public browser: Browser, + public page: Page ) { super(browser, page); }No
new BusinessLayer(...)calls found in the repo—verify external call sites (DI, tests, consumers) to update any usages accordingly.src/lib/wapi/serializers/serialize-message.js (1)
18-19: LGTM: formatting-only change.Indentation change preserves behavior of chatId fallback chain.
src/lib/wapi/wapi.js (4)
125-126: ESM-friendly explicit imports look good.Moving to
./functions/index.jsavoids ambiguous dir resolution.
133-134: Consistent explicit entrypoints.Helper imports updated to
index.js— aligns with ESM and bundlers.
148-149: All listener exports are correctly named and flat-exported; import block is safe.
157-159: WAPI imports and entry files verified. All requiredsrc/lib/wapientry files exist and no extensionless imports remain. Remember to runnpm run build:wapiafter modifying any WAPI files.src/lib/wapi/serialize/serialize-message.js (1)
26-27: LGTM: formatting-only change.Ternary indentation change for chatId is non-functional.
src/api/layers/callback-on.layes.ts (1)
22-22: LGTM: explicit guard is clearer.
if (event) event(change);improves readability over short-circuit call.src/lib/wapi/functions/sendMessageOptions.js (1)
1-127: Rebuild WAPI bundle after changesPlease run: npm run build:wapi to regenerate the injected bundle.
src/api/layers/profile.layer.ts (1)
6-6: Verify TS config for defaultfsimport
import fs from 'fs'requiresesModuleInteropor NodeNext module resolution. If not enabled, switch toimport * as fs from 'fs'.src/api/helpers/delete-file.ts (1)
6-6: Primitive type change looks good
String→stringis correct and safer for public API..commitlintrc.js (1)
1-1: ESM export may not be loaded from.commitlintrc.jsCommitlint typically expects CJS in dotfiles. Either rename to
commitlint.config.js(ESM) or revert to CJS export.-export default { +module.exports = {src/lib/wapi/functions/send-ptt.js (2)
32-37: Guarding withhasOwnPropertymay skip necessary updatesIf the fields are absent, assignments won’t run, diverging from prior behavior. Prefer checking object existence and assigning.
- if (inChat) { - if (chat.lastReceivedKey?.hasOwnProperty('_serialized')) { - chat.lastReceivedKey._serialized = inChat._serialized; - } - if (chat.lastReceivedKey?.hasOwnProperty('id')) { - chat.lastReceivedKey.id = inChat.id; - } - } + if (inChat && chat.lastReceivedKey) { + chat.lastReceivedKey._serialized = inChat._serialized; + chat.lastReceivedKey.id = inChat.id; + }
1-187: Rebuild WAPI bundle after changesPlease run: npm run build:wapi to regenerate the injected bundle.
src/api/helpers/check-token-file.ts (1)
1-1: ESM + primitive type change look goodImports and
stringtype are fine.Also applies to: 4-4
src/lib/wapi/functions/get-list-mute.js (1)
6-10: LGTM: clearer than the ternaryThe explicit if/else improves readability.
src/lib/wapi/functions/send-message.js (1)
47-52: Improved property existence checking with hasOwnProperty.The change from truthy checks to
hasOwnPropertychecks is more precise - it updates the properties when they exist regardless of their current truthiness. This avoids issues where properties might be falsy but still need updating.src/lib/middleware/webpack.config.mjs (2)
1-6: LGTM! Proper ES module migration pattern.The migration follows the established pattern seen in other webpack configs in this PR:
- ES module imports replace CommonJS
require__dirnameis properly derived usingfileURLToPathanddirname- The approach is consistent with similar files like
src/lib/wapi/webpack.config.mjs
8-8: LGTM! ES module export syntax.The export syntax correctly follows ES module standards and aligns with the package.json
"type": "module"setting established in this PR.src/lib/wapi/functions/remove-participant.js (1)
15-18: LGTM: explicit callback guard on empty input.Switching from short-circuit to explicit guard improves clarity without changing behavior.
src/api/layers/host.layer.ts (1)
96-99: Nice: status callback before auto-close.Emitting 'autocloseCalled' prior to closing improves observability.
src/api/helpers/file-to-base64.ts (1)
1-1: esModuleInterop enabled – default import ofmime-typesis safe
Root tsconfig.json has"esModuleInterop": true, satisfying interop for CommonJS modules.package.json (1)
23-26: Unify lint:fix with explicit config invocation
Change lint:fix tonpx eslint -c eslint.config.js --ext .js,.ts src --fixso it matches lint:js/ts and guarantees the flat config is applied; manually verify CI picks up eslint.config.js (e.g.
npx eslint -c eslint.config.js --print-config .).src/controllers/initializer.ts (1)
188-188: LGTM: explicit optional-callback guards.Replacing short-circuit invocation with explicit
if (...)improves clarity and satisfies stricter ESLint rules. No behavior regression.Also applies to: 210-210, 215-215, 221-221, 251-251, 263-263, 271-271, 277-277, 295-295, 306-306, 326-326, 333-333, 340-340, 349-349, 356-356, 363-363, 436-436, 469-469, 483-483
src/api/layers/group.layer.ts (1)
34-35: LGTM: Promise typing normalization.Consistent with the repo-wide switch from
Objecttoobjectand narrows expectations.Also applies to: 129-129, 178-179, 255-256, 417-417
src/types/WAPI.d.ts (1)
64-64: LGTM: d.ts refinements (object/string, Promise).These align the public typings with actual runtime shapes and reduce
anyleakage.Also applies to: 68-68, 71-75, 135-135, 147-147, 186-187, 191-191, 195-196, 266-266
src/api/layers/sender.layer.ts (1)
55-56: LGTM: Promise return types.Matches WAPI.d.ts updates and improves type consistency across layers.
Also applies to: 291-292, 351-352, 382-383
eslint.config.js (1)
1-9: Nice setup with FlatCompat and ESM helpersImports,
__filename/__dirname, andFlatCompatwiring look correct. Once theextendsplacement is fixed, this should compose cleanly.Also applies to: 13-17
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (5)
eslint.config.js (4)
65-69: Modernize parsing; remove empty parserOptions.Use latest ECMAScript; no need for empty parserOptions.
languageOptions: { - ecmaVersion: 6, + ecmaVersion: 'latest', sourceType: 'module', - parserOptions: {},
83-88: JS override uses a TS-only rule.Swap to the base rule so JS files don’t depend on TS plugin.
rules: { - '@typescript-eslint/no-array-constructor': 'off', + 'no-array-constructor': 'off', 'no-prototype-builtins': 'off', 'no-redeclare': 'off', 'no-console': 0 }
91-100: Tooling overrides: ensure ESM parsing for webpack/gulp configs.Explicitly set modern ecmaVersion and module sourceType here too.
{ files: ['src/lib/**/webpack.*.{js,mjs}', 'src/lib/**/gulpfile.mjs'], languageOptions: { + ecmaVersion: 'latest', + sourceType: 'module', globals: { ...Object.fromEntries( Object.entries(globals.browser).map(([key]) => [key, 'off']) ), ...globals.node } } },
19-33: Flat config misuse:extendsis ignored; spread compat at top level and scope TS to TS files.-export default defineConfig([ - { - languageOptions: { - parser: tsParser - }, - plugins: { - '@typescript-eslint': typescriptEslint - }, - extends: compat.extends( - 'eslint:recommended', - 'plugin:@typescript-eslint/eslint-recommended', - 'plugin:@typescript-eslint/recommended', - 'prettier', - 'plugin:prettier/recommended' - ), +export default defineConfig([ + ...compat.extends( + 'eslint:recommended', + 'plugin:@typescript-eslint/eslint-recommended', + 'plugin:@typescript-eslint/recommended', + 'prettier', + 'plugin:prettier/recommended' + ), + { + files: ['**/*.ts', '**/*.tsx'], + languageOptions: { + parser: tsParser + }, + plugins: { + '@typescript-eslint': typescriptEslint + },package.json (1)
5-20: Dual-package surface added — good step toward non-breaking ESM/CJS.The new main/module + conditional exports map addresses prior feedback about CJS consumers. Nice.
🧹 Nitpick comments (6)
tsconfig.cjs.json (1)
4-8: Centralize declarations to a single output
Disabledeclarationin tsconfig.cjs.json and update alltypesexports in package.json (bothimport.typesandrequire.types) to./dist/index.d.ts, so only the ESM build emits.d.ts.package.json (5)
8-20: Conditional "types" entries are likely ignored by TypeScript.TS resolves types via top-level "types" or "typesVersions"; nested "types" inside "exports" aren’t used by tsc/Editor TS. Consider removing them and rely on the top-level "types": "dist/index.d.ts" to avoid confusion.
"import": { - "types": "./dist/esm/index.d.ts", "default": "./dist/index.js" }, "require": { - "types": "./dist/cjs/index.d.ts", "default": "./dist/index.cjs" }
26-31: Build split + wrapper step looks fine; add a quick guard for stale wrappers.Minor: to prevent publishing stale wrappers if a step fails, chain with
&&(already used) and consider cleaning dist before building to avoid cross-contamination between cjs/esm.Example:
- "build:venom": "npm run build:venom:cjs && npm run build:venom:esm && npm run build:wrapper", + "build:venom": "shx rm -rf dist && npm run build:venom:cjs && npm run build:venom:esm && npm run build:wrapper",
37-43: Lint scripts are redundant and partly legacy.
fix:importsalready runs eslint --fix, then callslint:fixwhich runs eslint --fix again.- With flat config,
--extis unnecessary when a directory is passed.Suggested simplification:
- "fix:imports": "eslint --fix \"src/**/*.{js,jsx,ts,tsx}\" && npm run lint:fix", + "fix:imports": "eslint --fix src", - "lint:js": "npx eslint -c eslint.config.js --ext .js src", - "lint:ts": "npx eslint -c eslint.config.js --ext .ts src", + "lint:js": "eslint -c eslint.config.js \"src/**/*.js\"", + "lint:ts": "eslint -c eslint.config.js \"src/**/*.ts\"", - "lint:fix": "npx eslint src --fix", + "lint:fix": "eslint src --fix",
96-104: Prettier deps are unused per CI — remove or wire them in.Pipeline flags
eslint-config-prettier,eslint-plugin-prettier, andprettieras unused. Either integrate them in eslint.config.js or drop them to reduce install weight.Remove option:
- "eslint-config-prettier": "^10.0.0", - "eslint-plugin-prettier": "^5.0.0", - "prettier": "^3.0.0",
85-104: Remove redundanttypescript-eslintmeta package and align scoped package versions
- Remove the line
"typescript-eslint": "^8.43.0"from package.json (currently at line 108).- Update
@typescript-eslint/parserand@typescript-eslint/eslint-pluginfrom^8.0.0to^8.43.0so all TS-ESLint packages share the same minor/patch.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
.eslintrc.cjs(0 hunks)eslint.config.js(1 hunks)package.json(3 hunks)scripts/create-wrappers.js(1 hunks)tsconfig.cjs.json(1 hunks)tsconfig.esm.json(1 hunks)
💤 Files with no reviewable changes (1)
- .eslintrc.cjs
✅ Files skipped from review due to trivial changes (1)
- tsconfig.esm.json
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
PR: venomlib/venom#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-08T17:49:03.312Z
Learning: Applies to src/lib/wapi/**/*.js : WAPI layer code is built with webpack and injected into the Puppeteer browser context
Learnt from: CR
PR: venomlib/venom#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-08T17:49:03.312Z
Learning: Applies to tsconfig.json : TypeScript must target ESNext with CommonJS modules, output to ./dist, and generate declaration files and source maps
Learnt from: CR
PR: venomlib/venom#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-08T17:49:03.312Z
Learning: Applies to src/lib/wapi/functions/**/*.js : WAPI functions in src/lib/wapi/functions are JavaScript files injected into the browser; after changing them, run `npm run build:wapi` to rebuild
📚 Learning: 2025-09-08T17:49:03.312Z
Learnt from: CR
PR: venomlib/venom#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-08T17:49:03.312Z
Learning: Applies to tsconfig.json : TypeScript must target ESNext with CommonJS modules, output to ./dist, and generate declaration files and source maps
Applied to files:
tsconfig.cjs.jsonscripts/create-wrappers.jseslint.config.js
📚 Learning: 2025-09-08T17:49:03.312Z
Learnt from: CR
PR: venomlib/venom#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-08T17:49:03.312Z
Learning: Run ESLint for both TypeScript and JavaScript code and fix issues (`npm run lint`, `lint:fix`, `lint:ts`, `lint:js`)
Applied to files:
package.json
📚 Learning: 2025-09-08T17:49:03.312Z
Learnt from: CR
PR: venomlib/venom#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-08T17:49:03.312Z
Learning: Applies to src/lib/wapi/**/*.js : WAPI layer code is built with webpack and injected into the Puppeteer browser context
Applied to files:
eslint.config.js
🧬 Code graph analysis (2)
scripts/create-wrappers.js (1)
eslint.config.js (1)
__dirname(11-11)
eslint.config.js (3)
src/lib/counter/gulpfile.mjs (2)
__filename(6-6)__dirname(7-7)src/lib/middleware/webpack.config.mjs (2)
__filename(5-5)__dirname(6-6)src/lib/wapi/webpack.config.mjs (2)
__filename(6-6)__dirname(7-7)
🪛 GitHub Actions: Build
package.json
[warning] 97-97: Unused devDependency: eslint-config-prettier.
[warning] 98-98: Unused devDependency: eslint-plugin-prettier.
[warning] 103-103: Unused devDependency: prettier.
Fixes # .
Changes proposed in this pull request
To test (it takes a while):
npm install github:<username>/venom#<branch>Summary by CodeRabbit
New Features
Bug Fixes
Chores
Tests