mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-09 16:13:31 +01:00
Add webpack building (#907)
* friggin webpack tho
* probably important
* add all the stuff to the package.json
* add minify builds and a nice package.json script to run it all
* clean up
* use uglify harmony branch so we can actually run minify builds that work
* update build system
* make test better
* clean up
* fix issues with compression
*
* c++ requirements in a node lib? whaaaaat?
* fix travis yml?
* put railings on voice connections
* 🖕🏻
* aaaaaa
* handle arraybuffers in the unlikely event one is sent
* support arraybuffers in resolvebuffer
* this needs to be fixed at some point
* this was fixed
* disable filename versioning if env VERSIONED is set to false
* Update ClientDataResolver.js
* Update ClientVoiceManager.js
* Update WebSocketManager.js
* Update ConvertArrayBuffer.js
* Update webpack.html
* enable compression for browser and fix ws error handler
* Update WebSocketManager.js
* everything will be okay gawdl3y
* compression is slower in browser, so rip the last three hours of my life
* Update Constants.js
* Update .gitignore
This commit is contained in:
committed by
Schuyler Cebulskie
parent
b3e795d0b0
commit
2440a4a2c8
2
.gitignore
vendored
2
.gitignore
vendored
@@ -8,6 +8,7 @@ logs/
|
|||||||
|
|
||||||
# Authentication
|
# Authentication
|
||||||
test/auth.json
|
test/auth.json
|
||||||
|
test/auth.js
|
||||||
docs/deploy/deploy_key
|
docs/deploy/deploy_key
|
||||||
docs/deploy/deploy_key.pub
|
docs/deploy/deploy_key.pub
|
||||||
|
|
||||||
@@ -15,3 +16,4 @@ docs/deploy/deploy_key.pub
|
|||||||
.tmp/
|
.tmp/
|
||||||
.vscode/
|
.vscode/
|
||||||
docs/docs.json
|
docs/docs.json
|
||||||
|
webpack/
|
||||||
|
|||||||
@@ -10,4 +10,10 @@ env:
|
|||||||
global:
|
global:
|
||||||
- ENCRYPTION_LABEL: "af862fa96d3e"
|
- ENCRYPTION_LABEL: "af862fa96d3e"
|
||||||
- COMMIT_AUTHOR_EMAIL: "amishshah.2k@gmail.com"
|
- COMMIT_AUTHOR_EMAIL: "amishshah.2k@gmail.com"
|
||||||
|
- CXX=g++-4.9
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
packages:
|
||||||
|
- g++-4.9
|
||||||
|
|||||||
16
package.json
16
package.json
@@ -7,7 +7,8 @@
|
|||||||
"test": "eslint src && node docs/generator test",
|
"test": "eslint src && node docs/generator test",
|
||||||
"docs": "node docs/generator",
|
"docs": "node docs/generator",
|
||||||
"test-docs": "node docs/generator test",
|
"test-docs": "node docs/generator test",
|
||||||
"lint": "eslint src"
|
"lint": "eslint src",
|
||||||
|
"web-dist": "npm install && ./node_modules/parallel-webpack/bin/run.js"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -29,16 +30,23 @@
|
|||||||
"homepage": "https://github.com/hydrabolt/discord.js#readme",
|
"homepage": "https://github.com/hydrabolt/discord.js#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"superagent": "^2.3.0",
|
"superagent": "^2.3.0",
|
||||||
"tweetnacl": "^0.14.0",
|
"tweetnacl": "^0.14.3",
|
||||||
"ws": "^1.1.0"
|
"ws": "^1.1.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"node-opus": "^0.2.0",
|
"node-opus": "^0.2.0",
|
||||||
"opusscript": "^0.0.1"
|
"opusscript": "^0.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"bufferutil": "^1.2.1",
|
||||||
"eslint": "^3.10.0",
|
"eslint": "^3.10.0",
|
||||||
"jsdoc-to-markdown": "^2.0.0"
|
"jsdoc-to-markdown": "^2.0.0",
|
||||||
|
"json-loader": "^0.5.4",
|
||||||
|
"parallel-webpack": "^1.5.0",
|
||||||
|
"uglify-js": "github:mishoo/UglifyJS2#harmony",
|
||||||
|
"utf-8-validate": "^1.2.1",
|
||||||
|
"webpack": "^1.13.3",
|
||||||
|
"zlibjs": "github:imaya/zlib.js"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
|
|||||||
@@ -23,6 +23,12 @@ class Client extends EventEmitter {
|
|||||||
constructor(options = {}) {
|
constructor(options = {}) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the client is in a browser environment
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
this.browser = typeof window !== 'undefined';
|
||||||
|
|
||||||
// Obtain shard details from environment
|
// Obtain shard details from environment
|
||||||
if (!options.shardId && 'SHARD_ID' in process.env) options.shardId = Number(process.env.SHARD_ID);
|
if (!options.shardId && 'SHARD_ID' in process.env) options.shardId = Number(process.env.SHARD_ID);
|
||||||
if (!options.shardCount && 'SHARD_COUNT' in process.env) options.shardCount = Number(process.env.SHARD_COUNT);
|
if (!options.shardCount && 'SHARD_COUNT' in process.env) options.shardCount = Number(process.env.SHARD_COUNT);
|
||||||
|
|||||||
@@ -3,13 +3,14 @@ const fs = require('fs');
|
|||||||
const request = require('superagent');
|
const request = require('superagent');
|
||||||
|
|
||||||
const Constants = require('../util/Constants');
|
const Constants = require('../util/Constants');
|
||||||
const User = require(`../structures/User`);
|
const convertArrayBuffer = require('../util/ConvertArrayBuffer');
|
||||||
const Message = require(`../structures/Message`);
|
const User = require('../structures/User');
|
||||||
const Guild = require(`../structures/Guild`);
|
const Message = require('../structures/Message');
|
||||||
const Channel = require(`../structures/Channel`);
|
const Guild = require('../structures/Guild');
|
||||||
const GuildMember = require(`../structures/GuildMember`);
|
const Channel = require('../structures/Channel');
|
||||||
const Emoji = require(`../structures/Emoji`);
|
const GuildMember = require('../structures/GuildMember');
|
||||||
const ReactionEmoji = require(`../structures/ReactionEmoji`);
|
const Emoji = require('../structures/Emoji');
|
||||||
|
const ReactionEmoji = require('../structures/ReactionEmoji');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The DataResolver identifies different objects and tries to resolve a specific piece of information from them, e.g.
|
* The DataResolver identifies different objects and tries to resolve a specific piece of information from them, e.g.
|
||||||
@@ -240,14 +241,16 @@ class ClientDataResolver {
|
|||||||
*/
|
*/
|
||||||
resolveBuffer(resource) {
|
resolveBuffer(resource) {
|
||||||
if (resource instanceof Buffer) return Promise.resolve(resource);
|
if (resource instanceof Buffer) return Promise.resolve(resource);
|
||||||
|
if (this.client.browser && resource instanceof ArrayBuffer) return Promise.resolve(convertArrayBuffer(resource));
|
||||||
|
|
||||||
if (typeof resource === 'string') {
|
if (typeof resource === 'string') {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (/^https?:\/\//.test(resource)) {
|
if (/^https?:\/\//.test(resource)) {
|
||||||
request.get(resource)
|
const req = request.get(resource).set('Content-Type', 'blob');
|
||||||
.set('Content-Type', 'blob')
|
if (this.client.browser) req.responseType('arraybuffer');
|
||||||
.end((err, res) => {
|
req.end((err, res) => {
|
||||||
if (err) return reject(err);
|
if (err) return reject(err);
|
||||||
|
if (this.client.browser) return resolve(convertArrayBuffer(res.xhr.response));
|
||||||
if (!(res.body instanceof Buffer)) return reject(new TypeError('Body is not a Buffer'));
|
if (!(res.body instanceof Buffer)) return reject(new TypeError('Body is not a Buffer'));
|
||||||
return resolve(res.body);
|
return resolve(res.body);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,14 +3,13 @@ const Collection = require('../../util/Collection');
|
|||||||
const splitMessage = require('../../util/SplitMessage');
|
const splitMessage = require('../../util/SplitMessage');
|
||||||
const parseEmoji = require('../../util/ParseEmoji');
|
const parseEmoji = require('../../util/ParseEmoji');
|
||||||
|
|
||||||
const requireStructure = name => require(`../../structures/${name}`);
|
const User = require('../../structures/User');
|
||||||
const User = requireStructure('User');
|
const GuildMember = require('../../structures/GuildMember');
|
||||||
const GuildMember = requireStructure('GuildMember');
|
const Role = require('../../structures/Role');
|
||||||
const Role = requireStructure('Role');
|
const Invite = require('../../structures/Invite');
|
||||||
const Invite = requireStructure('Invite');
|
const Webhook = require('../../structures/Webhook');
|
||||||
const Webhook = requireStructure('Webhook');
|
const UserProfile = require('../../structures/UserProfile');
|
||||||
const UserProfile = requireStructure('UserProfile');
|
const ClientOAuth2Application = require('../../structures/ClientOAuth2Application');
|
||||||
const ClientOAuth2Application = requireStructure('ClientOAuth2Application');
|
|
||||||
|
|
||||||
class RESTMethods {
|
class RESTMethods {
|
||||||
constructor(restManager) {
|
constructor(restManager) {
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ class ClientVoiceManager {
|
|||||||
*/
|
*/
|
||||||
joinChannel(channel) {
|
joinChannel(channel) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
if (this.client.browser) throw new Error('Voice connections are not available in browsers.');
|
||||||
if (this.pending.get(channel.guild.id)) throw new Error('Already connecting to this guild\'s voice server.');
|
if (this.pending.get(channel.guild.id)) throw new Error('Already connecting to this guild\'s voice server.');
|
||||||
if (!channel.joinable) throw new Error('You do not have permission to join this voice channel.');
|
if (!channel.joinable) throw new Error('You do not have permission to join this voice channel.');
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
const WebSocket = require('ws');
|
const browser = typeof window !== 'undefined';
|
||||||
|
const WebSocket = browser ? window.WebSocket : require('ws'); // eslint-disable-line no-undef
|
||||||
const EventEmitter = require('events').EventEmitter;
|
const EventEmitter = require('events').EventEmitter;
|
||||||
const Constants = require('../../util/Constants');
|
const Constants = require('../../util/Constants');
|
||||||
const zlib = require('zlib');
|
const inflate = browser ? require('zlibjs').inflateSync : require('zlib').inflateSync;
|
||||||
const PacketManager = require('./packets/WebSocketPacketManager');
|
const PacketManager = require('./packets/WebSocketPacketManager');
|
||||||
|
const convertArrayBuffer = require('../../util/ConvertArrayBuffer');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The WebSocket Manager of the Client
|
* The WebSocket Manager of the Client
|
||||||
@@ -78,6 +80,7 @@ class WebSocketManager extends EventEmitter {
|
|||||||
this.normalReady = false;
|
this.normalReady = false;
|
||||||
if (this.status !== Constants.Status.RECONNECTING) this.status = Constants.Status.CONNECTING;
|
if (this.status !== Constants.Status.RECONNECTING) this.status = Constants.Status.CONNECTING;
|
||||||
this.ws = new WebSocket(gateway);
|
this.ws = new WebSocket(gateway);
|
||||||
|
if (browser) this.ws.binaryType = 'arraybuffer';
|
||||||
this.ws.onopen = () => this.eventOpen();
|
this.ws.onopen = () => this.eventOpen();
|
||||||
this.ws.onclose = (d) => this.eventClose(d);
|
this.ws.onclose = (d) => this.eventClose(d);
|
||||||
this.ws.onmessage = (e) => this.eventMessage(e);
|
this.ws.onmessage = (e) => this.eventMessage(e);
|
||||||
@@ -193,11 +196,11 @@ class WebSocketManager extends EventEmitter {
|
|||||||
*/
|
*/
|
||||||
eventClose(event) {
|
eventClose(event) {
|
||||||
this.emit('close', event);
|
this.emit('close', event);
|
||||||
|
this.client.clearInterval(this.client.manager.heartbeatInterval);
|
||||||
/**
|
/**
|
||||||
* Emitted whenever the client websocket is disconnected
|
* Emitted whenever the client websocket is disconnected
|
||||||
* @event Client#disconnect
|
* @event Client#disconnect
|
||||||
*/
|
*/
|
||||||
clearInterval(this.client.manager.heartbeatInterval);
|
|
||||||
if (!this.reconnecting) this.client.emit(Constants.Events.DISCONNECT);
|
if (!this.reconnecting) this.client.emit(Constants.Events.DISCONNECT);
|
||||||
if (event.code === 4004) return;
|
if (event.code === 4004) return;
|
||||||
if (event.code === 4010) return;
|
if (event.code === 4010) return;
|
||||||
@@ -211,10 +214,13 @@ class WebSocketManager extends EventEmitter {
|
|||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
eventMessage(event) {
|
eventMessage(event) {
|
||||||
let packet;
|
let packet = event.data;
|
||||||
try {
|
try {
|
||||||
if (event.binary) event.data = zlib.inflateSync(event.data).toString();
|
if (typeof packet !== 'string') {
|
||||||
packet = JSON.parse(event.data);
|
if (packet instanceof ArrayBuffer) packet = convertArrayBuffer(packet);
|
||||||
|
packet = inflate(packet).toString();
|
||||||
|
}
|
||||||
|
packet = JSON.parse(packet);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return this.eventError(new Error(Constants.Errors.BAD_WS_MESSAGE));
|
return this.eventError(new Error(Constants.Errors.BAD_WS_MESSAGE));
|
||||||
}
|
}
|
||||||
@@ -236,7 +242,7 @@ class WebSocketManager extends EventEmitter {
|
|||||||
* @param {Error} error The encountered error
|
* @param {Error} error The encountered error
|
||||||
*/
|
*/
|
||||||
if (this.client.listenerCount('error') > 0) this.client.emit('error', err);
|
if (this.client.listenerCount('error') > 0) this.client.emit('error', err);
|
||||||
this.tryReconnect();
|
this.ws.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
_emitReady(normal = true) {
|
_emitReady(normal = true) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
const AbstractHandler = require('./AbstractHandler');
|
const AbstractHandler = require('./AbstractHandler');
|
||||||
|
|
||||||
const getStructure = name => require(`../../../../structures/${name}`);
|
const ClientUser = require('../../../../structures/ClientUser');
|
||||||
const ClientUser = getStructure('ClientUser');
|
|
||||||
|
|
||||||
class ReadyHandler extends AbstractHandler {
|
class ReadyHandler extends AbstractHandler {
|
||||||
handle(packet) {
|
handle(packet) {
|
||||||
|
|||||||
@@ -41,3 +41,5 @@ module.exports = {
|
|||||||
|
|
||||||
version: require('../package').version,
|
version: require('../package').version,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (typeof window !== 'undefined') window.Discord = module.exports; // eslint-disable-line no-undef
|
||||||
|
|||||||
@@ -42,11 +42,12 @@ exports.DefaultOptions = {
|
|||||||
* Websocket options. These are left as snake_case to match the API.
|
* Websocket options. These are left as snake_case to match the API.
|
||||||
* @typedef {Object} WebsocketOptions
|
* @typedef {Object} WebsocketOptions
|
||||||
* @property {number} [large_threshold=250] Number of members in a guild to be considered large
|
* @property {number} [large_threshold=250] Number of members in a guild to be considered large
|
||||||
* @property {boolean} [compress=true] Whether to compress data sent on the connection
|
* @property {boolean} [compress=true] Whether to compress data sent on the connection.
|
||||||
|
* Defaults to `false` for browsers.
|
||||||
*/
|
*/
|
||||||
ws: {
|
ws: {
|
||||||
large_threshold: 250,
|
large_threshold: 250,
|
||||||
compress: true,
|
compress: typeof window === 'undefined',
|
||||||
properties: {
|
properties: {
|
||||||
$os: process ? process.platform : 'discord.js',
|
$os: process ? process.platform : 'discord.js',
|
||||||
$browser: 'discord.js',
|
$browser: 'discord.js',
|
||||||
|
|||||||
18
src/util/ConvertArrayBuffer.js
Normal file
18
src/util/ConvertArrayBuffer.js
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
function arrayBufferToBuffer(ab) {
|
||||||
|
const buffer = new Buffer(ab.byteLength);
|
||||||
|
const view = new Uint8Array(ab);
|
||||||
|
for (var i = 0; i < buffer.length; ++i) buffer[i] = view[i];
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
function str2ab(str) {
|
||||||
|
const buffer = new ArrayBuffer(str.length * 2);
|
||||||
|
const view = new Uint16Array(buffer);
|
||||||
|
for (var i = 0, strLen = str.length; i < strLen; i++) view[i] = str.charCodeAt(i);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = function convertArrayBuffer(x) {
|
||||||
|
if (typeof x === 'string') x = str2ab(x);
|
||||||
|
return arrayBufferToBuffer(x);
|
||||||
|
};
|
||||||
30
test/webpack.html
Normal file
30
test/webpack.html
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>discord.js Webpack test</title>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script type="text/javascript" src="../webpack/discord.10.0.1.js"></script>
|
||||||
|
<script type="text/javascript" src="auth.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
(() => {
|
||||||
|
const client = window.client = new Discord.Client();
|
||||||
|
|
||||||
|
client.on('ready', () => {
|
||||||
|
console.log('[CLIENT] Ready!');
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('error', console.error);
|
||||||
|
|
||||||
|
client.ws.on('close', (event) => console.log('[CLIENT] Disconnect!', event));
|
||||||
|
|
||||||
|
client.on('message', (message) => {
|
||||||
|
console.log(message.author.username, message.author.id, message.content);
|
||||||
|
});
|
||||||
|
|
||||||
|
client.login(window.token || prompt('token', 'abcdef123456'));
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
43
webpack.config.js
Normal file
43
webpack.config.js
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
ONLY RUN BUILDS WITH `npm run web-dist`!
|
||||||
|
DO NOT USE NORMAL WEBPACK! IT WILL NOT WORK!
|
||||||
|
*/
|
||||||
|
|
||||||
|
const webpack = require('webpack');
|
||||||
|
const createVariants = require('parallel-webpack').createVariants;
|
||||||
|
const version = require('./package.json').version;
|
||||||
|
|
||||||
|
const createConfig = (options) => {
|
||||||
|
const plugins = [
|
||||||
|
new webpack.DefinePlugin({ 'global.GENTLY': false }),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (options.minify) plugins.push(new webpack.optimize.UglifyJsPlugin({ minimize: true }));
|
||||||
|
|
||||||
|
const filename = `./webpack/discord${process.env.VERSIONED === 'false' ? '' : '.' + version}${options.minify ? '.min' : ''}.js`; // eslint-disable-line
|
||||||
|
|
||||||
|
return {
|
||||||
|
entry: './src/index.js',
|
||||||
|
output: {
|
||||||
|
path: __dirname,
|
||||||
|
filename,
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
loaders: [
|
||||||
|
{ test: /\.json$/, loader: 'json-loader' },
|
||||||
|
{ test: /\.md$/, loader: 'ignore-loader' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
node: {
|
||||||
|
fs: 'empty',
|
||||||
|
dns: 'mock',
|
||||||
|
tls: 'mock',
|
||||||
|
child_process: 'empty',
|
||||||
|
dgram: 'empty',
|
||||||
|
__dirname: true,
|
||||||
|
},
|
||||||
|
plugins,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = createVariants({}, { minify: [false, true] }, createConfig);
|
||||||
Reference in New Issue
Block a user