refactor: scwp
This commit is contained in:
parent
37eb88ffba
commit
ada3dfd997
|
@ -1 +0,0 @@
|
|||
// I don't know how to create assets out of thin air with webpack.
|
|
@ -1,67 +0,0 @@
|
|||
const path = require('path');
|
||||
|
||||
const glob = require('glob');
|
||||
const {getOptions} = require('loader-utils');
|
||||
const validateOptions = require('schema-utils');
|
||||
|
||||
const {lookupSourcePaths} = require('../webpack/util');
|
||||
|
||||
const schema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
paths: {
|
||||
items: {
|
||||
type: 'string',
|
||||
},
|
||||
type: 'array',
|
||||
},
|
||||
},
|
||||
required: [
|
||||
'paths',
|
||||
],
|
||||
};
|
||||
|
||||
// Dynamically require all traits.
|
||||
module.exports = function(source) {
|
||||
const options = getOptions(this);
|
||||
// Validate schema.
|
||||
validateOptions(schema, options, '[avocado] Hooks');
|
||||
// Extract options.
|
||||
const {paths, root} = options;
|
||||
// Build registers.
|
||||
const sourcePaths = lookupSourcePaths(paths, '*.hooks.js');
|
||||
const registers = sourcePaths.map((sourcePath) => {
|
||||
const relativePath = path.relative(root, sourcePath);
|
||||
const parts = relativePath.split('/');
|
||||
// Chop off basename.
|
||||
const basename = parts.pop();
|
||||
const moduleName = path.basename(basename, '.js');
|
||||
// Module or local?
|
||||
let hookKey;
|
||||
let importDirectory;
|
||||
if ('node_modules' === parts[0]) {
|
||||
importDirectory = parts.slice(1).join('/');
|
||||
hookKey = `${importDirectory}/${moduleName}`;
|
||||
}
|
||||
else {
|
||||
importDirectory = `${root}/${parts.join('/')}`;
|
||||
hookKey = `./${parts.join('/')}/${moduleName}`;
|
||||
}
|
||||
// Register hooks.
|
||||
const importPath = `${importDirectory}/${moduleName}`;
|
||||
return [
|
||||
`registerHooks('${hookKey}', require('${importPath}'));`,
|
||||
].join('\n');
|
||||
});
|
||||
// Shortcut.
|
||||
if (0 === registers.length) {
|
||||
return '';
|
||||
}
|
||||
// Import trait registry first.
|
||||
const output = [
|
||||
`import {registerHooks} from '@avocado/core/hook/registry'`,
|
||||
'',
|
||||
...registers
|
||||
].join('\n');
|
||||
return output;
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
import {fromObject} from '../array';
|
||||
|
||||
const impl = {};
|
||||
export function registerHooks(name, implementations) {
|
||||
for (const hook in implementations) {
|
||||
if (!impl[hook]) {
|
||||
impl[hook] = {};
|
||||
}
|
||||
impl[hook][name] = implementations[hook];
|
||||
}
|
||||
}
|
||||
|
||||
export function invoke(hook, ...args) {
|
||||
const hookImpl = impl[hook];
|
||||
if (!hookImpl) {
|
||||
return {};
|
||||
}
|
||||
const result = {};
|
||||
for (const name in hookImpl) {
|
||||
result[name] = hookImpl[name](...args);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function invokeFlat(hook, ...args) {
|
||||
return fromObject(invoke(hook, ...args));
|
||||
}
|
|
@ -8,7 +8,6 @@ export {
|
|||
export {EventEmitterMixin as EventEmitter} from './event-emitter';
|
||||
export {inflate, deflate} from './flate';
|
||||
export {compose, fastApply} from './function';
|
||||
export {invoke as invokeHook, invokeFlat as invokeHookFlat} from './hook/registry';
|
||||
export {iterateForEach} from './iterator';
|
||||
export {merge} from './merge';
|
||||
export {
|
||||
|
|
|
@ -1,92 +0,0 @@
|
|||
const path = require('path');
|
||||
|
||||
const glob = require('glob');
|
||||
const {getOptions} = require('loader-utils');
|
||||
const validateOptions = require('schema-utils');
|
||||
|
||||
const {lookupSourcePaths} = require('./util');
|
||||
|
||||
const schema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
paths: {
|
||||
items: {
|
||||
type: 'string',
|
||||
},
|
||||
type: 'array',
|
||||
},
|
||||
registrar: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
function: {
|
||||
type: 'string',
|
||||
},
|
||||
module: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
required: [
|
||||
'function',
|
||||
'module',
|
||||
],
|
||||
},
|
||||
type: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
required: [
|
||||
'registrar',
|
||||
'type',
|
||||
],
|
||||
};
|
||||
|
||||
// Dynamically require all traits.
|
||||
module.exports = function(source) {
|
||||
const options = getOptions(this);
|
||||
// Validate schema.
|
||||
validateOptions(schema, options, '[avocado] Autotomatic registration');
|
||||
// Extract options.
|
||||
const {classTransformer: transformer, paths, registrar, root, type} = options;
|
||||
// Search avocado.
|
||||
paths.push(path.resolve(
|
||||
__dirname, 'node_modules', '@avocado',
|
||||
));
|
||||
// Get all trait source paths.
|
||||
const sourcePaths = lookupSourcePaths(paths, `*.${type}.js`);
|
||||
// Build import definitions.
|
||||
const importDefinitions = sourcePaths.map((sourcePath) => {
|
||||
const relativePath = path.relative(root, sourcePath);
|
||||
const basename = path.basename(relativePath, `.${type}.js`);
|
||||
const parts = relativePath.split('/');
|
||||
// Chop off basename.
|
||||
parts.pop();
|
||||
// Module or local?
|
||||
let importDirectory;
|
||||
if ('node_modules' === parts[0]) {
|
||||
importDirectory = `${parts.slice(1).join('/')}`;
|
||||
}
|
||||
else {
|
||||
importDirectory = `${root}/${parts.join('/')}`
|
||||
}
|
||||
const importPath = `${importDirectory}/${basename}.${type}`;
|
||||
// Extract class name.
|
||||
const baseparts = basename.split('-');
|
||||
const className = baseparts.reduce((className, part) => {
|
||||
const firstLetter = part.charAt(0).toUpperCase();
|
||||
const rest = part.substr(1).toLowerCase();
|
||||
return className + firstLetter + rest;
|
||||
}, '');
|
||||
const transformed = transformer ? transformer(className) : className;
|
||||
// Import and register.
|
||||
return [
|
||||
`${registrar.function}(require('${importPath}').${transformed});`,
|
||||
].join('\n');
|
||||
});
|
||||
// Import trait registry first.
|
||||
const output = [
|
||||
`import {${registrar.function}} from '${registrar.module}'`,
|
||||
'',
|
||||
...importDefinitions
|
||||
].join('\n');
|
||||
return output;
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
const path = require('path');
|
||||
|
||||
const {getOptions} = require('loader-utils');
|
||||
const validateOptions = require('schema-utils');
|
||||
|
||||
const {lookupSourcePaths} = require('../webpack/util');
|
||||
|
||||
const schema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
entries: {
|
||||
items: {
|
||||
type: 'string',
|
||||
},
|
||||
type: 'array',
|
||||
},
|
||||
},
|
||||
required: [
|
||||
'entries',
|
||||
],
|
||||
};
|
||||
|
||||
// Dynamically require all traits.
|
||||
module.exports = function(source) {
|
||||
const options = getOptions(this);
|
||||
validateOptions(schema, options, 'Avocado core');
|
||||
const {entries} = options;
|
||||
return entries.reduce((r, entry) => {
|
||||
return r + `import '${entry}';`;
|
||||
}, '');
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
const path = require('path');
|
||||
|
||||
const {lookupSourcePaths} = require('./util');
|
||||
|
||||
exports.AvocadoPlugin = class AvocadoPlugin {
|
||||
|
||||
constructor(root, side) {
|
||||
this.root = root;
|
||||
this.side = side;
|
||||
}
|
||||
|
||||
apply(compiler) {
|
||||
const {options} = compiler;
|
||||
const {module} = options;
|
||||
const entries = [
|
||||
'@babel/polyfill',
|
||||
];
|
||||
const paths = [
|
||||
path.resolve(this.root, 'common'),
|
||||
path.resolve(this.root, this.side),
|
||||
];
|
||||
const sourcePaths = lookupSourcePaths(paths, '*.avopack.js');
|
||||
sourcePaths.forEach((sourcePath) => {
|
||||
require(`${this.root}/${sourcePath}`)({
|
||||
compiler,
|
||||
entries,
|
||||
options,
|
||||
paths,
|
||||
root: this.root,
|
||||
rules: options.module.rules,
|
||||
side: this.side,
|
||||
});
|
||||
});
|
||||
module.rules.push({
|
||||
test: new RegExp('@avocado/packages/core/webpack/entry.js$'),
|
||||
use: {
|
||||
loader: '@avocado/core/webpack/loader',
|
||||
options: {
|
||||
entries,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
const path = require('path');
|
||||
|
||||
const glob = require('glob');
|
||||
|
||||
exports.lookupSourcePaths = function(paths, pattern) {
|
||||
// Include avocado.
|
||||
const avocadoPath = './node_modules/@avocado';
|
||||
paths.push(avocadoPath);
|
||||
// Get source paths.
|
||||
const sourcePaths = [];
|
||||
paths.forEach((path) => {
|
||||
const files = glob.sync(`${path}/**/${pattern}`, {
|
||||
follow: true,
|
||||
});
|
||||
sourcePaths.push(...files);
|
||||
});
|
||||
return sourcePaths;
|
||||
}
|
|
@ -11,7 +11,7 @@ import {
|
|||
import {SynchronizedMixin} from '@avocado/net';
|
||||
import {Resource} from '@avocado/resource';
|
||||
|
||||
import {hasTrait, lookupTrait} from './trait/registry';
|
||||
import {hasTrait, lookupTrait} from './trait/registrar';
|
||||
import EntityUpdateTraitPacket from './packets/entity-update-trait.packet';
|
||||
|
||||
const debug = D('@avocado:entity:traits');
|
||||
|
|
|
@ -6,8 +6,12 @@ export {EntityList, EntityListView} from './list';
|
|||
|
||||
export {
|
||||
hasTrait,
|
||||
idFrom as idFromTrait,
|
||||
lookupTrait,
|
||||
registerTrait,
|
||||
} from './trait/registry';
|
||||
} from './trait/registrar';
|
||||
|
||||
export {
|
||||
all as allTraits,
|
||||
} from './trait/traits.scwp';
|
||||
|
||||
export {StateProperty, Trait} from './trait';
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import {BundlePacket, SynchronizedUpdatePacket} from '@avocado/net';
|
||||
|
||||
import {idFromTrait, lookupTrait, traitFromId} from '../trait/registry';
|
||||
import {fromId} from '../trait/traits.scwp';
|
||||
import {idFrom, lookupTrait} from '../trait/registrar';
|
||||
|
||||
export default class EntityUpdateTraitPacket extends SynchronizedUpdatePacket {
|
||||
|
||||
|
@ -8,7 +9,7 @@ export default class EntityUpdateTraitPacket extends SynchronizedUpdatePacket {
|
|||
const data = packet.data[1];
|
||||
for (let i = 0; i < data.traits.length; i++) {
|
||||
const Trait = lookupTrait(data.traits[i].type);
|
||||
data.traits[i].type = idFromTrait(Trait);
|
||||
data.traits[i].type = idFrom(Trait);
|
||||
data.traits[i].packets = BundlePacket.packPacket(
|
||||
new BundlePacket(data.traits[i].packets)
|
||||
);
|
||||
|
@ -30,7 +31,7 @@ export default class EntityUpdateTraitPacket extends SynchronizedUpdatePacket {
|
|||
static unpack(packet) {
|
||||
const data = super.unpack(packet);
|
||||
for (let i = 0; i < data.traits.length; i++) {
|
||||
const Trait = traitFromId(data.traits[i].type);
|
||||
const {default: Trait} = fromId(data.traits[i].type);
|
||||
data.traits[i].type = Trait.type();
|
||||
data.traits[i].packets = BundlePacket.unpack(data.traits[i].packets);
|
||||
}
|
||||
|
|
37
packages/entity/trait/registrar.js
Normal file
37
packages/entity/trait/registrar.js
Normal file
|
@ -0,0 +1,37 @@
|
|||
const {all, idFrom: idFromRaw} = require('./traits.scwp');
|
||||
|
||||
let hasMapped = false;
|
||||
const traitTo = new Map();
|
||||
const typeTo = new Map();
|
||||
|
||||
function mapTypesToTraits() {
|
||||
const entries = Object.entries(all());
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
const [, M] = entries[i];
|
||||
const {default: Trait} = M;
|
||||
typeTo.set(Trait.type(), Trait);
|
||||
traitTo.set(Trait, M);
|
||||
}
|
||||
}
|
||||
|
||||
export function idFrom(Trait) {
|
||||
return idFromRaw(traitTo.get(Trait));
|
||||
}
|
||||
|
||||
export function hasTrait(type) {
|
||||
if (!hasMapped) {
|
||||
mapTypesToTraits();
|
||||
hasMapped = true;
|
||||
}
|
||||
return typeTo.has(type);
|
||||
}
|
||||
|
||||
export function lookupTrait(type) {
|
||||
if (!hasMapped) {
|
||||
mapTypesToTraits();
|
||||
hasMapped = true;
|
||||
}
|
||||
return typeTo.get(type);
|
||||
}
|
||||
|
||||
module.hot?.accept(['./traits.scwp'], () => hasMapped = false);
|
|
@ -1,30 +0,0 @@
|
|||
let traitId = 0;
|
||||
const idToTraitMap = new Map();
|
||||
const traitToIdMap = new Map();
|
||||
const traitRegistry = new Map();
|
||||
|
||||
export function registerTrait({default: Trait}) {
|
||||
const hadTrait = traitRegistry.has(Trait.type());
|
||||
traitRegistry.set(Trait.type(), Trait);
|
||||
if (!hadTrait) {
|
||||
traitToIdMap.set(Trait.type(), traitId);
|
||||
idToTraitMap.set(traitId, Trait.type());
|
||||
traitId += 1;
|
||||
}
|
||||
}
|
||||
|
||||
export function hasTrait(type) {
|
||||
return traitRegistry.has(type);
|
||||
}
|
||||
|
||||
export function idFromTrait(Trait) {
|
||||
return traitToIdMap.get(Trait.type());
|
||||
}
|
||||
|
||||
export function lookupTrait(type) {
|
||||
return traitRegistry.get(type);
|
||||
}
|
||||
|
||||
export function traitFromId(id) {
|
||||
return lookupTrait(idToTraitMap.get(id));
|
||||
}
|
|
@ -2,7 +2,6 @@ function traits(scwp) {
|
|||
scwp.enterSelf();
|
||||
scwp.loadSelf('scwp/autoreg', {
|
||||
paths: scwp.paths,
|
||||
registrar: './registry:registerTrait',
|
||||
root: scwp.root,
|
||||
type: 'trait',
|
||||
});
|
||||
|
|
|
@ -3,8 +3,6 @@ import io from 'socket.io-client';
|
|||
|
||||
import {compose, EventEmitter} from '@avocado/core';
|
||||
|
||||
import allPackets, idFromPacket from '...packet';
|
||||
|
||||
const debug = D('@avocado:client:socket');
|
||||
|
||||
const decorate = compose(
|
||||
|
@ -40,6 +38,7 @@ export class SocketClient extends decorate(class {}) {
|
|||
}
|
||||
|
||||
connect(address, options) {
|
||||
const {all, idFrom} = require('../packet/packets.scwp');
|
||||
this.worker.postMessage({
|
||||
type: 'connect',
|
||||
payload: {
|
||||
|
@ -47,8 +46,11 @@ export class SocketClient extends decorate(class {}) {
|
|||
options,
|
||||
},
|
||||
});
|
||||
for (const Packet of allPackets()) {
|
||||
const id = idFromPacket(Packet);
|
||||
const entries = Object.entries(all());
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
const [, M] = entries[i];
|
||||
const {default: Packet} = M;
|
||||
const id = idFrom(M);
|
||||
this.on(`${id}`, (data) => {
|
||||
this.emit('packet', new Packet(data));
|
||||
});
|
||||
|
@ -85,7 +87,8 @@ export class SocketClient extends decorate(class {}) {
|
|||
}
|
||||
|
||||
send(packet) {
|
||||
const id = idFromPacket(packet.constructor);
|
||||
const {idFrom} = require('../packet/registrar');
|
||||
const id = idFrom(packet.constructor);
|
||||
this.worker.postMessage({
|
||||
type: 'emit',
|
||||
payload: [id, packet.data],
|
||||
|
|
|
@ -3,7 +3,7 @@ import io from 'socket.io-client';
|
|||
|
||||
import {compose, EventEmitter} from '@avocado/core';
|
||||
|
||||
import {SocketIoParser, allPackets, idFromPacket} from '../packet';
|
||||
import {SocketIoParser} from '../packet/socket.io-parser';
|
||||
|
||||
const debug = D('@avocado/net:socket');
|
||||
|
||||
|
@ -55,8 +55,12 @@ export class SocketClient extends decorate(class {}) {
|
|||
debug('disconnect');
|
||||
this.tryReconnect();
|
||||
});
|
||||
for (const Packet of allPackets()) {
|
||||
const id = idFromPacket(Packet);
|
||||
const {all, idFrom} = require('../packet/packets.scwp');
|
||||
const entries = Object.entries(all());
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
const [, M] = entries[i];
|
||||
const {default: Packet} = M;
|
||||
const id = idFrom(M);
|
||||
this.socket.on(id, (data) => {
|
||||
const packet = new Packet(data);
|
||||
debug('recieved packet %o', packet);
|
||||
|
@ -75,7 +79,8 @@ export class SocketClient extends decorate(class {}) {
|
|||
|
||||
send(packet) {
|
||||
debug('sending packet %o', packet);
|
||||
const id = idFromPacket(packet.constructor);
|
||||
const {idFrom} = require('../packet/registrar');
|
||||
const id = idFrom(packet.constructor);
|
||||
this.socket.binary(true).emit(id, packet.data);
|
||||
}
|
||||
|
||||
|
@ -86,7 +91,8 @@ export class SocketClient extends decorate(class {}) {
|
|||
to(channel) {
|
||||
return {
|
||||
send: (packet) => {
|
||||
const id = idFromPacket(packet.constructor);
|
||||
const {idFrom} = require('../packet/registrar');
|
||||
const id = idFrom(packet.constructor);
|
||||
this.socket.binary(true).to(channel).emit(id, packet.data);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
export {
|
||||
allPackets,
|
||||
BundlePacket,
|
||||
idFromPacket,
|
||||
Packet,
|
||||
packetFromId,
|
||||
registerPacket,
|
||||
SocketIoParser,
|
||||
} from './packet';
|
||||
|
||||
|
@ -12,7 +8,6 @@ export {
|
|||
allSynchronizeds,
|
||||
ClientSynchronizer,
|
||||
idFromSynchronized,
|
||||
registerSynchronized,
|
||||
ServerSynchronizer,
|
||||
SynchronizedMixin,
|
||||
SynchronizedPacket,
|
||||
|
@ -21,3 +16,12 @@ export {
|
|||
SynchronizedUpdatePacket,
|
||||
synchronizedFromId,
|
||||
} from './s13n';
|
||||
|
||||
export {
|
||||
all as allPackets,
|
||||
fromId as packetFromId,
|
||||
} from './packet/packets.scwp';
|
||||
|
||||
export {
|
||||
idFrom as idFromPacket,
|
||||
} from './packet/registrar';
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import {Packet} from './packet';
|
||||
import {idFromPacket, packetFromId} from './registry';
|
||||
|
||||
export default class BundlePacket extends Packet {
|
||||
|
||||
static pack(packet) {
|
||||
const packets = packet.data[1];
|
||||
const {idFrom} = require('./registrar');
|
||||
// Pack up all the packets.
|
||||
const packedPackets = new Array(packets.length);
|
||||
for (let i = 0; i < packets.length; i++) {
|
||||
const packet = packets[i];
|
||||
const Packet_ = packet.constructor;
|
||||
const id = idFromPacket(Packet_);
|
||||
const id = idFrom(Packet_);
|
||||
packedPackets[i] = Packet_.pack({
|
||||
data: [id, packet.data],
|
||||
});
|
||||
|
@ -45,6 +45,7 @@ export default class BundlePacket extends Packet {
|
|||
|
||||
static unpack(packet) {
|
||||
const data = super.unpack(packet);
|
||||
const {fromId} = require('./packets.scwp');
|
||||
const packets = [];
|
||||
let caret = 0;
|
||||
while (caret < data.length) {
|
||||
|
@ -59,7 +60,7 @@ export default class BundlePacket extends Packet {
|
|||
}
|
||||
// Lookup packet.
|
||||
const packetId = packedPacket.readUInt8(0);
|
||||
const Packet = packetFromId(packetId);
|
||||
const {default: Packet} = fromId(packetId);
|
||||
// Unpack and instantiate the packet.
|
||||
const unpacked = Packet.unpack(packedPacket);
|
||||
packets.push(new Packet(unpacked));
|
||||
|
|
|
@ -1,13 +1,6 @@
|
|||
export {default as BundlePacket} from './bundle.packet';
|
||||
export {Packet} from './packet';
|
||||
|
||||
export {
|
||||
allPackets,
|
||||
idFromPacket,
|
||||
packetFromId,
|
||||
registerPacket,
|
||||
} from './registry';
|
||||
|
||||
// export * as SocketIoParser from './socket.io-parser';
|
||||
import * as SocketIoParser from './socket.io-parser';
|
||||
export {SocketIoParser};
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import {idFromPacket} from './registry';
|
||||
import schemapack from 'schemapack';
|
||||
|
||||
export class Packet {
|
||||
|
@ -29,7 +28,8 @@ export class Packet {
|
|||
}
|
||||
|
||||
static packPacket(packet) {
|
||||
const id = idFromPacket(packet.constructor);
|
||||
const {idFrom} = require('./registrar');
|
||||
const id = idFrom(packet.constructor);
|
||||
return packet.constructor.pack({
|
||||
data: [id, packet.data],
|
||||
});
|
||||
|
|
|
@ -2,7 +2,6 @@ module.exports = (scwp) => {
|
|||
scwp.enterSelf();
|
||||
scwp.loadSelf('scwp/autoreg', {
|
||||
paths: scwp.paths,
|
||||
registrar: './registry:registerPacket',
|
||||
root: scwp.root,
|
||||
type: 'packet',
|
||||
});
|
||||
|
|
23
packages/net/packet/registrar.js
Normal file
23
packages/net/packet/registrar.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
const {all, idFrom: idFromRaw} = require('./packets.scwp');
|
||||
|
||||
let hasMapped = false;
|
||||
const packetTo = new Map();
|
||||
|
||||
function mapPacketsToMs() {
|
||||
const entries = Object.entries(all());
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
const [, M] = entries[i];
|
||||
const {default: Packet} = M;
|
||||
packetTo.set(Packet, M);
|
||||
}
|
||||
}
|
||||
|
||||
export function idFrom(Packet) {
|
||||
if (!hasMapped) {
|
||||
mapPacketsToMs();
|
||||
hasMapped = true;
|
||||
}
|
||||
return idFromRaw(packetTo.get(Packet));
|
||||
}
|
||||
|
||||
module.hot?.accept(['./packets.scwp'], () => hasMapped = false);
|
|
@ -1,20 +0,0 @@
|
|||
let eventId = 0;
|
||||
const idToPacketMap = new Map();
|
||||
const keytoIdMap = new Map();
|
||||
const packetToIdMap = new Map();
|
||||
export function allPackets() {
|
||||
return Array.from(idToPacketMap.values());
|
||||
}
|
||||
export function idFromPacket(Packet) {
|
||||
return packetToIdMap.get(Packet);
|
||||
}
|
||||
export function packetFromId(id) {
|
||||
return idToPacketMap.get(id);
|
||||
}
|
||||
export function registerPacket({default: Packet}, key) {
|
||||
const id = keytoIdMap.has(key) ? keytoIdMap.get(key) : eventId++;
|
||||
idToPacketMap.set(id, Packet);
|
||||
keytoIdMap.set(key, id);
|
||||
packetToIdMap.set(Packet, id);
|
||||
return id;
|
||||
}
|
|
@ -1,7 +1,5 @@
|
|||
import {compose, deflate, EventEmitter, inflate} from '@avocado/core';
|
||||
|
||||
import {packetFromId} from './registry';
|
||||
|
||||
/**
|
||||
* Packet types (see https://github.com/socketio/socket.io-protocol)
|
||||
*/
|
||||
|
@ -24,8 +22,9 @@ class Encoder {
|
|||
}
|
||||
|
||||
pack(packet) {
|
||||
const {fromId} = require('./packets.scwp');
|
||||
const packetId = packet.data[0];
|
||||
const Packet = packetFromId(packetId);
|
||||
const {default: Packet} = fromId(packetId);
|
||||
return deflate(Packet.pack(packet));
|
||||
}
|
||||
|
||||
|
@ -49,10 +48,11 @@ class Decoder extends decorateDecoder(class {}) {
|
|||
destroy() {}
|
||||
|
||||
parseBinary(packet) {
|
||||
const {fromId} = require('./packets.scwp');
|
||||
packet = inflate(Buffer.from(packet));
|
||||
const view = new Uint8Array(packet);
|
||||
const packetId = view[0];
|
||||
const Packet = packetFromId(packetId);
|
||||
const {default: Packet} = fromId(packetId);
|
||||
const data = Packet.unpack(packet);
|
||||
this.emit('decoded', {
|
||||
type: TYPES.EVENT,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import {idFromSynchronized, synchronizedFromId} from './registry';
|
||||
import {fromId} from './s13n.scwp';
|
||||
import {idFrom} from './registrar';
|
||||
|
||||
import SynchronizedCreatePacket from './synchronized-create.packet';
|
||||
import SynchronizedDestroyPacket from './synchronized-destroy.packet';
|
||||
|
@ -14,7 +15,7 @@ export class ClientSynchronizer {
|
|||
if ((packet instanceof SynchronizedCreatePacket)) {
|
||||
const json = packet.data.spec;
|
||||
const {id, type} = packet.data.synchronized;
|
||||
const Synchronized = synchronizedFromId(type);
|
||||
const {default: Synchronized} = fromId(type);
|
||||
if (!(type in this._synchronized)) {
|
||||
this._synchronized[type] = {};
|
||||
}
|
||||
|
@ -41,7 +42,7 @@ export class ClientSynchronizer {
|
|||
}
|
||||
|
||||
addSynchronized(synchronized) {
|
||||
const type = idFromSynchronized(synchronized.constructor);
|
||||
const type = idFrom(synchronized.constructor);
|
||||
if (!(type in this._synchronized)) {
|
||||
this._synchronized[type] = new Map();
|
||||
}
|
||||
|
|
|
@ -1,10 +1,3 @@
|
|||
export {
|
||||
allSynchronizeds,
|
||||
idFromSynchronized,
|
||||
synchronizedFromId,
|
||||
registerSynchronized,
|
||||
} from './registry';
|
||||
|
||||
export {ClientSynchronizer} from './client';
|
||||
export {ServerSynchronizer} from './server';
|
||||
|
||||
|
@ -14,3 +7,12 @@ export {default as SynchronizedPacket} from './synchronized.packet';
|
|||
export {default as SynchronizedCreatePacket} from './synchronized-create.packet';
|
||||
export {default as SynchronizedDestroyPacket} from './synchronized-destroy.packet';
|
||||
export {default as SynchronizedUpdatePacket} from './synchronized-update.packet';
|
||||
|
||||
export {
|
||||
all as allSynchronizeds,
|
||||
fromId as synchronizedFromId,
|
||||
} from './s13n.scwp';
|
||||
|
||||
export {
|
||||
idFrom as idFromSynchronized,
|
||||
} from './registrar';
|
||||
|
|
23
packages/net/s13n/registrar.js
Normal file
23
packages/net/s13n/registrar.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
const {all, idFrom: idFromRaw} = require('./s13n.scwp');
|
||||
|
||||
let hasMapped = false;
|
||||
const synchronizedTo = new Map();
|
||||
|
||||
function mapSynchronizedsToMs() {
|
||||
const entries = Object.entries(all());
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
const [, M] = entries[i];
|
||||
const {default: Synchronized} = M;
|
||||
synchronizedTo.set(Synchronized, M);
|
||||
}
|
||||
}
|
||||
|
||||
export function idFrom(Synchronized) {
|
||||
if (!hasMapped) {
|
||||
mapSynchronizedsToMs();
|
||||
hasMapped = true;
|
||||
}
|
||||
return idFromRaw(synchronizedTo.get(Synchronized));
|
||||
}
|
||||
|
||||
module.hot?.accept(['./s13n.scwp'], () => hasMapped = false);
|
|
@ -1,21 +0,0 @@
|
|||
let synchronizedId = 0;
|
||||
const synchronizedToIdMap = new Map();
|
||||
const idToSynchronizedMap = new Map();
|
||||
export function allSynchronizeds() {
|
||||
return Array.from(idToSynchronizedMap.values());
|
||||
}
|
||||
export function idFromSynchronized(Synchronized) {
|
||||
return synchronizedToIdMap.get(Synchronized);
|
||||
}
|
||||
export function synchronizedFromId(id) {
|
||||
return idToSynchronizedMap.get(id);
|
||||
}
|
||||
export function registerSynchronized({default: Synchronized}) {
|
||||
if (synchronizedToIdMap.has(Synchronized)) {
|
||||
return;
|
||||
}
|
||||
const id = synchronizedId++;
|
||||
synchronizedToIdMap.set(Synchronized, id);
|
||||
idToSynchronizedMap.set(id, Synchronized);
|
||||
return id;
|
||||
}
|
|
@ -4,7 +4,6 @@ function s13n(scwp) {
|
|||
scwp.enterSelf();
|
||||
scwp.loadSelf('scwp/autoreg', {
|
||||
paths: scwp.paths,
|
||||
registrar: './registry:registerSynchronized',
|
||||
root: scwp.root,
|
||||
type: 'synchronized',
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {idFromSynchronized} from './registry';
|
||||
import {idFrom} from './registrar';
|
||||
|
||||
import SynchronizedCreatePacket from './synchronized-create.packet';
|
||||
import SynchronizedDestroyPacket from './synchronized-destroy.packet';
|
||||
|
@ -19,7 +19,7 @@ export class ServerSynchronizer {
|
|||
else {
|
||||
this._added.push(synchronized);
|
||||
}
|
||||
const type = idFromSynchronized(synchronized.constructor);
|
||||
const type = idFrom(synchronized.constructor);
|
||||
if (!(type in this._synchronized)) {
|
||||
this._synchronized[type] = new Map();
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ export class ServerSynchronizer {
|
|||
}
|
||||
const index = this._synchronizedFlat.indexOf(synchronized);
|
||||
this._synchronizedFlat.splice(index, 1);
|
||||
const type = idFromSynchronized(synchronized.constructor);
|
||||
const type = idFrom(synchronized.constructor);
|
||||
const synchronizationId = synchronized.synchronizationId();
|
||||
this._synchronized[type].delete(synchronizationId);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {idFromSynchronized} from './registry';
|
||||
import {idFrom} from './registrar';
|
||||
import SynchronizedCreatePacket from './synchronized-create.packet';
|
||||
import SynchronizedDestroyPacket from './synchronized-destroy.packet';
|
||||
|
||||
|
@ -17,7 +17,7 @@ export function SynchronizedMixin(Superclass) {
|
|||
|
||||
createPacket(informed) {
|
||||
const id = this.synchronizationId();
|
||||
const type = idFromSynchronized(this.constructor);
|
||||
const type = idFrom(this.constructor);
|
||||
return new SynchronizedCreatePacket({
|
||||
synchronized: {
|
||||
id,
|
||||
|
@ -31,7 +31,7 @@ export function SynchronizedMixin(Superclass) {
|
|||
|
||||
destroyPacket(informed) {
|
||||
const id = this.synchronizationId();
|
||||
const type = idFromSynchronized(this.constructor);
|
||||
const type = idFrom(this.constructor);
|
||||
return new SynchronizedDestroyPacket({
|
||||
synchronized: {
|
||||
id,
|
||||
|
@ -65,7 +65,7 @@ export function SynchronizedMixin(Superclass) {
|
|||
}
|
||||
// Embed synchronization info.
|
||||
const id = this.synchronizationId();
|
||||
const type = idFromSynchronized(this.constructor);
|
||||
const type = idFrom(this.constructor);
|
||||
for (let i = 0; i < packets.length; i++) {
|
||||
packets[i].data.synchronized = {id, type};
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import SocketIoServer from 'socket.io';
|
|||
|
||||
import {compose, EventEmitter} from '@avocado/core';
|
||||
|
||||
import {SocketIoParser, allPackets, idFromPacket} from '../packet';
|
||||
import * as SocketIoParser from '../packet/socket.io-parser';
|
||||
|
||||
const debug = D('@avocado/net:socket');
|
||||
|
||||
|
@ -46,7 +46,8 @@ export class SocketServer extends decorateServer(class {}) {
|
|||
}
|
||||
|
||||
send(packet, channel = '/') {
|
||||
const id = idFromPacket(packet.constructor);
|
||||
const {idFrom} = require('../packet/registrar');
|
||||
const id = idFrom(packet.constructor);
|
||||
this.io.sockets.to(channel).binary(true).emit(id, packet.data);
|
||||
}
|
||||
|
||||
|
@ -61,8 +62,12 @@ class ServerSocket extends decorateSocket(class {}) {
|
|||
constructor(socket) {
|
||||
super();
|
||||
this.socket = socket;
|
||||
for (const Packet of allPackets()) {
|
||||
const id = idFromPacket(Packet);
|
||||
const {all, idFrom} = require('../packet/packets.scwp');
|
||||
const entries = Object.entries(all());
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
const [, M] = entries[i];
|
||||
const {default: Packet} = M;
|
||||
const id = idFrom(M);
|
||||
this.socket.on(id, (data) => {
|
||||
const packet = new Packet(data);
|
||||
debug('recieved packet %o', packet);
|
||||
|
@ -92,7 +97,8 @@ class ServerSocket extends decorateSocket(class {}) {
|
|||
|
||||
send(packet) {
|
||||
debug('sending packet %o', packet);
|
||||
const id = idFromPacket(packet.constructor);
|
||||
const {idFrom} = require('../packet/registrar');
|
||||
const id = idFrom(packet.constructor);
|
||||
this.socket.binary(true).emit(id, packet.data);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user