Compare commits

..
16 Commits
Author SHA1 Message Date
devlikepro 78186c2bfd up: GOWS v1.0.49 2026-10-02 13:08:15 +07:00
devlikepro ec2d8d9ddd version: 2026.10.1 2026-10-02 13:08:01 +07:00
devlikepro 90ba445a0e up(dashboard): fix refresh chat on new messages
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
2026-10-02 13:07:08 +07:00
devlikepro bf0f49b2e3 up: GOWS - v1.0.48 2026-10-02 13:07:08 +07:00
devlikepro c9ac14e1a4 fix(WEBJS): hide "what's new" modal - use gating days 2026-10-02 13:07:08 +07:00
devlikepro c4f224b7a6 fix(WEBJS): remove hide ux fresh look 2026-10-02 13:07:08 +07:00
devlikepro 0da9ef68cf feat: groups share history mode - fix #2282 2026-10-02 13:07:08 +07:00
Alison White cc650fca3b feat(NOWEB): expose group member-share-history-mode as a settable endpoint (#2283) 2026-10-02 13:07:08 +07:00
devlikepro 9c080611b6 fix(NOWEB): fix delete channel message - fix #2038 2026-10-02 13:07:08 +07:00
devlikepro 235ec01d8b fix(NOWEB): fix update contact - mention #2285 2026-10-02 13:07:08 +07:00
devlikepro ce1e42bb17 up(WEBJS): fix set push name 2026-10-02 13:07:08 +07:00
devlikepro 7440cfc72c up(WEBJS): fix some modules 2026-10-02 13:07:08 +07:00
devlikepro dbb6be3814 up(WEBJS): fix forward message - fix #2278 2026-10-02 13:07:08 +07:00
devlikepro 9035dd95ff up: WPP 2026-10-02 13:07:08 +07:00
devlikepro 9a70c50f62 version: 2026.9.2 2026-10-02 13:07:08 +07:00
Brian Babón 7d7d331195 fix(NOWEB): fix deleting channel message - fix #2038 (#2284) 2026-09-30 15:41:12 +07:00
16 changed files with 261 additions and 56 deletions

No files matched your search

+39
View File
@@ -41,6 +41,7 @@ import {
JoinGroupResponse,
ParticipantsRequest,
SettingsMemberAddMode,
SettingsMemberShareHistoryMode,
SettingsMembershipApproval,
SettingsSecurityChangeInfo,
SubjectRequest,
@@ -346,6 +347,44 @@ export class GroupsController {
return session.getMemberAddMode(id);
}
@Put(':id/settings/security/member-share-history-mode')
@SessionApiParam
@GroupIdApiParam
@CheckPolicies(CanSession(Action.Send, FromParam('session')))
@ApiOperation({
summary:
'Update settings - members can send message history to new members',
description:
'Updates the group settings for whether members can share message history with new members, or only admins can.',
})
@UsePipes(new ValidationPipe({ transform: true, whitelist: true }))
setMemberShareHistoryMode(
@WorkingSessionParam session: WhatsappSession,
@Param('id') id: string,
@Body() request: SettingsMemberShareHistoryMode,
): Promise<boolean> {
return session.setMemberShareHistoryMode(
id,
request.membersCanShareHistory,
);
}
@Get(':id/settings/security/member-share-history-mode')
@SessionApiParam
@GroupIdApiParam
@CheckPolicies(CanSession(Action.Read, FromParam('session')))
@ApiOperation({
summary: 'Get settings - members can send message history to new members',
description:
'The group settings for whether members can share message history with new members, or only admins can.',
})
getMemberShareHistoryMode(
@WorkingSessionParam session: WhatsappSession,
@Param('id') id: string,
): Promise<SettingsMemberShareHistoryMode> {
return session.getMemberShareHistoryMode(id);
}
@Put(':id/settings/security/membership-approval')
@SessionApiParam
@GroupIdApiParam
+42
View File
@@ -9,6 +9,7 @@ import {
GroupIdInput,
GroupJoinInput,
GroupMembershipApprovalInput,
GroupMemberShareHistoryInput,
GroupParticipantsInput,
GroupPictureInput,
GroupsListInput,
@@ -405,6 +406,47 @@ export class GroupTools extends McpController {
});
}
@Tool('groups-get-member-share-history', {
title: 'Get member share history setting',
description:
'Get whether all members or only admins can share message history with new members',
inputSchema: GroupIdInput,
annotations: {
readOnlyHint: true,
destructiveHint: false,
idempotentHint: true,
},
})
async getMemberShareHistory({ session, id }: z.infer<typeof GroupIdInput>) {
return this.textRequest({
method: 'GET',
url: `/api/${session}/groups/${id}/settings/security/member-share-history-mode`,
});
}
@Tool('groups-set-member-share-history', {
title: 'Set member share history setting',
description:
'Allow all members or only admins to share message history with new members',
inputSchema: GroupMemberShareHistoryInput,
annotations: {
readOnlyHint: false,
destructiveHint: false,
idempotentHint: true,
},
})
async setMemberShareHistory({
session,
id,
...body
}: z.infer<typeof GroupMemberShareHistoryInput>) {
return this.textRequest({
method: 'PUT',
url: `/api/${session}/groups/${id}/settings/security/member-share-history-mode`,
data: body,
});
}
@Tool('groups-get-join-requests', {
title: 'Get pending requests to join the group',
description: 'Get pending requests to join the group',
+8
View File
@@ -8,6 +8,7 @@ import {
JoinGroupRequest,
ParticipantsRequest,
SettingsMembershipApproval,
SettingsMemberShareHistoryMode,
SettingsSecurityChangeInfo,
SubjectRequest,
} from '@waha/structures/groups.dto';
@@ -72,3 +73,10 @@ export const GroupMembershipApprovalInput = DtoToZod(
session: SessionField,
id: GroupIdField,
});
export const GroupMemberShareHistoryInput = DtoToZod(
SettingsMemberShareHistoryMode,
).extend({
session: SessionField,
id: GroupIdField,
});
+14
View File
@@ -114,6 +114,7 @@ import {
GroupsListFields,
ParticipantsRequest,
SettingsMemberAddMode,
SettingsMemberShareHistoryMode,
SettingsMembershipApproval,
SettingsSecurityChangeInfo,
} from '../../structures/groups.dto';
@@ -1025,6 +1026,19 @@ export abstract class WhatsappSession {
throw new NotImplementedByEngineError();
}
public getMemberShareHistoryMode(
id: string,
): Promise<SettingsMemberShareHistoryMode> {
throw new NotImplementedByEngineError();
}
public setMemberShareHistoryMode(
id: string,
value: boolean,
): Promise<boolean> {
throw new NotImplementedByEngineError();
}
public getMembershipApprovalMode(
id: string,
): Promise<SettingsMembershipApproval> {
+13
View File
@@ -11726,6 +11726,15 @@ export namespace messages {
responseSerialize: (message: Empty) => Buffer.from(message.serialize()),
responseDeserialize: (bytes: Buffer) => Empty.deserialize(new Uint8Array(bytes))
},
SetGroupMemberShareHistoryMode: {
path: "/messages.MessageService/SetGroupMemberShareHistoryMode",
requestStream: false,
responseStream: false,
requestSerialize: (message: JidBoolRequest) => Buffer.from(message.serialize()),
requestDeserialize: (bytes: Buffer) => JidBoolRequest.deserialize(new Uint8Array(bytes)),
responseSerialize: (message: Empty) => Buffer.from(message.serialize()),
responseDeserialize: (bytes: Buffer) => Empty.deserialize(new Uint8Array(bytes))
},
UpdateGroupParticipants: {
path: "/messages.MessageService/UpdateGroupParticipants",
requestStream: false,
@@ -12144,6 +12153,7 @@ export namespace messages {
abstract SetGroupLocked(call: grpc_1.ServerUnaryCall<JidBoolRequest, Empty>, callback: grpc_1.sendUnaryData<Empty>): void;
abstract SetGroupAnnounce(call: grpc_1.ServerUnaryCall<JidBoolRequest, Empty>, callback: grpc_1.sendUnaryData<Empty>): void;
abstract SetGroupMemberAddMode(call: grpc_1.ServerUnaryCall<JidBoolRequest, Empty>, callback: grpc_1.sendUnaryData<Empty>): void;
abstract SetGroupMemberShareHistoryMode(call: grpc_1.ServerUnaryCall<JidBoolRequest, Empty>, callback: grpc_1.sendUnaryData<Empty>): void;
abstract UpdateGroupParticipants(call: grpc_1.ServerUnaryCall<UpdateParticipantsRequest, JsonList>, callback: grpc_1.sendUnaryData<JsonList>): void;
abstract SetGroupJoinApprovalMode(call: grpc_1.ServerUnaryCall<JidBoolRequest, Empty>, callback: grpc_1.sendUnaryData<Empty>): void;
abstract GetGroupRequestParticipants(call: grpc_1.ServerUnaryCall<JidRequest, JsonList>, callback: grpc_1.sendUnaryData<JsonList>): void;
@@ -12279,6 +12289,9 @@ export namespace messages {
SetGroupMemberAddMode: GrpcUnaryServiceInterface<JidBoolRequest, Empty> = (message: JidBoolRequest, metadata: grpc_1.Metadata | grpc_1.CallOptions | grpc_1.requestCallback<Empty>, options?: grpc_1.CallOptions | grpc_1.requestCallback<Empty>, callback?: grpc_1.requestCallback<Empty>): grpc_1.ClientUnaryCall => {
return super.SetGroupMemberAddMode(message, metadata, options, callback);
};
SetGroupMemberShareHistoryMode: GrpcUnaryServiceInterface<JidBoolRequest, Empty> = (message: JidBoolRequest, metadata: grpc_1.Metadata | grpc_1.CallOptions | grpc_1.requestCallback<Empty>, options?: grpc_1.CallOptions | grpc_1.requestCallback<Empty>, callback?: grpc_1.requestCallback<Empty>): grpc_1.ClientUnaryCall => {
return super.SetGroupMemberShareHistoryMode(message, metadata, options, callback);
};
UpdateGroupParticipants: GrpcUnaryServiceInterface<UpdateParticipantsRequest, JsonList> = (message: UpdateParticipantsRequest, metadata: grpc_1.Metadata | grpc_1.CallOptions | grpc_1.requestCallback<JsonList>, options?: grpc_1.CallOptions | grpc_1.requestCallback<JsonList>, callback?: grpc_1.requestCallback<JsonList>): grpc_1.ClientUnaryCall => {
return super.UpdateGroupParticipants(message, metadata, options, callback);
};
@@ -1073,6 +1073,18 @@ setGroupMemberAddMode: {
responseDeserialize: deserialize_messages_Empty,
},
// who can add members - true - all members, false - admins only
setGroupMemberShareHistoryMode: {
path: '/messages.MessageService/SetGroupMemberShareHistoryMode',
requestStream: false,
responseStream: false,
requestType: gows_pb.JidBoolRequest,
responseType: gows_pb.Empty,
requestSerialize: serialize_messages_JidBoolRequest,
requestDeserialize: deserialize_messages_JidBoolRequest,
responseSerialize: serialize_messages_Empty,
responseDeserialize: deserialize_messages_Empty,
},
// who can share message history with new members - true - all members, false - admins only
updateGroupParticipants: {
path: '/messages.MessageService/UpdateGroupParticipants',
requestStream: false,
@@ -133,6 +133,7 @@ import {
Participant,
ParticipantsRequest,
SettingsMemberAddMode,
SettingsMemberShareHistoryMode,
SettingsMembershipApproval,
SettingsSecurityChangeInfo,
} from '@waha/structures/groups.dto';
@@ -1804,6 +1805,30 @@ export class WhatsappSessionGoWSCore extends WhatsappSession {
return;
}
public async getMemberShareHistoryMode(
id: string,
): Promise<SettingsMemberShareHistoryMode> {
const group = await this.getGroup(id);
return {
membersCanShareHistory:
group.MemberShareHistoryMode === 'all_member_share',
};
}
@Activity()
public async setMemberShareHistoryMode(
id: string,
value: boolean,
): Promise<boolean> {
const req = new messages.JidBoolRequest({
session: this.session,
jid: id,
value: value,
});
await promisify(this.client.SetGroupMemberShareHistoryMode)(req);
return true;
}
public async getMembershipApprovalMode(
id: string,
): Promise<SettingsMembershipApproval> {
+1
View File
@@ -101,6 +101,7 @@ export interface GroupInfoFull {
IsAnnounce: boolean; // specifies whether only admins can send messages in the group
Participants: GOWSGroupParticipant[];
MemberAddMode: string; // all_member_add | admin_add
MemberShareHistoryMode: string; // all_member_share | admin_share
IsJoinApprovalRequired: boolean;
}
+40 -7
View File
@@ -168,6 +168,7 @@ import {
GroupParticipant,
ParticipantsRequest,
SettingsMemberAddMode,
SettingsMemberShareHistoryMode,
SettingsMembershipApproval,
SettingsSecurityChangeInfo,
} from '@waha/structures/groups.dto';
@@ -1148,6 +1149,10 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
const options = {
messageId: this.generateMessageID(),
};
if (isJidNewsletter(jid)) {
// Newsletter deletes reuse the original message ID
options.messageId = key.id;
}
return this.sock.sendMessage(jid, { delete: key }, options);
}
@@ -2012,6 +2017,7 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
@Activity()
public async upsertContact(chatId: string, body: ContactUpdateBody) {
const jid = await this.hooks.wid.chat.promise(chatId, 'upsertContact');
const lid = await this.resolveContactLid(jid);
let fullName = body.firstName;
if (body.lastName) {
fullName = `${body.firstName} ${body.lastName}`;
@@ -2019,16 +2025,26 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
const action = {
fullName: fullName,
firstName: body.firstName,
lidJid: lid ?? undefined,
saveOnPrimaryAddressbook: true,
};
await this.sock.addOrEditContact(jid, action);
const updates: Partial<Contact>[] = [
{
id: jid,
name: fullName,
},
];
this.sock.ev.emit('contacts.update', updates);
const update: Partial<Contact> = {
id: jid,
name: fullName,
};
if (lid) {
update.lid = lid;
}
this.sock.ev.emit('contacts.update', [update]);
}
private async resolveContactLid(pn: string): Promise<string | null> {
const lid = await this.sock.signalRepository.lidMapping.getLIDForPN(pn);
if (!lid) {
return null;
}
return jidNormalizedUser(lid);
}
async getContact(query: ContactQuery) {
@@ -2223,6 +2239,23 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
return await this.sock.groupMemberAddMode(id, mode);
}
public async getMemberShareHistoryMode(
id: string,
): Promise<SettingsMemberShareHistoryMode> {
const group = await this.getGroup(id);
return { membersCanShareHistory: !!group.memberShareHistoryMode };
}
@Activity()
public async setMemberShareHistoryMode(
id: string,
value: boolean,
): Promise<boolean> {
const mode = value ? 'all_member_share' : 'admin_share';
await this.sock.groupMemberShareHistoryMode(id, mode);
return true;
}
public async getMembershipApprovalMode(
id: string,
): Promise<SettingsMembershipApproval> {
+15 -24
View File
@@ -141,26 +141,6 @@ export class WebjsClientCore extends Client {
await this.pupPage.evaluate(LoadPaginator);
}
/**
* @result indicating whether the UX fresh look was successfully hidden.
*/
hideUXFreshLook(): Promise<boolean> {
return this.pupPage.evaluate(() => {
const WAWebUserPrefsUiRefresh = window.require('WAWebUserPrefsUiRefresh');
if (!WAWebUserPrefsUiRefresh) {
return false;
}
if (WAWebUserPrefsUiRefresh.getUiRefreshNuxAcked()) {
return false;
}
WAWebUserPrefsUiRefresh.incrementNuxViewCount();
WAWebUserPrefsUiRefresh.setUiRefreshNuxAcked(true);
const WAWebModalManager = window.require('WAWebModalManager');
WAWebModalManager.ModalManager.close();
return true;
});
}
/**
* @result indicating whether the "What's New" auto-modal was prevented or dismissed.
*/
@@ -179,7 +159,13 @@ export class WebjsClientCore extends Client {
if (!WAWebUserPrefsMeUser.getMaybeMePnUser()) {
return false;
}
const nux = WAWebWhatsNewNux.createWhatsNewNux();
// The app checks the cool-off with AB-prop driven days (15 or 30)
const WAWebWhatsNewGatingUtils = window.require(
'WAWebWhatsNewGatingUtils',
);
const days =
WAWebWhatsNewGatingUtils?.getWhatsNewAutoModalCooldownDays?.();
const nux = WAWebWhatsNewNux.createWhatsNewNux(days);
if (!nux.shouldShow()) {
return false;
}
@@ -338,9 +324,14 @@ export class WebjsClientCore extends Client {
async setPushName(name: string) {
await this.ensureWahaInjected();
await this.pupPage.evaluate(async (pushName) => {
return await window
.require('WAWebSetPushnameConnAction')
.setPushname(pushName);
// @ts-ignore
const WAWebSetPushnameConnAction = await window.WWebJS.requireLazy(
'WAWebSetPushnameConnAction',
{
'WAWebProfileDrawer.react': 'WAWebProfileDrawerLoadableRequireBundle',
},
);
return await WAWebSetPushnameConnAction.setPushname(pushName);
}, name);
if (this.info) {
this.info.pushname = name;
+23 -16
View File
@@ -117,6 +117,7 @@ import {
GroupSortField,
ParticipantsRequest,
SettingsMemberAddMode,
SettingsMemberShareHistoryMode,
SettingsMembershipApproval,
SettingsSecurityChangeInfo,
} from '@waha/structures/groups.dto';
@@ -685,22 +686,6 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
this.logger.info(`Session '${this.name}' is ready!`);
});
//
// Temp fix for hiding "Fresh look" modal
// https://github.com/devlikeapro/waha/issues/987
//
this.whatsapp.on(Events.READY, async () => {
try {
const hidden = await this.whatsapp.hideUXFreshLook();
if (hidden) {
this.logger.info('"Fresh look" modal has been hidden');
}
} catch (err) {
this.logger.warn('Failed to hide "Fresh look" modal');
this.logger.warn(err, err.stack);
}
});
this.whatsapp.on(Events.AUTHENTICATED, async (args) => {
this.status = WAHASessionStatus.WORKING;
this.qr.save('');
@@ -1757,6 +1742,28 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
return groupChat.setAddMembersAdminsOnly(!value);
}
public async getMemberShareHistoryMode(
id: string,
): Promise<SettingsMemberShareHistoryMode> {
const groupChat = (await this.whatsapp.getChatById(id)) as GroupChat;
return {
membersCanShareHistory:
// @ts-ignore
groupChat.groupMetadata.memberShareGroupHistoryMode ===
'all_member_share',
};
}
@Activity()
public async setMemberShareHistoryMode(
id: string,
value: boolean,
): Promise<boolean> {
const groupChat = (await this.whatsapp.getChatById(id)) as GroupChat;
// The library setter is inverted - it takes "adminsOnly"
return groupChat.setShareHistoryAdminsOnly(!value);
}
@Activity()
public async getMembershipApprovalMode(
id: string,
+15
View File
@@ -178,6 +178,7 @@ import {
NormalizeJoinRequestMethod,
ParticipantsRequest,
SettingsMemberAddMode,
SettingsMemberShareHistoryMode,
SettingsMembershipApproval,
SettingsSecurityChangeInfo,
} from '@waha/structures/groups.dto';
@@ -1624,6 +1625,20 @@ export class WhatsappSessionWPPCore extends WhatsappSession {
);
}
public async getMemberShareHistoryMode(
id: string,
): Promise<SettingsMemberShareHistoryMode> {
const groupId = await this.hooks.wid.chat.promise(
id,
'getMemberShareHistoryMode',
);
const group = await this.wpp!.getChatById(groupId);
// Undocumented property - 'all_member_share' or 'admin_share'
// @ts-ignore
const mode = group?.groupMetadata?.memberShareGroupHistoryMode;
return { membersCanShareHistory: mode === 'all_member_share' };
}
public async getMembershipApprovalMode(
id: string,
): Promise<SettingsMembershipApproval> {
+5
View File
@@ -31,6 +31,11 @@ export class SettingsMemberAddMode {
membersCanAddNewMember: boolean = true;
}
export class SettingsMemberShareHistoryMode {
@IsBoolean()
membersCanShareHistory: boolean = true;
}
export class SettingsMembershipApproval {
@IsBoolean()
newMembersApprovalRequired: boolean = false;
+1 -1
View File
@@ -48,7 +48,7 @@ function getPlatform() {
}
export const VERSION: WAHAEnvironment = {
version: '2026.9.1',
version: '2026.10.1',
engine: getEngineName(),
tier: getWAHAVersion(),
browser: getBrowser(),
+2 -2
View File
@@ -2,11 +2,11 @@
"waha": {
"gows": {
"repo": "devlikeapro/gows-plus",
"ref": "v1.0.47"
"ref": "v1.0.49"
},
"dashboard": {
"repo": "devlikeapro/dashboard",
"ref": "5b27f93682c5465b54e6614401adf06e2e1c2c4e"
"ref": "89ba45be91a8493de23aff97b00a2e29df5c9841"
}
}
}
+6 -6
View File
@@ -7,7 +7,7 @@ __metadata:
"@adiwajshing/baileys@github:devlikeapro/Baileys#fork-master-2026-04-28":
version: 7.0.0-rc14
resolution: "@adiwajshing/baileys@https://github.com/devlikeapro/Baileys.git#commit=94d2d1be16f2a316d388a9a273e43ac38a731b5d"
resolution: "@adiwajshing/baileys@https://github.com/devlikeapro/Baileys.git#commit=14ed18cd9fc524309fbecaed4949ea73eaf6761e"
dependencies:
"@cacheable/node-cache": "npm:^1.4.0"
"@hapi/boom": "npm:^9.1.3"
@@ -32,7 +32,7 @@ __metadata:
optional: true
link-preview-js:
optional: true
checksum: 10/6573177fd2fded5a674ae13f397a837ea976a5cde9b3f4021c9700921b986a7c2030ce4cce66008c879ce8e016e94eb67999ae61fa514cae321c32d6c149ff01
checksum: 10/d7c290e64065517c43094f5700daf1230dfa54254aa2965d8efca94bdefbd464904a390f16d695c0305a0e7f408acd9fda566bacb30dc493ff563fcb06892873
languageName: node
linkType: hard
@@ -5101,8 +5101,8 @@ __metadata:
"@wppconnect/wa-js@github:wppconnect-team/wa-js#main":
version: 4.6.0
resolution: "@wppconnect/wa-js@https://github.com/wppconnect-team/wa-js.git#commit=be5a182c3ad7ad152674c0a087088b32b8a289da"
checksum: 10/3d6f887c7ed903a44f7bd17e8adc70f460e8b470e741393795fe4d4c8eb2c2a5ca59eac2623fdcb679149ea27bca1aee976484f2348d5d6852463647be2f5841
resolution: "@wppconnect/wa-js@https://github.com/wppconnect-team/wa-js.git#commit=879d5c2b30e2ef633abeed8cdf7f601823ef0911"
checksum: 10/29d70f88869e536c438803183b56732b45721a6d267d3c67fe90664bba53d737338262c186d7dcb6f850e6caf8d55276f5422987652958fc207f9ac85e4292e0
languageName: node
linkType: hard
@@ -14381,7 +14381,7 @@ __metadata:
"whatsapp-web.js@github:devlikeapro/whatsapp-web.js#fork-main-2026-06-26":
version: 1.34.7
resolution: "whatsapp-web.js@https://github.com/devlikeapro/whatsapp-web.js.git#commit=481db6c749f9ca1a2afad34f520769eace9d8f29"
resolution: "whatsapp-web.js@https://github.com/devlikeapro/whatsapp-web.js.git#commit=7bcd3528538372f9420a63472491513066993090"
dependencies:
archiver: "npm:7.0.1"
fluent-ffmpeg: "npm:2.1.3"
@@ -14398,7 +14398,7 @@ __metadata:
optional: true
unzipper:
optional: true
checksum: 10/917a28428c55aeaf548b726c4afe1a56100cddac5facc4d9306123a06f34f62f36df19094350bd7623668f5065fa891e81c29c8b7615369f773657bb00fa463a
checksum: 10/52b776bd9cde2799fed01ca507f8a43e17cce11254fa58cc3e96fa40f206532311050a38d6c25ee895616c9c39286615e6513c952667b6bd8610d5de03068cdb
languageName: node
linkType: hard