feat: RNG ts 테스트 일치
This commit is contained in:
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"extension": ["ts"],
|
||||||
|
"spec": "hwe/test-ts/**/*.test.ts",
|
||||||
|
"require": [
|
||||||
|
"ts-node/register",
|
||||||
|
"tsconfig-paths/register"
|
||||||
|
],
|
||||||
|
"node-option": [
|
||||||
|
"experimental-specifier-resolution=node",
|
||||||
|
"loader=ts-node/esm"
|
||||||
|
]
|
||||||
|
}
|
||||||
Vendored
+1
-1
@@ -28,5 +28,5 @@
|
|||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
"josa",
|
"josa",
|
||||||
"sammo"
|
"sammo"
|
||||||
],
|
]
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,194 @@
|
|||||||
|
import chai, { assert, expect } from 'chai';
|
||||||
|
import chaiBytes from 'chai-bytes';
|
||||||
|
import { bufferByteSize, LiteHashDRBG } from '../ts/util/LiteHashDRBG';
|
||||||
|
import { RandUtil } from '../ts/util/RandUtil';
|
||||||
|
import { convertBytesLikeToArrayBuffer } from '../ts/util/convertBytesLikeToArrayBuffer';
|
||||||
|
import { convertBytesLikeToUint8Array as toBytes } from '../ts/util/convertBytesLikeToUint8Array';
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
chai.use(chaiBytes);
|
||||||
|
|
||||||
|
type Bytes = ArrayBuffer | DataView | Uint8Array;
|
||||||
|
type MaybeBytes = Bytes | string;
|
||||||
|
|
||||||
|
function fillBlock(body: MaybeBytes, filler: MaybeBytes = '\0', length = bufferByteSize): Uint8Array {
|
||||||
|
const u8Body = toBytes(body);
|
||||||
|
const u8Filler = toBytes(filler, false);
|
||||||
|
|
||||||
|
if (u8Filler.byteLength < 1) {
|
||||||
|
throw new Error('filler must have length');
|
||||||
|
}
|
||||||
|
|
||||||
|
const buffer = new Uint8Array(length);
|
||||||
|
buffer.set(u8Body, 0);
|
||||||
|
let bufferIdx = u8Body.byteLength;
|
||||||
|
|
||||||
|
while (bufferIdx + u8Filler.byteLength < length) {
|
||||||
|
buffer.set(u8Filler, bufferIdx);
|
||||||
|
bufferIdx += u8Filler.byteLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bufferIdx < length) {
|
||||||
|
const slice = new Uint8Array(u8Filler.buffer, u8Filler.byteOffset, length - bufferIdx);
|
||||||
|
buffer.set(slice, bufferIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
class DummyBlockRNG extends LiteHashDRBG {
|
||||||
|
private repeatBlockCnt: number;
|
||||||
|
private repeatBlock: ArrayBuffer[];
|
||||||
|
|
||||||
|
public constructor(repeatBlock: MaybeBytes[], stateIdx = 0) {
|
||||||
|
super('x');
|
||||||
|
|
||||||
|
this.repeatBlock = [];
|
||||||
|
for (const rawBlock of repeatBlock) {
|
||||||
|
const block = convertBytesLikeToArrayBuffer(rawBlock);
|
||||||
|
if (block.byteLength !== bufferByteSize) {
|
||||||
|
throw new Error;
|
||||||
|
}
|
||||||
|
this.repeatBlock.push(block);
|
||||||
|
}
|
||||||
|
this.repeatBlockCnt = this.repeatBlock.length;
|
||||||
|
this.stateIdx = stateIdx;
|
||||||
|
this.bufferIdx = 0;
|
||||||
|
this.genNextBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected genNextBlock() {
|
||||||
|
if (!this.repeatBlock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.buffer = this.repeatBlock[this.stateIdx];
|
||||||
|
this.bufferIdx = 0;
|
||||||
|
this.stateIdx = (this.stateIdx + 1) % this.repeatBlockCnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fixedKey = 'HelloWorld';
|
||||||
|
|
||||||
|
|
||||||
|
describe('RNGtestDummy', () => {
|
||||||
|
const rng = new DummyBlockRNG([
|
||||||
|
fillBlock('', "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff")
|
||||||
|
]);
|
||||||
|
|
||||||
|
it('BasicConvert', () => {
|
||||||
|
assert.equal(toBytes("\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff", false).length, 16);
|
||||||
|
});
|
||||||
|
it('SimpleByte', () => {
|
||||||
|
assert.equalBytes(toBytes("\x00", false), rng.nextBytes(1), 'b1');
|
||||||
|
assert.equalBytes(toBytes("\x11\x22", false), rng.nextBytes(2), 'b2');
|
||||||
|
assert.equalBytes(toBytes("\x33\x44\x55", false), rng.nextBytes(3), 'b3');
|
||||||
|
assert.equalBytes(toBytes("\x66\x77\x88\x99", false), rng.nextBytes(4), 'b4');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('OverflowBlock', () => {
|
||||||
|
for (const idx in _.range(16)) {
|
||||||
|
assert.equalBytes(
|
||||||
|
toBytes("\xaa\xbb\xcc\xdd\xee\xff\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99", false),
|
||||||
|
rng.nextBytes(16)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('MultiBlock', () => {
|
||||||
|
assert.equalBytes(
|
||||||
|
fillBlock('', "\xaa\xbb\xcc\xdd\xee\xff\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99", bufferByteSize * 2),
|
||||||
|
rng.nextBytes(bufferByteSize * 2)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('bitTest', () => {
|
||||||
|
assert.equalBytes(toBytes("\x00", false), rng.nextBits(1)); //aa
|
||||||
|
assert.equalBytes(toBytes("\x01", false), rng.nextBits(1)); //bb
|
||||||
|
assert.equalBytes(toBytes("\xcc", false), rng.nextBits(8)); //cc
|
||||||
|
assert.equalBytes(toBytes("\xdd\x02", false), rng.nextBits(10)); //ddee
|
||||||
|
assert.equalBytes(toBytes("\x7f", false), rng.nextBits(7)); //ff
|
||||||
|
assert.equalBytes(toBytes("\x00\x11\x22\x33\x44\x55\x06", false), rng.nextBits(53));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('int', () => {
|
||||||
|
assert.equal(0x77, rng.nextInt(0xff));
|
||||||
|
assert.equal(0x9988, rng.nextInt((1 << 16) - 1));
|
||||||
|
assert.equal(0xddccbbaa, rng.nextInt(0xffffffff));
|
||||||
|
assert.equal(0x0433221100ffee, rng.nextInt());
|
||||||
|
assert.equal(0x05, rng.nextInt(0x0f)); //55
|
||||||
|
assert.equal(0x06, rng.nextInt(0x12)); //66
|
||||||
|
assert.equal(0x08, rng.nextInt(99)); //77(119 -> 7bit) -> 88(136 -> 8bit -> 8)
|
||||||
|
assert.equal(0x99, rng.nextInt(0x99)); //99
|
||||||
|
assert.equal(0xaa, rng.nextInt(0xaa)); //aa (fit Max)
|
||||||
|
});
|
||||||
|
|
||||||
|
it('float', () => {
|
||||||
|
const floatMax = 2 ** 53;
|
||||||
|
const fa = rng.nextFloat1();
|
||||||
|
assert.equal(0x1100ffeeddccbb / floatMax, fa);
|
||||||
|
assert.isTrue(0.5313720384 > fa);
|
||||||
|
assert.isTrue(0.5313720383 < fa);
|
||||||
|
const fb = rng.nextFloat1();
|
||||||
|
assert.equal(0x08776655443322 / floatMax, fb);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('RNGexpectedError', ()=>{
|
||||||
|
const rng = new LiteHashDRBG(fixedKey);
|
||||||
|
it('nextBits0', ()=>{
|
||||||
|
assert.throw(()=>rng.nextBits(0));
|
||||||
|
});
|
||||||
|
it('nextBits-1', ()=>{
|
||||||
|
assert.throw(()=>rng.nextBits(-1));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('nextBytes0', ()=>{
|
||||||
|
assert.throw(()=>rng.nextBytes(0));
|
||||||
|
});
|
||||||
|
it('nextBytes-1', ()=>{
|
||||||
|
assert.throw(()=>rng.nextBytes(-1));
|
||||||
|
});
|
||||||
|
|
||||||
|
const randUtil = new RandUtil(rng);
|
||||||
|
it('utilEmptyChoice', ()=>{
|
||||||
|
assert.throw(()=>randUtil.choice([]));
|
||||||
|
});
|
||||||
|
it('utilEmptyChoiceUsingWeight', ()=>{
|
||||||
|
assert.throw(()=>randUtil.choiceUsingWeight({}));
|
||||||
|
});
|
||||||
|
it('utilEmptyChoiceUsingWeightPair', ()=>{
|
||||||
|
assert.throw(()=>randUtil.choiceUsingWeightPair([]));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('RNGAcceptable', ()=>{
|
||||||
|
const rng = new LiteHashDRBG(fixedKey);
|
||||||
|
it('RNG', ()=>{
|
||||||
|
rng.nextInt(0);
|
||||||
|
rng.nextInt(2 ** 53 - 1);
|
||||||
|
rng.nextBytes(65);
|
||||||
|
rng.nextBits(512);
|
||||||
|
});
|
||||||
|
|
||||||
|
const randUtil = new RandUtil(rng);
|
||||||
|
it('RandUtil', ()=>{
|
||||||
|
randUtil.choice([0, 0, 0]);
|
||||||
|
randUtil.choiceUsingWeight({
|
||||||
|
0: 0,
|
||||||
|
1: -1
|
||||||
|
});
|
||||||
|
randUtil.choiceUsingWeightPair([
|
||||||
|
[0, 0],
|
||||||
|
[1, 0],
|
||||||
|
[2, -2]
|
||||||
|
]);
|
||||||
|
randUtil.nextBool(1.1);
|
||||||
|
randUtil.nextBool(-0.1);
|
||||||
|
randUtil.shuffle([]);
|
||||||
|
randUtil.shuffle([1]);
|
||||||
|
randUtil.nextRange(0, 0);
|
||||||
|
randUtil.nextRangeInt(0, 0);
|
||||||
|
randUtil.nextRange(1, -1);
|
||||||
|
randUtil.nextRangeInt(1, -1);
|
||||||
|
})
|
||||||
|
});
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
export type Bytes = ArrayBuffer | DataView | Uint8Array;
|
||||||
|
export type BytesLike = Bytes | string;
|
||||||
+20
-33
@@ -2,15 +2,14 @@ import { RNG } from "./RNG";
|
|||||||
|
|
||||||
import { sha512 } from 'js-sha512';
|
import { sha512 } from 'js-sha512';
|
||||||
|
|
||||||
//Buffer를 써도 된다면 Buffer가 최선이지만..
|
import { convertBytesLikeToUint8Array } from "./convertBytesLikeToUint8Array";
|
||||||
type Bytes = ArrayBuffer | DataView | Uint8Array;
|
import { BytesLike } from "./BytesLike";
|
||||||
type MaybeBytes = Bytes | string;
|
|
||||||
|
|
||||||
const maxRngSupportBit = 53;
|
const maxRngSupportBit = 53;
|
||||||
const maxInt = 0x1f_ffff_ffff_ffff; // NOTE: b 0, 10000110011, 11...11
|
const maxInt = 0x1f_ffff_ffff_ffff; // NOTE: b 0, 10000110011, 11...11
|
||||||
const maxIntMore1 = 0x20_0000_0000_0000n; //NOTE: b 0, 10000110100, 00...00
|
const maxIntMore1 = 0x20_0000_0000_0000n; //NOTE: b 0, 10000110100, 00...00
|
||||||
const maxIntMore1f = Number(maxIntMore1);
|
const maxIntMore1f = Number(maxIntMore1);
|
||||||
const bufferByteSize = 512 / 8; //SHA512
|
export const bufferByteSize = 512 / 8; //SHA512
|
||||||
|
|
||||||
const intBitMapMask = new Map([
|
const intBitMapMask = new Map([
|
||||||
[0x1n, 1],
|
[0x1n, 1],
|
||||||
@@ -85,7 +84,7 @@ export class LiteHashDRBG implements RNG {
|
|||||||
protected hq: DataView;
|
protected hq: DataView;
|
||||||
protected hqIdxPos: number;
|
protected hqIdxPos: number;
|
||||||
|
|
||||||
public constructor(protected seed: MaybeBytes, protected stateIdx = 0, bufferIdx = 0) {
|
public constructor(protected seed: BytesLike, protected stateIdx = 0, bufferIdx = 0) {
|
||||||
if(bufferIdx < 0){
|
if(bufferIdx < 0){
|
||||||
throw new Error(`bufferIdx ${bufferIdx} < 0`);
|
throw new Error(`bufferIdx ${bufferIdx} < 0`);
|
||||||
}
|
}
|
||||||
@@ -96,18 +95,7 @@ export class LiteHashDRBG implements RNG {
|
|||||||
throw new Error(`stateIdx ${stateIdx} < 0`);
|
throw new Error(`stateIdx ${stateIdx} < 0`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const seedU8 = (() => {
|
const seedU8 = convertBytesLikeToUint8Array(seed);
|
||||||
if (seed instanceof Uint8Array) {
|
|
||||||
return seed;
|
|
||||||
}
|
|
||||||
if (seed instanceof ArrayBuffer) {
|
|
||||||
return new Uint8Array(seed);
|
|
||||||
}
|
|
||||||
if (typeof(seed) === 'string'){
|
|
||||||
return (new TextEncoder()).encode(seed);
|
|
||||||
}
|
|
||||||
return new Uint8Array(seed.buffer);
|
|
||||||
})();
|
|
||||||
const hqBuffer = new ArrayBuffer(seedU8.byteLength + 4);
|
const hqBuffer = new ArrayBuffer(seedU8.byteLength + 4);
|
||||||
const hqU8 = new Uint8Array(hqBuffer);
|
const hqU8 = new Uint8Array(hqBuffer);
|
||||||
|
|
||||||
@@ -131,7 +119,7 @@ export class LiteHashDRBG implements RNG {
|
|||||||
return maxInt;
|
return maxInt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public nextBytes(bytes: number, baseBytes?: number): ArrayBuffer {
|
public nextBytes(bytes: number, baseBytes?: number): Uint8Array {
|
||||||
bytes |= 0;
|
bytes |= 0;
|
||||||
if (bytes <= 0) {
|
if (bytes <= 0) {
|
||||||
throw new Error(`${bytes} <= 0`);
|
throw new Error(`${bytes} <= 0`);
|
||||||
@@ -139,17 +127,17 @@ export class LiteHashDRBG implements RNG {
|
|||||||
|
|
||||||
if (this.bufferIdx + bytes <= bufferByteSize) {
|
if (this.bufferIdx + bytes <= bufferByteSize) {
|
||||||
if(baseBytes === undefined || bytes >= baseBytes){
|
if(baseBytes === undefined || bytes >= baseBytes){
|
||||||
const result = this.buffer.slice(this.bufferIdx, bytes);
|
const result = this.buffer.slice(this.bufferIdx, this.bufferIdx + bytes);
|
||||||
this.bufferIdx += bytes;
|
this.bufferIdx += bytes;
|
||||||
if (this.bufferIdx === bufferByteSize) {
|
if (this.bufferIdx === bufferByteSize) {
|
||||||
this.genNextBlock();
|
this.genNextBlock();
|
||||||
}
|
}
|
||||||
return result;
|
return new Uint8Array(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = new ArrayBuffer(Math.max(bytes, baseBytes));
|
const resultBuffer = new ArrayBuffer(Math.max(bytes, baseBytes));
|
||||||
const resultU8 = new Uint8Array(result);
|
const result = new Uint8Array(resultBuffer);
|
||||||
resultU8.set(new Uint8Array(this.buffer, this.bufferIdx, bytes));
|
result.set(new Uint8Array(this.buffer, this.bufferIdx, bytes));
|
||||||
this.bufferIdx += bytes;
|
this.bufferIdx += bytes;
|
||||||
if( this.bufferIdx === bufferByteSize){
|
if( this.bufferIdx === bufferByteSize){
|
||||||
this.genNextBlock();
|
this.genNextBlock();
|
||||||
@@ -157,16 +145,16 @@ export class LiteHashDRBG implements RNG {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = new ArrayBuffer(baseBytes ? Math.max(bytes, baseBytes) : bytes);
|
const resultBuffer = new ArrayBuffer(baseBytes ? Math.max(bytes, baseBytes) : bytes);
|
||||||
const resultU8 = new Uint8Array(result);
|
const result = new Uint8Array(resultBuffer);
|
||||||
|
|
||||||
resultU8.set(new Uint8Array(this.buffer, this.bufferIdx));
|
result.set(new Uint8Array(this.buffer, this.bufferIdx));
|
||||||
let offset = bufferByteSize - this.bufferIdx;
|
let offset = bufferByteSize - this.bufferIdx;
|
||||||
let remain = bytes - offset;
|
let remain = bytes - offset;
|
||||||
|
|
||||||
while (remain > bufferByteSize) {
|
while (remain > bufferByteSize) {
|
||||||
this.genNextBlock();
|
this.genNextBlock();
|
||||||
resultU8.set(new Uint8Array(this.buffer), offset);
|
result.set(new Uint8Array(this.buffer), offset);
|
||||||
offset += bufferByteSize;
|
offset += bufferByteSize;
|
||||||
remain -= bufferByteSize;
|
remain -= bufferByteSize;
|
||||||
}
|
}
|
||||||
@@ -176,12 +164,12 @@ export class LiteHashDRBG implements RNG {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
resultU8.set(new Uint8Array(this.buffer, 0, remain), offset);
|
result.set(new Uint8Array(this.buffer, 0, remain), offset);
|
||||||
this.bufferIdx = remain;
|
this.bufferIdx = remain;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public nextBits(bits: number, baseBytes?: number): ArrayBuffer {
|
public nextBits(bits: number, baseBytes?: number): Uint8Array {
|
||||||
bits |= 0;
|
bits |= 0;
|
||||||
const bytes = (bits + 7) >> 3;
|
const bytes = (bits + 7) >> 3;
|
||||||
const headBits = bits & 0x7;
|
const headBits = bits & 0x7;
|
||||||
@@ -191,14 +179,13 @@ export class LiteHashDRBG implements RNG {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const resultU8 = new Uint8Array(result);
|
result[bytes - 1] &= 0xff >> (8 - headBits);
|
||||||
resultU8[bytes - 1] &= 0xff >> (8 - headBits);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected _nextInt(bits: number): bigint{
|
protected _nextInt(bits: number): bigint{
|
||||||
const buffer = this.nextBits(bits, 8);
|
const buffer = this.nextBits(bits, 8);
|
||||||
const dataView = new DataView(buffer);
|
const dataView = new DataView(buffer.buffer);
|
||||||
return dataView.getBigUint64(0, true);
|
return dataView.getBigUint64(0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,7 +226,7 @@ export class LiteHashDRBG implements RNG {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static build(seed: MaybeBytes, stateIdx = 0): LiteHashDRBG{
|
public static build(seed: BytesLike, stateIdx = 0): LiteHashDRBG{
|
||||||
return new LiteHashDRBG(seed, stateIdx);
|
return new LiteHashDRBG(seed, stateIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -5,8 +5,8 @@ export interface RNG {
|
|||||||
*/
|
*/
|
||||||
getMaxInt(): number;
|
getMaxInt(): number;
|
||||||
|
|
||||||
nextBytes(bytes: number): ArrayBuffer;
|
nextBytes(bytes: number): Uint8Array;
|
||||||
nextBits(bits: number): ArrayBuffer;
|
nextBits(bits: number): Uint8Array;
|
||||||
|
|
||||||
nextInt(max?: number): number;
|
nextInt(max?: number): number;
|
||||||
nextFloat1(): number;
|
nextFloat1(): number;
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { BytesLike } from "./BytesLike";
|
||||||
|
|
||||||
|
export function convertBytesLikeToArrayBuffer(data: BytesLike, encodeUTF8 = true): ArrayBuffer{
|
||||||
|
if (data instanceof ArrayBuffer) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
if (data instanceof Uint8Array) {
|
||||||
|
return data.buffer;
|
||||||
|
}
|
||||||
|
if (typeof(data) === 'string'){
|
||||||
|
if(encodeUTF8){
|
||||||
|
return (new TextEncoder()).encode(data);
|
||||||
|
}
|
||||||
|
return new Uint8Array(data.split('').map(s=>s.codePointAt(0) as number));
|
||||||
|
}
|
||||||
|
return data.buffer;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { BytesLike } from "./BytesLike";
|
||||||
|
|
||||||
|
export function convertBytesLikeToUint8Array(data: BytesLike, encodeUTF8 = true): Uint8Array {
|
||||||
|
if (data instanceof Uint8Array) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
if (data instanceof ArrayBuffer) {
|
||||||
|
return new Uint8Array(data);
|
||||||
|
}
|
||||||
|
if (typeof (data) === 'string') {
|
||||||
|
if(encodeUTF8){
|
||||||
|
return (new TextEncoder()).encode(data);
|
||||||
|
}
|
||||||
|
return new Uint8Array(data.split('').map(s=>s.codePointAt(0) as number));
|
||||||
|
}
|
||||||
|
return new Uint8Array(data.buffer);
|
||||||
|
}
|
||||||
+3
-1
@@ -6,7 +6,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "npm-run-all test-php-gateway test-ts",
|
"test": "npm-run-all test-php-gateway test-ts",
|
||||||
"test-php-gateway": "vendor/bin/phpunit --bootstrap vendor/autoload.php tests",
|
"test-php-gateway": "vendor/bin/phpunit --bootstrap vendor/autoload.php tests",
|
||||||
"test-ts": "node --loader ts-node/esm ./node_modules/.bin/mocha hwe/test-ts/**/*.test.ts",
|
"test-ts": "mocha",
|
||||||
"build": "webpack",
|
"build": "webpack",
|
||||||
"buildDev": "webpack --mode=development",
|
"buildDev": "webpack --mode=development",
|
||||||
"watch": "webpack watch --mode=development",
|
"watch": "webpack watch --mode=development",
|
||||||
@@ -77,6 +77,7 @@
|
|||||||
"babel-preset-modern-browsers": "^15.0.2",
|
"babel-preset-modern-browsers": "^15.0.2",
|
||||||
"bootswatch": "^5.1.3",
|
"bootswatch": "^5.1.3",
|
||||||
"chai": "^4.3.6",
|
"chai": "^4.3.6",
|
||||||
|
"chai-bytes": "^0.1.2",
|
||||||
"clean-terminal-webpack-plugin": "^3.0.0",
|
"clean-terminal-webpack-plugin": "^3.0.0",
|
||||||
"css-loader": "^6.6.0",
|
"css-loader": "^6.6.0",
|
||||||
"cssnano": "^5.0.17",
|
"cssnano": "^5.0.17",
|
||||||
@@ -95,6 +96,7 @@
|
|||||||
"sass-loader": "^12.6.0",
|
"sass-loader": "^12.6.0",
|
||||||
"style-loader": "^3.3.1",
|
"style-loader": "^3.3.1",
|
||||||
"ts-node": "^10.6.0",
|
"ts-node": "^10.6.0",
|
||||||
|
"tsconfig-paths": "^3.13.0",
|
||||||
"typescript": "^4.5.5",
|
"typescript": "^4.5.5",
|
||||||
"url-loader": "^4.1.1",
|
"url-loader": "^4.1.1",
|
||||||
"vue-eslint-parser": "^8.2.0",
|
"vue-eslint-parser": "^8.2.0",
|
||||||
|
|||||||
Reference in New Issue
Block a user