@formo/analytics 1.17.3 → 1.17.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -1
- package/.env.example +0 -1
- package/.github/workflows/ci.yml +0 -50
- package/.github/workflows/release.yml +0 -54
- package/.husky/post-commit +0 -7
- package/.husky/pre-commit +0 -11
- package/.releaserc.js +0 -35
- package/CONTRIBUTING.md +0 -83
- package/scripts/generate-sri.sh +0 -52
- package/src/FormoAnalytics.ts +0 -1031
- package/src/FormoAnalyticsProvider.tsx +0 -84
- package/src/constants/base.ts +0 -6
- package/src/constants/config.ts +0 -660
- package/src/constants/events.ts +0 -21
- package/src/constants/index.ts +0 -3
- package/src/global.d.ts +0 -12
- package/src/index.ts +0 -3
- package/src/lib/event/EventFactory.ts +0 -519
- package/src/lib/event/EventManager.ts +0 -39
- package/src/lib/event/constants.ts +0 -4
- package/src/lib/event/index.ts +0 -3
- package/src/lib/event/type.ts +0 -9
- package/src/lib/event/utils.ts +0 -33
- package/src/lib/fetch.ts +0 -3
- package/src/lib/index.ts +0 -5
- package/src/lib/logger/Logger.ts +0 -115
- package/src/lib/logger/index.ts +0 -2
- package/src/lib/logger/type.ts +0 -14
- package/src/lib/queue/EventQueue.ts +0 -306
- package/src/lib/queue/index.ts +0 -2
- package/src/lib/queue/type.ts +0 -6
- package/src/lib/ramda/internal/_curry1.ts +0 -19
- package/src/lib/ramda/internal/_curry2.ts +0 -37
- package/src/lib/ramda/internal/_curry3.ts +0 -68
- package/src/lib/ramda/internal/_has.ts +0 -3
- package/src/lib/ramda/internal/_isObject.ts +0 -3
- package/src/lib/ramda/internal/_isPlaceholder.ts +0 -5
- package/src/lib/ramda/mergeDeepRight.ts +0 -13
- package/src/lib/ramda/mergeDeepWithKey.ts +0 -22
- package/src/lib/ramda/mergeWithKey.ts +0 -28
- package/src/lib/storage/StorageManager.ts +0 -51
- package/src/lib/storage/built-in/blueprint.ts +0 -17
- package/src/lib/storage/built-in/cookie.ts +0 -60
- package/src/lib/storage/built-in/memory.ts +0 -23
- package/src/lib/storage/built-in/web.ts +0 -57
- package/src/lib/storage/constant.ts +0 -2
- package/src/lib/storage/index.ts +0 -25
- package/src/lib/storage/type.ts +0 -21
- package/src/lib/version.ts +0 -2
- package/src/types/base.ts +0 -120
- package/src/types/events.ts +0 -126
- package/src/types/index.ts +0 -3
- package/src/types/provider.ts +0 -17
- package/src/utils/address.ts +0 -43
- package/src/utils/base.ts +0 -3
- package/src/utils/converter.ts +0 -44
- package/src/utils/generate.ts +0 -16
- package/src/utils/index.ts +0 -4
- package/src/utils/timestamp.ts +0 -9
- package/src/validators/address.ts +0 -69
- package/src/validators/agent.ts +0 -4
- package/src/validators/checks.ts +0 -160
- package/src/validators/index.ts +0 -7
- package/src/validators/network.ts +0 -34
- package/src/validators/object.ts +0 -4
- package/src/validators/string.ts +0 -4
- package/src/validators/uint8array.ts +0 -17
- package/test/lib/events.spec.ts +0 -12
- package/test/utils/address.spec.ts +0 -14
- package/test/utils/converter.spec.ts +0 -31
- package/test/validators/address.spec.ts +0 -15
- package/tsconfig.json +0 -28
- package/webpack.config.ts +0 -23
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { isUint8Array, uint8ArrayToHexString } from "./uint8array";
|
|
2
|
-
import { keccak256 } from "ethereum-cryptography/keccak.js";
|
|
3
|
-
import { utf8ToBytes } from "ethereum-cryptography/utils.js";
|
|
4
|
-
import { ValidInputTypes } from "../types";
|
|
5
|
-
import { isHexStrict } from "./string";
|
|
6
|
-
|
|
7
|
-
export const isAddress = (value: ValidInputTypes, checkChecksum = true) => {
|
|
8
|
-
if (typeof value !== "string" && !isUint8Array(value)) {
|
|
9
|
-
return false;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
let valueToCheck: string;
|
|
13
|
-
|
|
14
|
-
if (isUint8Array(value)) {
|
|
15
|
-
valueToCheck = uint8ArrayToHexString(value);
|
|
16
|
-
} else if (typeof value === "string" && !isHexStrict(value)) {
|
|
17
|
-
valueToCheck = value.toLowerCase().startsWith("0x") ? value : `0x${value}`;
|
|
18
|
-
} else {
|
|
19
|
-
valueToCheck = value;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// check if it has the basic requirements of an address
|
|
23
|
-
if (!/^(0x)?[0-9a-f]{40}$/i.test(valueToCheck)) {
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
// If it's ALL lowercase or ALL upppercase
|
|
27
|
-
if (
|
|
28
|
-
/^(0x|0X)?[0-9a-f]{40}$/.test(valueToCheck) ||
|
|
29
|
-
/^(0x|0X)?[0-9A-F]{40}$/.test(valueToCheck)
|
|
30
|
-
) {
|
|
31
|
-
return true;
|
|
32
|
-
// Otherwise check each case
|
|
33
|
-
}
|
|
34
|
-
return checkChecksum ? checkAddressCheckSum(valueToCheck) : true;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export const checkAddressCheckSum = (data: string): boolean => {
|
|
38
|
-
if (!/^(0x)?[0-9a-f]{40}$/i.test(data)) return false;
|
|
39
|
-
const address = data.slice(2);
|
|
40
|
-
const updatedData = utf8ToBytes(address.toLowerCase());
|
|
41
|
-
|
|
42
|
-
const addressHash = uint8ArrayToHexString(
|
|
43
|
-
keccak256(ensureIfUint8Array(updatedData))
|
|
44
|
-
).slice(2);
|
|
45
|
-
|
|
46
|
-
for (let i = 0; i < 40; i += 1) {
|
|
47
|
-
// the nth letter should be uppercase if the nth digit of casemap is 1
|
|
48
|
-
if (
|
|
49
|
-
(parseInt(addressHash[i], 16) > 7 &&
|
|
50
|
-
address[i].toUpperCase() !== address[i]) ||
|
|
51
|
-
(parseInt(addressHash[i], 16) <= 7 &&
|
|
52
|
-
address[i].toLowerCase() !== address[i])
|
|
53
|
-
) {
|
|
54
|
-
return false;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return true;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
export function ensureIfUint8Array<T = any>(data: T) {
|
|
61
|
-
if (
|
|
62
|
-
!(data instanceof Uint8Array) &&
|
|
63
|
-
(data as { constructor: { name: string } })?.constructor?.name ===
|
|
64
|
-
"Uint8Array"
|
|
65
|
-
) {
|
|
66
|
-
return Uint8Array.from(data as unknown as Uint8Array);
|
|
67
|
-
}
|
|
68
|
-
return data;
|
|
69
|
-
}
|
package/src/validators/agent.ts
DELETED
package/src/validators/checks.ts
DELETED
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A function to check given value is a function
|
|
3
|
-
* @param value input value
|
|
4
|
-
* @returns boolean
|
|
5
|
-
*/
|
|
6
|
-
const isFunction = (value: any): value is Function =>
|
|
7
|
-
typeof value === "function" &&
|
|
8
|
-
Boolean(value.constructor && value.call && value.apply);
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* A function to check given value is a string
|
|
12
|
-
* @param value input value
|
|
13
|
-
* @returns boolean
|
|
14
|
-
*/
|
|
15
|
-
const isString = (value: any): value is string => typeof value === "string";
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* A function to check given value is null or not
|
|
19
|
-
* @param value input value
|
|
20
|
-
* @returns boolean
|
|
21
|
-
*/
|
|
22
|
-
const isNull = (value: any): value is null => value === null;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* A function to check given value is undefined
|
|
26
|
-
* @param value input value
|
|
27
|
-
* @returns boolean
|
|
28
|
-
*/
|
|
29
|
-
const isUndefined = (value: any): value is undefined =>
|
|
30
|
-
typeof value === "undefined";
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* A function to check given value is null or undefined
|
|
34
|
-
* @param value input value
|
|
35
|
-
* @returns boolean
|
|
36
|
-
*/
|
|
37
|
-
const isNullOrUndefined = (value: any): boolean =>
|
|
38
|
-
isNull(value) || isUndefined(value);
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Checks if the input is a BigInt
|
|
42
|
-
* @param value input value
|
|
43
|
-
* @returns True if the input is a BigInt
|
|
44
|
-
*/
|
|
45
|
-
const isBigInt = (value: any): value is bigint => typeof value === "bigint";
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* A function to check given value is defined
|
|
49
|
-
* @param value input value
|
|
50
|
-
* @returns boolean
|
|
51
|
-
*/
|
|
52
|
-
const isDefined = (value: any): boolean => !isUndefined(value);
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* A function to check given value is defined and not null
|
|
56
|
-
* @param value input value
|
|
57
|
-
* @returns boolean
|
|
58
|
-
*/
|
|
59
|
-
const isDefinedAndNotNull = (value: any): boolean => !isNullOrUndefined(value);
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* A function to check given value is defined and not null
|
|
63
|
-
* @param value input value
|
|
64
|
-
* @returns boolean
|
|
65
|
-
*/
|
|
66
|
-
const isDefinedNotNullAndNotEmptyString = (value: any): boolean =>
|
|
67
|
-
isDefinedAndNotNull(value) && value !== "";
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Determines if the input is of type error
|
|
71
|
-
* @param value input value
|
|
72
|
-
* @returns true if the input is of type error else false
|
|
73
|
-
*/
|
|
74
|
-
const isTypeOfError = (value: any): boolean => {
|
|
75
|
-
switch (Object.prototype.toString.call(value)) {
|
|
76
|
-
case "[object Error]":
|
|
77
|
-
case "[object Exception]":
|
|
78
|
-
case "[object DOMException]":
|
|
79
|
-
return true;
|
|
80
|
-
default:
|
|
81
|
-
return value instanceof Error;
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* A function to check given value is an array
|
|
87
|
-
* @param value input value
|
|
88
|
-
* @returns true if the input is of type array else false
|
|
89
|
-
*/
|
|
90
|
-
const isArray = (arg: any): arg is Array<any> => {
|
|
91
|
-
return Array.isArray(arg);
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
const isBoolean = (arg: any): arg is boolean => {
|
|
95
|
-
return typeof arg === "boolean";
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
const isNumber = (arg: any): arg is number => {
|
|
99
|
-
return typeof arg === "number";
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
const isObject = (value: any): value is object => typeof value === "object";
|
|
103
|
-
|
|
104
|
-
const isObjectAndNotNull = (value: any): value is object =>
|
|
105
|
-
!isNull(value) && isObject(value) && !isArray(value);
|
|
106
|
-
|
|
107
|
-
const isRegExp = (arg: any): arg is RegExp => {
|
|
108
|
-
return isObject(arg) && objectToString(arg) === "[object RegExp]";
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
const isDate = (arg: any): arg is Date => {
|
|
112
|
-
return isObject(arg) && objectToString(arg) === "[object Date]";
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
const isError = (arg: any): arg is Error => {
|
|
116
|
-
return (
|
|
117
|
-
isObject(arg) &&
|
|
118
|
-
(objectToString(arg) === "[object Error]" || arg instanceof Error)
|
|
119
|
-
);
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
const isPrimitive = (
|
|
123
|
-
arg: any
|
|
124
|
-
): arg is null | boolean | number | string | symbol | undefined => {
|
|
125
|
-
return (
|
|
126
|
-
arg === null ||
|
|
127
|
-
typeof arg === "boolean" ||
|
|
128
|
-
typeof arg === "number" ||
|
|
129
|
-
typeof arg === "string" ||
|
|
130
|
-
typeof arg === "symbol" || // ES6 symbol
|
|
131
|
-
typeof arg === "undefined"
|
|
132
|
-
);
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
const objectToString = (arg: any) => {
|
|
136
|
-
return Object.prototype.toString.call(arg);
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
export {
|
|
140
|
-
isFunction,
|
|
141
|
-
isString,
|
|
142
|
-
isNull,
|
|
143
|
-
isUndefined,
|
|
144
|
-
isNullOrUndefined,
|
|
145
|
-
isTypeOfError,
|
|
146
|
-
isDefined,
|
|
147
|
-
isDefinedAndNotNull,
|
|
148
|
-
isDefinedNotNullAndNotEmptyString,
|
|
149
|
-
isBigInt,
|
|
150
|
-
isArray,
|
|
151
|
-
isBoolean,
|
|
152
|
-
isNumber,
|
|
153
|
-
isObject,
|
|
154
|
-
isObjectAndNotNull,
|
|
155
|
-
isRegExp,
|
|
156
|
-
isDate,
|
|
157
|
-
isError,
|
|
158
|
-
isPrimitive,
|
|
159
|
-
objectToString,
|
|
160
|
-
};
|
package/src/validators/index.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
const objectToString = Object.prototype.toString;
|
|
2
|
-
|
|
3
|
-
const isError = (value: any) => objectToString.call(value) === "[object Error]";
|
|
4
|
-
|
|
5
|
-
const errorMessages = new Set([
|
|
6
|
-
"network error", // Chrome
|
|
7
|
-
"Failed to fetch", // Chrome
|
|
8
|
-
"NetworkError when attempting to fetch resource.", // Firefox
|
|
9
|
-
"The Internet connection appears to be offline.", // Safari 16
|
|
10
|
-
"Load failed", // Safari 17+
|
|
11
|
-
"Network request failed", // `cross-fetch`
|
|
12
|
-
"fetch failed", // Undici (Node.js)
|
|
13
|
-
"terminated", // Undici (Node.js)
|
|
14
|
-
]);
|
|
15
|
-
|
|
16
|
-
export function isNetworkError(error: any) {
|
|
17
|
-
const isValid =
|
|
18
|
-
error &&
|
|
19
|
-
isError(error) &&
|
|
20
|
-
error.name === "TypeError" &&
|
|
21
|
-
typeof error.message === "string";
|
|
22
|
-
|
|
23
|
-
if (!isValid) {
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// We do an extra check for Safari 17+ as it has a very generic error message.
|
|
28
|
-
// Network errors in Safari have no stack.
|
|
29
|
-
if (error.message === "Load failed") {
|
|
30
|
-
return error.stack === undefined;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return errorMessages.has(error.message);
|
|
34
|
-
}
|
package/src/validators/object.ts
DELETED
package/src/validators/string.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export function isUint8Array(data: unknown | Uint8Array): data is Uint8Array {
|
|
2
|
-
return (
|
|
3
|
-
data instanceof Uint8Array ||
|
|
4
|
-
(data as { constructor: { name: string } })?.constructor?.name ===
|
|
5
|
-
"Uint8Array" ||
|
|
6
|
-
(data as { constructor: { name: string } })?.constructor?.name === "Buffer"
|
|
7
|
-
);
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function uint8ArrayToHexString(uint8Array: Uint8Array): string {
|
|
11
|
-
let hexString = "0x";
|
|
12
|
-
for (const e of uint8Array as any) {
|
|
13
|
-
const hex = e.toString(16);
|
|
14
|
-
hexString += hex.length === 1 ? `0${hex}` : hex;
|
|
15
|
-
}
|
|
16
|
-
return hexString;
|
|
17
|
-
}
|
package/test/lib/events.spec.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { describe, it } from "mocha";
|
|
2
|
-
import { expect } from "chai";
|
|
3
|
-
import { getCookieDomain } from "../../src/lib/event/utils";
|
|
4
|
-
|
|
5
|
-
describe("getCookieDomain", () => {
|
|
6
|
-
it("should return the cookie domain format", () => {
|
|
7
|
-
expect(getCookieDomain("192.168.0.1")).to.equal("");
|
|
8
|
-
expect(getCookieDomain("localhost:3000")).to.equal("");
|
|
9
|
-
expect(getCookieDomain("example.com")).to.equal(".example.com");
|
|
10
|
-
expect(getCookieDomain("www.example.com")).to.equal(".example.com");
|
|
11
|
-
});
|
|
12
|
-
});
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { describe, it } from "mocha";
|
|
2
|
-
import { expect } from "chai";
|
|
3
|
-
import { toChecksumAddress } from "../../src/utils";
|
|
4
|
-
|
|
5
|
-
describe("toChecksumAddress", () => {
|
|
6
|
-
it("should return the checksum of the address", () => {
|
|
7
|
-
expect(
|
|
8
|
-
toChecksumAddress("0x82827Bc8342a16b681AfbA6B979E3D1aE5F28a0e")
|
|
9
|
-
).to.equal("0x82827Bc8342a16b681AfbA6B979E3D1aE5F28a0e");
|
|
10
|
-
expect(
|
|
11
|
-
toChecksumAddress("0x82827bc8342a16b681afba6b979e3d1ae5f28a0e")
|
|
12
|
-
).to.equal("0x82827Bc8342a16b681AfbA6B979E3D1aE5F28a0e");
|
|
13
|
-
});
|
|
14
|
-
});
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { describe, it } from "mocha";
|
|
2
|
-
import { expect } from "chai";
|
|
3
|
-
import { toSnakeCase } from "../../src/utils";
|
|
4
|
-
|
|
5
|
-
describe("toSnakeCase", () => {
|
|
6
|
-
it("should convert object keys to snake case", () => {
|
|
7
|
-
expect(
|
|
8
|
-
toSnakeCase({ chainId: "12345", hashMessage: "John Doe" })
|
|
9
|
-
).to.deep.equal({
|
|
10
|
-
chain_id: "12345",
|
|
11
|
-
hash_message: "John Doe",
|
|
12
|
-
});
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it("should convert object keys to snake case, omitting keys in the omitKeys array", () => {
|
|
16
|
-
expect(
|
|
17
|
-
toSnakeCase(
|
|
18
|
-
{
|
|
19
|
-
chainId: "12345",
|
|
20
|
-
hashMessage: "John Doe",
|
|
21
|
-
"user-agent": "Mozilla/5.0",
|
|
22
|
-
},
|
|
23
|
-
["user-agent"]
|
|
24
|
-
)
|
|
25
|
-
).to.deep.equal({
|
|
26
|
-
chain_id: "12345",
|
|
27
|
-
hash_message: "John Doe",
|
|
28
|
-
"user-agent": "Mozilla/5.0",
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
});
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { expect } from "chai";
|
|
2
|
-
import { describe, it } from "mocha";
|
|
3
|
-
import { isAddress } from "../../src/validators";
|
|
4
|
-
|
|
5
|
-
describe("isAddress", () => {
|
|
6
|
-
it("should return true if the input is a valid ethereum address", () => {
|
|
7
|
-
expect(isAddress("0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC")).to.equal(
|
|
8
|
-
true
|
|
9
|
-
);
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it("should return false otherwise", () => {
|
|
13
|
-
expect(isAddress("o")).to.equal(false);
|
|
14
|
-
});
|
|
15
|
-
});
|
package/tsconfig.json
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"jsx": "react-jsx",
|
|
4
|
-
"outDir": "dist/cjs",
|
|
5
|
-
"allowJs": false,
|
|
6
|
-
"esModuleInterop": true,
|
|
7
|
-
"resolveJsonModule": true,
|
|
8
|
-
"skipLibCheck": true,
|
|
9
|
-
"strict": true,
|
|
10
|
-
"module": "commonjs",
|
|
11
|
-
"target": "es5",
|
|
12
|
-
"lib": ["es2015", "dom"],
|
|
13
|
-
"moduleResolution": "node",
|
|
14
|
-
"declaration": true,
|
|
15
|
-
"noImplicitThis": false,
|
|
16
|
-
"noImplicitAny": true,
|
|
17
|
-
"noUnusedParameters": true,
|
|
18
|
-
"declarationMap": true,
|
|
19
|
-
"composite": true,
|
|
20
|
-
"incremental": true,
|
|
21
|
-
"sourceMap": true,
|
|
22
|
-
"isolatedModules": true
|
|
23
|
-
},
|
|
24
|
-
"ts-node": {
|
|
25
|
-
"files": true
|
|
26
|
-
},
|
|
27
|
-
"include": ["src", "test"]
|
|
28
|
-
}
|
package/webpack.config.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import path from "path";
|
|
2
|
-
|
|
3
|
-
module.exports = {
|
|
4
|
-
entry: {
|
|
5
|
-
bundle: "./src/index.ts",
|
|
6
|
-
"bundle.min": "./src/index.ts",
|
|
7
|
-
},
|
|
8
|
-
output: {
|
|
9
|
-
path: path.resolve(__dirname, "dist"),
|
|
10
|
-
filename: "index.umd.min.js",
|
|
11
|
-
libraryTarget: "umd",
|
|
12
|
-
library: "FormoAnalytics",
|
|
13
|
-
libraryExport: "FormoAnalytics",
|
|
14
|
-
umdNamedDefine: true,
|
|
15
|
-
},
|
|
16
|
-
resolve: {
|
|
17
|
-
extensions: [".ts", ".tsx", ".js"],
|
|
18
|
-
},
|
|
19
|
-
devtool: "source-map",
|
|
20
|
-
module: {
|
|
21
|
-
rules: [{ test: /\.tsx?$/, loader: "ts-loader" }],
|
|
22
|
-
},
|
|
23
|
-
};
|