Commit 3a84cbd5 authored by Ahmet Turan Koçak's avatar Ahmet Turan Koçak
Browse files

Initial commit

parents
{"version":3,"file":"Constants.d.ts","sourceRoot":"","sources":["../src/utils/Constants.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,oBAAY,UAAU;IAClB,GAAG,QAAQ;IACX,IAAI,SAAS;CAChB;AAED,oBAAY,UAAU;IAClB,mBAAmB,MAAM;IACzB,iBAAiB,MAAM;IACvB,QAAQ,MAAM;IACd,wBAAwB,MAAM;IAC9B,sBAAsB,MAAM;IAC5B,wBAAwB,MAAM;IAC9B,sBAAsB,MAAM;CAC/B;AAED,oBAAY,WAAW;IACnB,mBAAmB,MAAM;IACzB,iBAAiB,MAAM;IACvB,YAAY,MAAM;CACrB;AAED;;GAEG;AACH,eAAO,MAAM,2BAA2B,gBAAgB,CAAC;AAEzD;;GAEG;AACH,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC;;GAEG;AACH,eAAO,MAAM,IAAI;;CAEhB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,OAAO;;CAGnB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,KAAK;;;CAGjB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,SAAS;;;;;;CAMrB,CAAC;AAEF;;;;;;GAMG;AACH,oBAAY,KAAK;IACb,kBAAkB,KAAK;IACvB,8BAA8B,MAAM;IACpC,wBAAwB,MAAM;IAC9B,8BAA8B,MAAM;IACpC,kBAAkB,MAAM;IACxB,0BAA0B,MAAM;CACnC;AAED;;GAEG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;CAWxB,CAAC;AAEF,eAAO,MAAM,yBAAyB;;;CAGrC,CAAC"}
\ No newline at end of file
/// <reference types="node" />
export declare class EncodingUtils {
/**
* 'utf8': Multibyte encoded Unicode characters. Many web pages and other document formats use UTF-8.
* 'base64': Base64 encoding.
*
* @param str text
*/
static base64Encode(str: string, encoding?: BufferEncoding): string;
/**
* encode a URL
* @param str
*/
static base64EncodeUrl(str: string, encoding?: BufferEncoding): string;
/**
* 'utf8': Multibyte encoded Unicode characters. Many web pages and other document formats use UTF-8.
* 'base64': Base64 encoding.
*
* @param base64Str Base64 encoded text
*/
static base64Decode(base64Str: string): string;
/**
* @param base64Str Base64 encoded Url
*/
static base64DecodeUrl(base64Str: string): string;
}
//# sourceMappingURL=EncodingUtils.d.ts.map
\ No newline at end of file
{"version":3,"file":"EncodingUtils.d.ts","sourceRoot":"","sources":["../src/utils/EncodingUtils.ts"],"names":[],"mappings":";AAOA,qBAAa,aAAa;IACtB;;;;;OAKG;IACH,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,cAAc,GAAG,MAAM;IAInE;;;OAGG;IACH,MAAM,CAAC,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,cAAc,GAAG,MAAM;IAOtE;;;;;OAKG;IACH,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAI9C;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;CAOpD"}
\ No newline at end of file
import { NetworkResponse } from "@azure/msal-common";
export declare class NetworkUtils {
static getNetworkResponse<T>(headers: Record<string, string>, body: T, statusCode: number): NetworkResponse<T>;
}
//# sourceMappingURL=NetworkUtils.d.ts.map
\ No newline at end of file
{"version":3,"file":"NetworkUtils.d.ts","sourceRoot":"","sources":["../src/utils/NetworkUtils.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,qBAAa,YAAY;IACrB,MAAM,CAAC,kBAAkB,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,UAAU,EAAE,MAAM,GAAG,eAAe,CAAC,CAAC,CAAC;CAOjH"}
\ No newline at end of file
{
"name": "@azure/msal-node",
"version": "1.14.5",
"author": {
"name": "Microsoft",
"email": "nugetaad@microsoft.com",
"url": "https://www.microsoft.com"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/AzureAD/microsoft-authentication-library-for-js.git"
},
"description": "Microsoft Authentication Library for Node",
"keywords": [
"js",
"ts",
"node",
"AAD",
"msal",
"oauth"
],
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"start": "tsdx watch --tsconfig ./tsconfig.build.json",
"build": "tsdx build --tsconfig ./tsconfig.build.json",
"build:modules:watch": "tsdx watch --verbose",
"test": "tsdx test .*.spec.*",
"test:watch": "tsdx test .*.spec.* --watch",
"test:coverage": "tsdx test .*.spec.* --coverage",
"lint": "cd ../../ && npm run lint:node",
"lint:fix": "npm run lint -- -- --fix",
"build:all": "npm run build:common && npm run build",
"build:common": "cd ../msal-common && npm run build",
"link:localDeps": "npx lerna bootstrap --scope @azure/msal-common --scope @azure/msal-node",
"prepack": "npm run build:all"
},
"beachball": {
"disallowedChangeTypes": [
"major"
]
},
"module": "dist/msal-node.esm.js",
"devDependencies": {
"@microsoft/api-extractor": "^7.19.4",
"@types/jest": "^25.2.3",
"@types/jsonwebtoken": "^8.5.5",
"@types/node": "^13.13.4",
"@types/uuid": "^7.0.0",
"husky": "^4.2.3",
"tsdx": "^0.14.1",
"tslib": "^1.10.0",
"typescript": "^3.8.3",
"yargs": "^17.3.1"
},
"dependencies": {
"@azure/msal-common": "^9.0.1",
"jsonwebtoken": "^8.5.1",
"uuid": "^8.3.0"
},
"engines": {
"node": "10 || 12 || 14 || 16 || 18"
}
,"_resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-1.14.5.tgz"
,"_integrity": "sha512-NcVdMfn8Z3ogN+9RjOSF7uwf2Gki5DEJl0BdDSL83KUAgVAobtkZi5W8EqxbJLrTO/ET0jv5DregrcR5qg2pEA=="
,"_from": "@azure/msal-node@^1.10.0"
}
\ No newline at end of file
root = true
[*]
indent_style = tab;
insert_final_newline = true;
quote_type = auto;
space_after_anonymous_functions = true;
space_after_control_statements = true;
spaces_around_operators = true;
trim_trailing_whitespace = true;
spaces_in_brackets = false;
end_of_line = lf;
[CHANGELOG.md]
indent_style = space
{
"root": true,
"extends": "@ljharb",
"env": {
"es6": true,
},
"rules": {
"array-bracket-newline": 0,
"complexity": 0,
"eqeqeq": [2, "allow-null"],
"func-name-matching": 0,
"id-length": [2, { "min": 1, "max": 40 }],
"max-params": [2, 4],
"max-statements-per-line": [2, { "max": 2 }],
"multiline-comment-style": 0,
"no-magic-numbers": 0,
"new-cap": 0,
"no-extra-parens": 1,
"sort-keys": 0,
},
"overrides": [
{
"files": "GetIntrinsic.js",
"rules": {
"max-statements": 0,
}
},
{
"files": "operations/*",
"rules": {
"max-lines": 0,
},
},
{
"files": [
"operations/deltas.js",
"operations/getOps.js",
"operations/spackle.js",
"operations/years.js",
],
"extends": "@ljharb/eslint-config/node/latest",
"rules": {
"complexity": 0,
"func-style": 0,
"max-lines-per-function": 0,
"max-nested-callbacks": 0,
"max-statements": 0,
"no-magic-numbers": 0,
"no-throw-literal": 0,
},
},
{
"files": "test/**",
"extends": "@ljharb/eslint-config/tests",
"rules": {
"max-len": 0,
"max-lines-per-function": 0,
"no-implicit-coercion": 0,
"no-invalid-this": 1,
},
},
],
}
{
"all": true,
"check-coverage": false,
"reporter": ["text-summary", "text", "html", "json"],
"exclude": [
"coverage",
"operations",
"test"
]
}
'use strict';
var ToNumber = require('./ToNumber');
var ToPrimitive = require('./ToPrimitive');
var Type = require('./Type');
// https://ecma-international.org/ecma-262/6.0/#sec-abstract-equality-comparison
module.exports = function AbstractEqualityComparison(x, y) {
var xType = Type(x);
var yType = Type(y);
if (xType === yType) {
return x === y; // ES6+ specified this shortcut anyways.
}
if (x == null && y == null) {
return true;
}
if (xType === 'Number' && yType === 'String') {
return AbstractEqualityComparison(x, ToNumber(y));
}
if (xType === 'String' && yType === 'Number') {
return AbstractEqualityComparison(ToNumber(x), y);
}
if (xType === 'Boolean') {
return AbstractEqualityComparison(ToNumber(x), y);
}
if (yType === 'Boolean') {
return AbstractEqualityComparison(x, ToNumber(y));
}
if ((xType === 'String' || xType === 'Number' || xType === 'Symbol') && yType === 'Object') {
return AbstractEqualityComparison(x, ToPrimitive(y));
}
if (xType === 'Object' && (yType === 'String' || yType === 'Number' || yType === 'Symbol')) {
return AbstractEqualityComparison(ToPrimitive(x), y);
}
return false;
};
'use strict';
var GetIntrinsic = require('get-intrinsic');
var $Number = GetIntrinsic('%Number%');
var $TypeError = GetIntrinsic('%TypeError%');
var $isNaN = require('../helpers/isNaN');
var $isFinite = require('../helpers/isFinite');
var isPrefixOf = require('../helpers/isPrefixOf');
var ToNumber = require('./ToNumber');
var ToPrimitive = require('./ToPrimitive');
var Type = require('./Type');
// https://262.ecma-international.org/5.1/#sec-11.8.5
// eslint-disable-next-line max-statements
module.exports = function AbstractRelationalComparison(x, y, LeftFirst) {
if (Type(LeftFirst) !== 'Boolean') {
throw new $TypeError('Assertion failed: LeftFirst argument must be a Boolean');
}
var px;
var py;
if (LeftFirst) {
px = ToPrimitive(x, $Number);
py = ToPrimitive(y, $Number);
} else {
py = ToPrimitive(y, $Number);
px = ToPrimitive(x, $Number);
}
var bothStrings = Type(px) === 'String' && Type(py) === 'String';
if (!bothStrings) {
var nx = ToNumber(px);
var ny = ToNumber(py);
if ($isNaN(nx) || $isNaN(ny)) {
return undefined;
}
if ($isFinite(nx) && $isFinite(ny) && nx === ny) {
return false;
}
if (nx === Infinity) {
return false;
}
if (ny === Infinity) {
return true;
}
if (ny === -Infinity) {
return false;
}
if (nx === -Infinity) {
return true;
}
return nx < ny; // by now, these are both nonzero, finite, and not equal
}
if (isPrefixOf(py, px)) {
return false;
}
if (isPrefixOf(px, py)) {
return true;
}
return px < py; // both strings, neither a prefix of the other. shortcut for steps c-f
};
'use strict';
var GetIntrinsic = require('get-intrinsic');
var IsInteger = require('./IsInteger');
var Type = require('./Type');
var MAX_SAFE_INTEGER = require('../helpers/maxSafeInteger');
var isLeadingSurrogate = require('../helpers/isLeadingSurrogate');
var isTrailingSurrogate = require('../helpers/isTrailingSurrogate');
var $TypeError = GetIntrinsic('%TypeError%');
var $charCodeAt = require('call-bind/callBound')('String.prototype.charCodeAt');
// https://ecma-international.org/ecma-262/6.0/#sec-advancestringindex
module.exports = function AdvanceStringIndex(S, index, unicode) {
if (Type(S) !== 'String') {
throw new $TypeError('Assertion failed: `S` must be a String');
}
if (!IsInteger(index) || index < 0 || index > MAX_SAFE_INTEGER) {
throw new $TypeError('Assertion failed: `length` must be an integer >= 0 and <= 2**53');
}
if (Type(unicode) !== 'Boolean') {
throw new $TypeError('Assertion failed: `unicode` must be a Boolean');
}
if (!unicode) {
return index + 1;
}
var length = S.length;
if ((index + 1) >= length) {
return index + 1;
}
var first = $charCodeAt(S, index);
if (!isLeadingSurrogate(first)) {
return index + 1;
}
var second = $charCodeAt(S, index + 1);
if (!isTrailingSurrogate(second)) {
return index + 1;
}
return index + 2;
};
'use strict';
var GetIntrinsic = require('get-intrinsic');
var $ArrayPrototype = GetIntrinsic('%Array.prototype%');
var $RangeError = GetIntrinsic('%RangeError%');
var $SyntaxError = GetIntrinsic('%SyntaxError%');
var $TypeError = GetIntrinsic('%TypeError%');
var IsInteger = require('./IsInteger');
var MAX_ARRAY_LENGTH = Math.pow(2, 32) - 1;
var $setProto = GetIntrinsic('%Object.setPrototypeOf%', true) || (
// eslint-disable-next-line no-proto, no-negated-condition
[].__proto__ !== $ArrayPrototype
? null
: function (O, proto) {
O.__proto__ = proto; // eslint-disable-line no-proto, no-param-reassign
return O;
}
);
// https://ecma-international.org/ecma-262/6.0/#sec-arraycreate
module.exports = function ArrayCreate(length) {
if (!IsInteger(length) || length < 0) {
throw new $TypeError('Assertion failed: `length` must be an integer Number >= 0');
}
if (length > MAX_ARRAY_LENGTH) {
throw new $RangeError('length is greater than (2**32 - 1)');
}
var proto = arguments.length > 1 ? arguments[1] : $ArrayPrototype;
var A = []; // steps 5 - 7, and 9
if (proto !== $ArrayPrototype) { // step 8
if (!$setProto) {
throw new $SyntaxError('ArrayCreate: a `proto` argument that is not `Array.prototype` is not supported in an environment that does not support setting the [[Prototype]]');
}
$setProto(A, proto);
}
if (length !== 0) { // bypasses the need for step 2
A.length = length;
}
/* step 10, the above as a shortcut for the below
OrdinaryDefineOwnProperty(A, 'length', {
'[[Configurable]]': false,
'[[Enumerable]]': false,
'[[Value]]': length,
'[[Writable]]': true
});
*/
return A;
};
'use strict';
var GetIntrinsic = require('get-intrinsic');
var $RangeError = GetIntrinsic('%RangeError%');
var $TypeError = GetIntrinsic('%TypeError%');
var assign = require('object.assign');
var isPropertyDescriptor = require('../helpers/isPropertyDescriptor');
var IsArray = require('./IsArray');
var IsAccessorDescriptor = require('./IsAccessorDescriptor');
var IsDataDescriptor = require('./IsDataDescriptor');
var OrdinaryDefineOwnProperty = require('./OrdinaryDefineOwnProperty');
var OrdinaryGetOwnProperty = require('./OrdinaryGetOwnProperty');
var ToNumber = require('./ToNumber');
var ToString = require('./ToString');
var ToUint32 = require('./ToUint32');
var Type = require('./Type');
// https://ecma-international.org/ecma-262/6.0/#sec-arraysetlength
// eslint-disable-next-line max-statements, max-lines-per-function
module.exports = function ArraySetLength(A, Desc) {
if (!IsArray(A)) {
throw new $TypeError('Assertion failed: A must be an Array');
}
if (!isPropertyDescriptor({
Type: Type,
IsDataDescriptor: IsDataDescriptor,
IsAccessorDescriptor: IsAccessorDescriptor
}, Desc)) {
throw new $TypeError('Assertion failed: Desc must be a Property Descriptor');
}
if (!('[[Value]]' in Desc)) {
return OrdinaryDefineOwnProperty(A, 'length', Desc);
}
var newLenDesc = assign({}, Desc);
var newLen = ToUint32(Desc['[[Value]]']);
var numberLen = ToNumber(Desc['[[Value]]']);
if (newLen !== numberLen) {
throw new $RangeError('Invalid array length');
}
newLenDesc['[[Value]]'] = newLen;
var oldLenDesc = OrdinaryGetOwnProperty(A, 'length');
if (!IsDataDescriptor(oldLenDesc)) {
throw new $TypeError('Assertion failed: an array had a non-data descriptor on `length`');
}
var oldLen = oldLenDesc['[[Value]]'];
if (newLen >= oldLen) {
return OrdinaryDefineOwnProperty(A, 'length', newLenDesc);
}
if (!oldLenDesc['[[Writable]]']) {
return false;
}
var newWritable;
if (!('[[Writable]]' in newLenDesc) || newLenDesc['[[Writable]]']) {
newWritable = true;
} else {
newWritable = false;
newLenDesc['[[Writable]]'] = true;
}
var succeeded = OrdinaryDefineOwnProperty(A, 'length', newLenDesc);
if (!succeeded) {
return false;
}
while (newLen < oldLen) {
oldLen -= 1;
// eslint-disable-next-line no-param-reassign
var deleteSucceeded = delete A[ToString(oldLen)];
if (!deleteSucceeded) {
newLenDesc['[[Value]]'] = oldLen + 1;
if (!newWritable) {
newLenDesc['[[Writable]]'] = false;
OrdinaryDefineOwnProperty(A, 'length', newLenDesc);
return false;
}
}
}
if (!newWritable) {
return OrdinaryDefineOwnProperty(A, 'length', { '[[Writable]]': false });
}
return true;
};
'use strict';
var GetIntrinsic = require('get-intrinsic');
var $Array = GetIntrinsic('%Array%');
var $species = GetIntrinsic('%Symbol.species%', true);
var $TypeError = GetIntrinsic('%TypeError%');
var Get = require('./Get');
var IsArray = require('./IsArray');
var IsConstructor = require('./IsConstructor');
var IsInteger = require('./IsInteger');
var Type = require('./Type');
// https://ecma-international.org/ecma-262/6.0/#sec-arrayspeciescreate
module.exports = function ArraySpeciesCreate(originalArray, length) {
if (!IsInteger(length) || length < 0) {
throw new $TypeError('Assertion failed: length must be an integer >= 0');
}
var len = length === 0 ? 0 : length;
var C;
var isArray = IsArray(originalArray);
if (isArray) {
C = Get(originalArray, 'constructor');
// TODO: figure out how to make a cross-realm normal Array, a same-realm Array
// if (IsConstructor(C)) {
// if C is another realm's Array, C = undefined
// Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(Array))) === null ?
// }
if ($species && Type(C) === 'Object') {
C = Get(C, $species);
if (C === null) {
C = void 0;
}
}
}
if (typeof C === 'undefined') {
return $Array(len);
}
if (!IsConstructor(C)) {
throw new $TypeError('C must be a constructor');
}
return new C(len); // Construct(C, len);
};
'use strict';
var GetIntrinsic = require('get-intrinsic');
var callBound = require('call-bind/callBound');
var $TypeError = GetIntrinsic('%TypeError%');
var IsArray = require('./IsArray');
var $apply = GetIntrinsic('%Reflect.apply%', true) || callBound('%Function.prototype.apply%');
// https://ecma-international.org/ecma-262/6.0/#sec-call
module.exports = function Call(F, V) {
var argumentsList = arguments.length > 2 ? arguments[2] : [];
if (!IsArray(argumentsList)) {
throw new $TypeError('Assertion failed: optional `argumentsList`, if provided, must be a List');
}
return $apply(F, V, argumentsList);
};
'use strict';
var GetIntrinsic = require('get-intrinsic');
var $TypeError = GetIntrinsic('%TypeError%');
var SameValue = require('./SameValue');
var ToNumber = require('./ToNumber');
var ToString = require('./ToString');
var Type = require('./Type');
// https://ecma-international.org/ecma-262/6.0/#sec-canonicalnumericindexstring
module.exports = function CanonicalNumericIndexString(argument) {
if (Type(argument) !== 'String') {
throw new $TypeError('Assertion failed: `argument` must be a String');
}
if (argument === '-0') { return -0; }
var n = ToNumber(argument);
if (SameValue(ToString(n), argument)) { return n; }
return void 0;
};
'use strict';
var GetIntrinsic = require('get-intrinsic');
var callBound = require('call-bind/callBound');
var $fromCharCode = GetIntrinsic('%String.fromCharCode%');
var $TypeError = GetIntrinsic('%TypeError%');
var $charCodeAt = callBound('%String.prototype.charCodeAt%');
var $push = callBound('%Array.prototype.push%');
module.exports = function CharacterRange(A, B) {
if (A.length !== 1 || B.length !== 1) {
throw new $TypeError('Assertion failed: CharSets A and B contain exactly one character');
}
var a = A[0];
var b = B[0];
var i = $charCodeAt(a, 0);
var j = $charCodeAt(b, 0);
if (!(i <= j)) {
throw new $TypeError('Assertion failed: i is not <= j');
}
var arr = [];
for (var k = i; k <= j; k += 1) {
$push(arr, $fromCharCode(k));
}
return arr;
};
'use strict';
var has = require('has');
var assertRecord = require('../helpers/assertRecord');
var IsDataDescriptor = require('./IsDataDescriptor');
var IsGenericDescriptor = require('./IsGenericDescriptor');
var Type = require('./Type');
// https://ecma-international.org/ecma-262/6.0/#sec-completepropertydescriptor
module.exports = function CompletePropertyDescriptor(Desc) {
/* eslint no-param-reassign: 0 */
assertRecord(Type, 'Property Descriptor', 'Desc', Desc);
if (IsGenericDescriptor(Desc) || IsDataDescriptor(Desc)) {
if (!has(Desc, '[[Value]]')) {
Desc['[[Value]]'] = void 0;
}
if (!has(Desc, '[[Writable]]')) {
Desc['[[Writable]]'] = false;
}
} else {
if (!has(Desc, '[[Get]]')) {
Desc['[[Get]]'] = void 0;
}
if (!has(Desc, '[[Set]]')) {
Desc['[[Set]]'] = void 0;
}
}
if (!has(Desc, '[[Enumerable]]')) {
Desc['[[Enumerable]]'] = false;
}
if (!has(Desc, '[[Configurable]]')) {
Desc['[[Configurable]]'] = false;
}
return Desc;
};
'use strict';
var GetIntrinsic = require('get-intrinsic');
var $TypeError = GetIntrinsic('%TypeError%');
var DefineOwnProperty = require('../helpers/DefineOwnProperty');
var FromPropertyDescriptor = require('./FromPropertyDescriptor');
var OrdinaryGetOwnProperty = require('./OrdinaryGetOwnProperty');
var IsDataDescriptor = require('./IsDataDescriptor');
var IsExtensible = require('./IsExtensible');
var IsPropertyKey = require('./IsPropertyKey');
var SameValue = require('./SameValue');
var Type = require('./Type');
// https://ecma-international.org/ecma-262/6.0/#sec-createdataproperty
module.exports = function CreateDataProperty(O, P, V) {
if (Type(O) !== 'Object') {
throw new $TypeError('Assertion failed: Type(O) is not Object');
}
if (!IsPropertyKey(P)) {
throw new $TypeError('Assertion failed: IsPropertyKey(P) is not true');
}
var oldDesc = OrdinaryGetOwnProperty(O, P);
var extensible = !oldDesc || IsExtensible(O);
var nonConfigurable = oldDesc && !oldDesc['[[Configurable]]'];
if (nonConfigurable || !extensible) {
return false;
}
return DefineOwnProperty(
IsDataDescriptor,
SameValue,
FromPropertyDescriptor,
O,
P,
{
'[[Configurable]]': true,
'[[Enumerable]]': true,
'[[Value]]': V,
'[[Writable]]': true
}
);
};
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment